Странная ошибка при инициализации QApplication перед использованием std :: stod

Я получаю неожиданное поведение в моем текущем проекте.

Я использую библиотеку DICOM dcmtk читать информацию из некоторых файлов dicom и Qt показать изображения.

При извлечении информации мне приходится конвертировать поля формата<64-разрядное число с плавающей запятой> \<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 функционировать? Поскольку все происходит во время выполнения, я не понимаю, как.

Замена 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, Boost.Python, Код построен с использованием проекта CMake с QtCreator в качестве IDE.

Кто-нибудь знает, откуда эта проблема? Это ошибка Qt?

3

Решение

Будучи одним из разработчиков DCMTK, т.е. используемого вами набора инструментов DICOM, я удивляюсь, почему вы не извлекаете значения с плавающей запятой непосредственно из элемента данных DICOM «Pixel Spacing», я имею в виду вместо извлечения всей строки символов (включая обратную косую черту) разделитель), а затем преобразование его компонентов в отдельные числа с плавающей точкой. Таким образом, не будет никаких проблем с текущими настройками локали.

Кстати, из-за проблемы с настройками локали мы ввели нашу собственную независимую от локали OFStandard :: atof () вспомогательная функция 🙂

3

Другие решения

std::stod поведение зависит от текущей установленной локали C.

В соответствии с cppreference:

Во время запуска программы эквивалент std::setlocale(LC_ALL, "C"); выполняется до запуска любого пользовательского кода.

Как указано @peppe в комментариях, во время QApplicationстроительство setlocale(LC_ALL, ""); вызывается на Unix, таким образом изменяя 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, например, при преобразовании между типами данных, такими как числа с плавающей запятой и строки, поскольку нотация может отличаться в разных локалях. Чтобы обойти эту проблему, вызовите функцию POSIX setlocale(LC_NUMERIC,"C") сразу после инициализации QApplication, QGuiApplication или QCoreApplication для сброса языкового стандарта, используемого для форматирования чисел, в «C» -locale.

тем не мение @ J.Riesmeier предоставил интересный ответ как один из разработчиков DCMTK.

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector