Почему Qt изменяет поведение sscanf()?

Я заметил, что Qt (4.8) меняет поведение sscanf(). Без Qt sscanf() работает как обычно, но с помощью он принимает только локализованные строки.

Здесь приведен пример с минимальным значением:


Без Qt (простой С++)

int main(int argc, char *argv[])
{
    float f;
    sscanf("0.83", "%f", &f);

    std::cout << f << "\t-->\t" << typeid("0.83").name() << std::endl;

    return 0;
}

Вывод:

0.83    -->     A5_c

(данная строка представляет собой 5x char -array, результат правильный)


С Qt

int main(int argc, char *argv[])
{
    /*
     * This breaks sscanf() for the whole (!) project
     * and linked libraries too!
     */
    QApplication(argc, argv);

    float f;
    sscanf("0.83", "%f", &f);

    std::cout << f << "\t-->\t" << typeid("0.83").name() << std::endl;

    return 0;
}

Вывод:

0       -->     A5_c

(задана строка 5x char -array, но результат неверен)


В то время как 0.83 не работает, использование 0,83 (мой формат локали) отлично работает с Qt - но не работает без Qt (поведение по умолчанию). Как показано typeid(), там не используется QString - только старые старые C (++) char -arrays. Btw., То же самое происходит с std::string.

Кроме того, использование std::stringstream работает нормально:

std::stringstream ss;
ss << "0.83"; // But the value into the stream
ss >> f;      // Get a float out of it

Результат:

0.83

И вот возникает вопрос: Почему char -array строки и sscanf() вызовы, затронутые Qt? Я понимаю, почему QString локализованы, но нарушение sscanf() (и, возможно, других функций stdio.h) звучит для меня злом.

Фон: я связал библиотеку (не Qt), содержащую sscanf() где-то глубоко в коде, в проекте Qt. Результат: Некоторый код не удался в этом проекте, в то время как он работал везде... (потребовалось некоторое время, чтобы найти причину...)

Ответ 1

В общих чертах, если вы получаете функцию в стандартной библиотеке, которая имеет какое-то отношение к потокам или операциям ввода-вывода, скорее всего, это повлияет на ваши настройки локали.

Это верно для sscanf, и в вашем случае Qt переопределяет значение по умолчанию C locale, которое вы обычно получаете при использовании конфигурации по умолчанию C/С++.

вы должны использовать

setlocale(LC_NUMERIC,"C")

сразу после инициализации вашей среды Qt, в этом случае после QApplication.

https://qt-project.org/doc/qt-5/qcoreapplication.html#locale-settings

чтобы вернуть все, что вы ожидаете.

Ответ 2

Я подозреваю, что QT автоматически устанавливает локаль автоматически на основе вашей системы. Фактически существует стандартная библиотека локализации.

Настройка локали C изменяет поведение набора функций, перечисленных на этой странице.

Обратите внимание, однако, что потоки С++ не автоматически выбирают языковой стандарт C, поэтому ваш std::stringstream ведет себя нормально.

Ответ 3

Qt вызывает setlocale, чтобы установить C runtuime для использования вашей локали. Вы можете попробовать установить его с помощью setlocale (LC_ALL, "C" ); но я не уверен, как это повлияет на остальную часть Qt.