std::locale::global是否影响printf()函数



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

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++对象产生影响吗

setlocale(LC_NUMERIC, "C");

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

当您设置全局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.1en", 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_ruLC_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"one_answers"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");

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

setlocale(LC_NUMERIC, "POSIX");

或类似的。

最新更新