【问题标题】:Does std::locale::global make affect to printf() function?std::locale::global 会影响 printf() 函数吗?
【发布时间】:2012-09-11 15:39:00
【问题描述】:

我在我的电脑上使用俄语区域设置。
如果我要设置:

class numpunct_withpoint: public numpunct<char>
{
protected:
    /// Override the function that gives the decimal separator.
    char do_decimal_point() const
    {
        return '.';
    }
};
...
locale loc(std::locale::classic(), new numpunct_withpoint);
std::locale::global(loc);


然后

printf("%f", 3.14);

输出是:

3,14

小数点分隔符是“,”,不像 do_decimal_point 函数! 如何使用 C++ 语言环境更改小数分隔符的 C 语言环境设置?


感谢您的回答!
但是,C setlocale 函数对 C++ cout 对象有影响吗?

setlocale(LC_NUMERIC, "C");

这会影响通过 cout 打印十进制值吗?

【问题讨论】:

    标签: c++ locale printf std setlocale


    【解决方案1】:

    当您设置全局 C++ 语言环境时,C 语言环境也会被修改。如果您修改 C 语言环境,则全局 C++ 语言环境不会修改。

    以下演示如何设置 C++ 全局语言环境。

    #include <cstdio>
    #include <clocale>
    #include <fstream>
    
    int main() {
        const char * locale_name = "French_France.1252"; // or "fr_Fr.UTF-8" on Unix
        double value = 1.2;
    
        std::locale::global(std::locale(locale_name));
    
        std::ofstream("out.txt") << "C++ " << value << '\n';
    
        if (FILE *f = std::fopen("out.txt", "a")) {
            std::fprintf(f, "C %1.1e\n", value);
            std::fclose(f);
        }
    }
    

    C 和 C++ 输出都应使用逗号小数点。

    C++ 1,2
    C 1,2e+000

    如果您将设置 C++ 语言环境替换为设置 C 语言环境 std::setlocale(LC_ALL, locale_name);,则输出应更改,以便只有 C 输出使用逗号十进制,而 C++ 输出仍使用默认句点十进制符号。

    C++ 1.2
    C 1,2e+000

    但是,设置 C++ 语言环境会影响 C 语言环境这一事实并不能使 C 语言环境像 C++ 语言环境那样具有可扩展性。基于 C 语言环境的函数永远不会使用自定义 C++ 方面。相反,您必须依靠您的系统来支持某些具有您需要的功能的命名语言环境。

    具体来说,std::locale::global() 被定义为使用您选择的 C++ 语言环境的名称来设置 C 语言环境(如果它有名称的话)。如果 C++ 语言环境没有名称,则行为由实现定义。此外,C++ 指定组合两个命名语言环境会产生一个命名语言环境。一些实现产生有用的组合名称,允许您通过设置 C++ 语言环境来混合 C 语言环境类别:

    std::locale::global(std::locale(std::locale("ru_RU"), "C", std::locale::numeric));
    

    使用 libstdc++ 会生成一个名为:

    LC_CTYPE=ru_RU;LC_NUMERIC=C;LC_TIME=ru_RU;LC_COLLATE=ru_RU;LC_MONETARY=ru_RU;LC_MESSAGES=ru_RU;LC_PAPER=ru_RU;LC_NAME=ru_RU;LC_ADDRESS=ru_RU;LC_TELEPHONE=ru_RU;LC_MEASUREMENT=ru_RU;LC_IDENTIFICATION=ru_RU LC_CTYPE=ru_RU;LC_NUMERIC=C;LC_TIME=ru_RU;LC_COLLATE=ru_RU;LC_MONETARY=ru_RU;LC_MESSAGES=ru_RU;LC_PAPER=ru_RU;LC_NAME=ru_RU;LC_ADDRESS=ru_RU;LC_TELEPHONE=ru_RU;LC_MEASUREMENT=ru_RU;LC_IDENTIFICATION=ru_RU

    因此,C 语言环境设置为与 C++ 语言环境相同的“ru_RU”和“C”语言环境之间的混合。

    不幸的是,其他实现选择了不太有用的行为,但在技术上仍然符合要求。在 Visual Studio 中

    std::locale::global(std::locale(std::locale("Russian_Russia.1251"), "C", std::locale::numeric));
    

    生成名称为“C”的语言环境。因此,虽然 C++ 语言环境是俄语和 C 语言环境类别的适当混合,但 C 语言环境只是设置为“C”。所以在这些平台上混合C语言环境类别你必须直接设置C语言环境:

    // set the C++ locale first
    std::locale::global(std::locale(std::locale("Russian_Russia.1251"), "C", std::locale::numeric));
    
    // set the C locale second, because it will not overwrite the changes you made to the C++ locale
    std::setlocale(LC_ALL, "Russian_Russia.1251");
    std::setlocale(LC_NUMERIC, "C");
    

    【讨论】:

      【解决方案2】:

      C 库不使用与 C++ 相同的区域设置。要覆盖printf 使用的语言环境,请使用setlocale:

      setlocale(LC_NUMERIC, "POSIX");
      

      或类似的。

      【讨论】:

      • 但是,locale::global 函数将为您调用 setlocale,如果您将其传递给指定的语言环境。
      猜你喜欢
      • 1970-01-01
      • 2014-10-29
      • 1970-01-01
      • 2017-09-24
      • 1970-01-01
      • 2020-05-30
      • 1970-01-01
      • 2021-09-18
      • 2017-04-26
      相关资源
      最近更新 更多