当您设置全局 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");