我在当前项目中收到了意外行为。
我使用DICOM库dcmtk
从某些dicom文件中读取信息,并使用Qt
来显示图像。
在信息提取过程中,我必须转换格式为“< 64bit float> \< 64 bit float>”的字段(Dicom Tag PixelSpacing)。我在“\”处拆分为2个字符串,并将字符串转换为double。到目前为止,一切正常。
好吧,差不多:每当我在之前创建一个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
的{{1}}
strtod
分配是否对QApplication
函数执行了某些操作?由于一切都在运行时发生,我不明白如何。
用std::stod
替换stod
可以解决问题......
我正在使用QString::toDouble
。
其他代码依赖项包括gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3), GNU ld (GNU Binutils for Ubuntu) 2.24
,Eigen3
。代码是使用QakeCreator作为IDE的CMake项目构建的。
有谁知道这个问题来自哪里?这是一个Qt错误吗?
答案 0 :(得分:3)
作为DCMTK开发人员之一,即您使用的DICOM工具包,我想知道为什么不直接从DICOM数据元素“Pixel Spacing”检索浮点值,我的意思是代替检索整个字符串(首先包括反斜杠分隔符,然后将其组件转换为单独的浮点数。这样,当前的语言环境设置就没有任何问题。
顺便说一句,由于区域设置问题,我们引入了自己的区域设置独立的OFStandard::atof()辅助函数: - )
答案 1 :(得分:2)
std::stod
行为取决于当前安装的C语言环境。
根据cppreference:
在程序启动期间,在运行任何用户代码之前执行等效的
std::setlocale(LC_ALL, "C");
。
正如@peppe在评论中指出的那样,在QApplication
期间,在Unix上调用构造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函数时导致冲突,例如,在诸如浮点数和字符串之类的数据类型之间进行转换时,因为区域设置之间的符号可能不同。要解决此问题,请在初始化QApplication,QGuiApplication或QCoreApplication后立即调用POSIX函数
setlocale(LC_NUMERIC,"C")
,以将用于数字格式设置的区域设置重置为&#34; C&#34; -locale。
然而,@J.Riesmeier作为DCMTK开发人员之一提供了一个代理人的答案。