当你设置全局的C++语言环境时,C语言环境也会被修改。如果你修改了C语言环境,全局的C++语言环境不会被修改。
以下演示了如何设置C++全局语言环境。
#include <cstdio>
#include <clocale>
#include <fstream>
int main() {
const char * locale_name = "French_France.1252";
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:
std::locale::global(std::locale(std::locale("Russian_Russia.1251"), "C", std::locale::numeric));
std::setlocale(LC_ALL, "Russian_Russia.1251");
std::setlocale(LC_NUMERIC, "C");
locale::global
函数会在你传递一个命名的区域设置时为你调用setlocale
。 - Bo Persson