如何为小数分隔符和位数调整std :: stod(字符串为double)

Ant*_*llo 7 c++ qt locale type-conversion c++11

有没有办法调整std :: stod()以增加(字符串到双)转换中的小数位数并强制它使用美国语言环境?

我有一个Qt应用程序,可以在控制台或gui模式下运行:

if (opt->getFlag( 'c' ) || opt->getFlag( "console" ) ){
  ThreadManager  modelMainThread;
  modelMainThread.runFromConsole(inputFileName,scenarioName);
}
else {
  QApplication app(argc, argv);
  MainWindow mainWin;
  mainWin.show();
  return app.exec();
}
Run Code Online (Sandbox Code Playgroud)

在这个应用程序中,我有一个包含新C++ 11 stod的字符串到double方法:

double s2d ( const string &string_h) const {
  try {
    return stod(string_h);
  } catch (...) {
    if (string_h == "") return 0;
    else {
      cout << "error!" << endl;
    }
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

奇怪的是,在控制台模式下,字符串到双转换需要一个带点作为十进制分隔符的字符串,在gui模式下它需要一个带逗号的字符串.此外,正如我以前使用istringstream:

istringstream totalSString( valueAsString );
totalSString >> valueAsDouble;
Run Code Online (Sandbox Code Playgroud)

我注意到stod会将生成的double缩减为只有3位十进制数,远小于istringstream.

那么有没有办法增加十进制数字的数量并强制std :: stod使用美国语言环境进行转换?

谢谢 :-)

编辑:

如果我尝试这个脚本:

// testing stod() ..
vector<string> numbers;
numbers.push_back("123.1234567890");
numbers.push_back("123.1234");
numbers.push_back("123,1234567890");
numbers.push_back("123,1234");
double outd;
for(uint i=0;i<numbers.size();i++){
    try {
        outd =  stod(numbers[i]);
        cout << "Conversion passed: " << numbers[i] << "  -  " << outd << endl;
    } catch (...) {
        cout << "Conversion DID NOT passed: " << numbers[i] << "  -  " <<endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到了这些结果:

"控制台"模式:

Conversion passed: 123.1234567890  -  123.123
Conversion passed: 123.1234  -  123.123
Conversion passed: 123,1234567890  -  123
Conversion passed: 123,1234  -  123
Run Code Online (Sandbox Code Playgroud)

"gui"模式:

Conversion passed: 123.1234567890  -  123
Conversion passed: 123.1234  -  123
Conversion passed: 123,1234567890  -  123.123
Conversion passed: 123,1234  -  123.123
Run Code Online (Sandbox Code Playgroud)

显然有一些影响stod()行为的东西!

Rus*_*lan 9

std::stod是根据 定义的std::strtod,它继承自 C 标准库。C 函数strtod根据 C 语言环境工作,可通过头文件中的setlocale函数访问<locale.h>

在 C++ 中,C 语言环境仍然可以通过头文件中的std::setlocale函数访问<clocale>,它确实影响std::strtodstd::stod

Qt的QApplication用途std::setlocale来设置用户选择的语言环境。因此,每当您在 GUI Qt 应用程序中使用 C 语言环境相关函数时,您将拥有语言环境相关小数点。

现在,要强制数字的特定语言环境,您可以使用std::setlocale如下。但请注意,这可能会破坏多线程应用程序,因为 C 语言环境是线程全局状态。下面的示例将程序的语言环境临时设置为LC_NUMERIC=C,并在调用 后恢复设置std::stod

#include <iostream>
#include <clocale>
#include <vector>
#include <string>

void test()
{
    for(auto s : {"123.1234567890",
                  "123.1234",
                  "123,1234567890",
                  "123,1234"})
    {
        // Save locale setting
        const std::string oldLocale=std::setlocale(LC_NUMERIC,nullptr);
        // Force '.' as the radix point. If you comment this out,
        // you'll get output similar to the OP's GUI mode sample
        std::setlocale(LC_NUMERIC,"C");
        try
        {
            const auto outd=std::stod(s);
            std::cout << "Conversion succeeded: " << s << "  =>  "
                      << outd << '\n';
        }
        catch (...)
        {
            std::cout << "Conversion FAILED   : " << s << "  =>  ???\n";
        }
        // Restore locale setting
        std::setlocale(LC_NUMERIC,oldLocale.c_str());

    }
}

#include <QApplication>
int main(int argc, char** argv)
{
    std::cout << "Test in normal console mode\n";
    test();
    QApplication app(argc, argv);
    std::cout << "Test in GUI mode\n";
    test();
}
Run Code Online (Sandbox Code Playgroud)

输出:

#include <iostream>
#include <clocale>
#include <vector>
#include <string>

void test()
{
    for(auto s : {"123.1234567890",
                  "123.1234",
                  "123,1234567890",
                  "123,1234"})
    {
        // Save locale setting
        const std::string oldLocale=std::setlocale(LC_NUMERIC,nullptr);
        // Force '.' as the radix point. If you comment this out,
        // you'll get output similar to the OP's GUI mode sample
        std::setlocale(LC_NUMERIC,"C");
        try
        {
            const auto outd=std::stod(s);
            std::cout << "Conversion succeeded: " << s << "  =>  "
                      << outd << '\n';
        }
        catch (...)
        {
            std::cout << "Conversion FAILED   : " << s << "  =>  ???\n";
        }
        // Restore locale setting
        std::setlocale(LC_NUMERIC,oldLocale.c_str());

    }
}

#include <QApplication>
int main(int argc, char** argv)
{
    std::cout << "Test in normal console mode\n";
    test();
    QApplication app(argc, argv);
    std::cout << "Test in GUI mode\n";
    test();
}
Run Code Online (Sandbox Code Playgroud)


Pet*_*ker 6

std::stod它的亲属旨在提供从字符串到数字类型的简单快速转换.(完全披露:这是我的设计)所以,不,没有区域设置; 你所看到的就是你得到的.

  • 只是为了澄清,stod()IS受当前语言环境的影响,至少在GCC中是这样.因此,例如,为了确保它将使用点作为小数分隔符,应使用#include <clocale>和setlocale(LC_ALL,"C")(这是默认值,但显然Qt必须将其设置为正在运行的计算机区域设置,因此您需要覆盖Qt覆盖;-)) (4认同)
  • 这个答案是错误的,您在评论中承认了这一点。为什么不编辑它进行修复? (3认同)