8

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

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

4

2 回答 2

7

当您设置全局 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");
于 2012-09-11T16:28:52.327 回答
0

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

setlocale(LC_NUMERIC, "POSIX");

或类似的。

于 2012-09-11T15:42:04.530 回答