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

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

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);

"and than" 翻译成中文是 "然后"。
printf("%f", 3.14);

输出为:

输出为:

3,14

小数点分隔符是“,”,而不是 do_decimal_point 函数中的格式!我该如何使用 C++ locale 更改 C 区域设置的小数点分隔符?


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

setlocale(LC_NUMERIC, "C");

这会影响通过cout打印十进制值吗?
2个回答

8

当你设置全局的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++ facets永远不会被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"的locale。因此,尽管C++ locale是俄语和C locale类别的适当混合,但C locale仅设置为"C"。因此,在这些平台上要混合C locale类别,您必须直接设置C locale:

// 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");

0

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

setlocale(LC_NUMERIC, "POSIX");

或类似的。

然而,locale::global 函数会在你传递一个命名的区域设置时为你调用 setlocale - Bo Persson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接