std :: locale :: global会影响printf()函数吗?

时间:2012-09-11 15:39:00

标签: c++ locale printf std setlocale

我在电脑上使用俄语语言环境设置。
如果我要设置:

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打印十进制值时产生影响吗?

2 个答案:

答案 0 :(得分:6)

设置全局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语言环境std::setlocale(LC_ALL, locale_name);替换设置C ++语言环境,则输出应该更改,以便只有C输出使用逗号十进制,而C ++输出仍然使用默认句点十进制符号。 / p>

  

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语言环境设置为“ru_RU”和“C”语言环境之间的相同混合,就像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");

答案 1 :(得分:0)

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

setlocale(LC_NUMERIC, "POSIX");

或类似。