为什么Qt会改变sscan()的行为

Why does Qt change behaviour of sscanf()?

本文关键字:sscan Qt 改变 为什么      更新时间:2023-10-16

我注意到,Qt(4.8)改变了sscanf()的行为。如果没有Qt,sscanf()将照常工作,但如果有,它只需要本地化的字符串。

下面是一个最小化的例子:


不带Qt(纯C++)

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

(给定字符串是5倍char数组,结果正确)


带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

(给定字符串仍然是5倍char-数组,但结果是错误的)


0.83失败时,使用0,83(我的区域设置格式)可以很好地处理Qt,但在没有Qt(默认行为)的情况下会失败。如typeid()所示,没有使用QString,只有普通的旧C(++)字符数组。顺便说一句,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数组字符串和sscanf()调用会受到Qt的影响?我理解为什么QString是本地化的,但破坏sscanf()(以及可能的其他stdio.h函数)对我来说听起来很邪恶

背景:我将一个(非Qt)库链接到一个Qt项目,该库包含代码深处的sscanf()。结果:这个项目中的一些代码失败了,而它在其他地方都有效…(花了一些时间找到原因…)

一般来说,如果您在标准库中获得一个与流或I/O操作有关的函数,它很可能会受到您的区域设置的影响。

这对于sscanf是正确的,在您的情况下,Qt覆盖了您在使用默认C/C++配置时通常获得的默认C locale

你应该使用

setlocale(LC_NUMERIC,"C")

在初始化您的Qt环境之后,在本例中是在QApplication之后。

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

让事情回到你期望的样子。

我怀疑QT会根据您的系统区域设置自动设置区域设置。实际上有一个标准的本地化库。

设置C语言环境会更改本页上列出的一组函数的行为。

但是,请注意,C++流不会自动选择C语言环境,这就是std::stringstream运行正常的原因。

Qt正在调用setlocale来设置C运行时使用您的区域设置。你可以试着用setlocale(LC_ALL,"C")来设置它;但我不确定这会对Qt的其他部分产生什么影响。