3

我在当前项目中收到意外行为。

我使用 DICOM 库dcmtk从一些 dicom 文件中读取信息,并Qt显示图像。

在信息提取过程中,我必须转换格式为“<64bit float>\<64 bit float>”(Dicom Tag PixelSpacing)的字段。我在“\”处拆分为 2 个字符串,并将字符串转换为双精度。到目前为止,一切正常。

好吧,几乎:每当我在将字符串转换为双精度数之前QApplication创建一个对象时,它都会给我整数而不是双精度数

代码如下所示:

// Faulty situation
Database db;

QApplication app(&argc, argv);
db.fill_from_source(source); // here i get ints instead of doubles

// Rearrange code and recompile:
Database db;
db.fill_from_source(source); // now it gets me doubles.

QApplication app(&argc, argv);

// The fill function looks like this (simplified)
void Database::fill_from_source(const Source& source){

    string s = source.get_pixel_spacing_string();
    vector<string> s2 = split(s, "\\");

    // get the double, that should not be integers!
    double a = stod(s2[0]);
    double b = stod(s2[1]);
}

更让我困惑的是,它确实可以使用 QtCreator 和 GDB 逐步执行代码。但是,当我运行可执行文件时,我再次得到整数。

所以我将问题追溯到stod操作:我从 DICOM 文件中得到了正确的字符串,但是在stod点之后的数字被截断之后。与stdlib's相同的行为strtod

QApplication分配对std::stod函数有影响吗?由于一切都发生在运行时,我不明白如何。

替换stodQString::toDouble解决问题...

我正在使用gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3), GNU ld (GNU Binutils for Ubuntu) 2.24.

其他代码依赖项包括Eigen3, Boost.Python. 代码是使用 CMake 项目和 QtCreator 作为 IDE 构建的。

有谁知道这个问题来自哪里?这是一个Qt错误吗?

4

2 回答 2

3

作为 DCMTK 开发人员之一,即您使用的 DICOM 工具包,我想知道您为什么不直接从 DICOM 数据元素“像素间距”中检索浮点值,而不是检索整个字符串(包括反斜杠)分隔符),然后将其组件转换为单独的浮点数。这样,当前的语言环境设置就完全没有问题。

顺便说一句,由于语言环境设置问题,我们引入了我们自己的独立于语言环境的OFStandard::atof()辅助函数 :-)

于 2016-12-22T10:37:56.643 回答
2

std::stod行为取决于当前安装的 C 语言环境。

根据cppreference

在程序启动期间,在std::setlocale(LC_ALL, "C");运行任何用户代码之前执行等效的 。

正如@peppe 在评论中指出的那样,在 Unix 上调用了 duringQApplication的构造setlocale(LC_ALL, "");,从而改变了std::stod.

您可以存储区域设置并将其设置回如下:

std::string backup(
    // pass a null pointer to query the current C locale without modifying it
    std::setlocale(LC_ALL, nullptr)
);

QApplication app(&argc, argv);

// restore the locale
std::setlocale(LC_ALL, backup.c_str());

编辑:

重读QCoreApplication的文档后,有一段关于语言环境设置的详细描述:

在 Unix/Linux 上,Qt 默认配置为使用系统区域设置。这可能会在使用 POSIX 函数时引起冲突,例如,在浮点数和字符串等数据类型之间进行转换时,因为不同语言环境的表示法可能不同。要解决此问题,请setlocale(LC_NUMERIC,"C")在初始化 QApplication、QGuiApplication 或 QCoreApplication 后立即调用 POSIX 函数以将用于数字格式化的语言环境重置为“C”语言环境。

然而,@J.Riesmeier作为 DCMTK 开发人员之一提供了一个有趣的答案。

于 2016-12-21T19:16:10.643 回答