多次调用 setlocale
Multiple calls to setlocale
我想弄清楚 C++ 是如何支持 Unicode 的。
当我想输出多语言文本到控制台时,我调用std::setlocale
。但是我注意到结果取决于之前对 setlocale
.
的调用
考虑以下示例。如果 运行 没有参数,它会调用 setlocale
一次,否则它会先调用 setlocale
以获取当前语言环境的值并在函数结束时恢复它。
#include <iostream>
#include <locale>
using namespace std;
int main(int argc, char** argv)
{
char *current_locale = 0;
if (argc > 1) {
current_locale = setlocale(LC_ALL, NULL);
wcout << L"Current output locale: " << current_locale << endl;
}
char* new_locale = setlocale(LC_ALL, "ru_RU.UTF8");
if (! new_locale)
wcout << L"failed to set new locale" << endl;
else
wcout << L"new locale: " << new_locale << endl;
wcout << L"Привет!" << endl;
if (current_locale) setlocale(LC_ALL, current_locale);
return 0;
}
输出不同:
:~> ./check_locale
new locale: ru_RU.UTF8
Привет!
:~> ./check_locale 1
Current output locale: C
new locale: ru_RU.UTF8
??????!
有什么事情 setlocale(LC_ALL, NULL)
需要在以后的 setlocale
电话中处理吗?
编译器是g++ 7.5.0
或clang++ 7.0.1
。控制台是图形终端中的 linux 控制台。
有关系统配置的更多详细信息:OpenSUSE 15.1、linux 4.12、glibc 2.26、libstdc++6-10.2.1
Is there something that setlocale(LC_ALL, NULL) does that needs to be taken care of in future setlocale calls?
不,setlocale(..., NULL)
不修改当前语言环境。下面的代码就可以了:
setlocale(LC_ALL, NULL);
setlocale(LC_ALL, "ru_RU.UTF8");
wprintf(L"Привет!\n");
但是下面的代码会失败:
wprintf(L"anything"); // or even just `fwide(stdout, 1);`
setlocale(LC_ALL, "ru_RU.UTF8");
wprintf(L"Привет!\n");
问题是流有它自己的区域设置,它是在流方向更改为宽时确定的。
// here stdout has no orientation and no locale associated with it
wprintf(L"anything");
// `stdout` stream orientation switches to wide stream
// current locale is used - `stdout` has C locale
setlocale(LC_ALL, "ru_RU.UTF8");
wprintf(L"Привет!\n");
// `stdout` is wide oriented
// current locale is ru_RU.UTF-8
// __but__ the locale of `stdout` is still C and cannot be changed!
我找到的关于这个 gnu.org Stream and I18N 重点的唯一文档:
Since a stream is created in the unoriented state it has at that point no conversion associated with it. The conversion which will be used is determined by the LC_CTYPE category selected at the time the stream is oriented. If the locales are changed at the runtime this might produce surprising results unless one pays attention. This is just another good reason to orient the stream explicitly as soon as possible, perhaps with a call to fwide.
您可以:
- 为 C++ 流和 C 使用不同的语言环境
FILE
(参见 here):
std::ios_base::sync_with_stdio(false);
std::wcout.imbue(std::locale("ru_RU.utf8"));
- 重新打开
stdout
:
wprintf(L""); // stdout has C locale
char* new_locale = setlocale(LC_ALL, "ru_RU.UTF8");
freopen("/dev/stdout", "w", stdout); // stdout has no stream orientation
wprintf(L"Привет!\n"); // stdout is wide and ru_RU locale
- 我认为(未经测试)在 glibc 中您甚至可以使用显式语言环境重新打开
stdout
(参见 GNU opening streams):
freopen("/dev/stdout", "w,css=ru_RU.UTF-8", stdout);
std::wcout << L"Привет!\n"; // fine
- 无论如何,在做任何其他事情之前,请尽快设置语言环境。
我想弄清楚 C++ 是如何支持 Unicode 的。
当我想输出多语言文本到控制台时,我调用std::setlocale
。但是我注意到结果取决于之前对 setlocale
.
考虑以下示例。如果 运行 没有参数,它会调用 setlocale
一次,否则它会先调用 setlocale
以获取当前语言环境的值并在函数结束时恢复它。
#include <iostream>
#include <locale>
using namespace std;
int main(int argc, char** argv)
{
char *current_locale = 0;
if (argc > 1) {
current_locale = setlocale(LC_ALL, NULL);
wcout << L"Current output locale: " << current_locale << endl;
}
char* new_locale = setlocale(LC_ALL, "ru_RU.UTF8");
if (! new_locale)
wcout << L"failed to set new locale" << endl;
else
wcout << L"new locale: " << new_locale << endl;
wcout << L"Привет!" << endl;
if (current_locale) setlocale(LC_ALL, current_locale);
return 0;
}
输出不同:
:~> ./check_locale
new locale: ru_RU.UTF8
Привет!
:~> ./check_locale 1
Current output locale: C
new locale: ru_RU.UTF8
??????!
有什么事情 setlocale(LC_ALL, NULL)
需要在以后的 setlocale
电话中处理吗?
编译器是g++ 7.5.0
或clang++ 7.0.1
。控制台是图形终端中的 linux 控制台。
有关系统配置的更多详细信息:OpenSUSE 15.1、linux 4.12、glibc 2.26、libstdc++6-10.2.1
Is there something that setlocale(LC_ALL, NULL) does that needs to be taken care of in future setlocale calls?
不,setlocale(..., NULL)
不修改当前语言环境。下面的代码就可以了:
setlocale(LC_ALL, NULL);
setlocale(LC_ALL, "ru_RU.UTF8");
wprintf(L"Привет!\n");
但是下面的代码会失败:
wprintf(L"anything"); // or even just `fwide(stdout, 1);`
setlocale(LC_ALL, "ru_RU.UTF8");
wprintf(L"Привет!\n");
问题是流有它自己的区域设置,它是在流方向更改为宽时确定的。
// here stdout has no orientation and no locale associated with it
wprintf(L"anything");
// `stdout` stream orientation switches to wide stream
// current locale is used - `stdout` has C locale
setlocale(LC_ALL, "ru_RU.UTF8");
wprintf(L"Привет!\n");
// `stdout` is wide oriented
// current locale is ru_RU.UTF-8
// __but__ the locale of `stdout` is still C and cannot be changed!
我找到的关于这个 gnu.org Stream and I18N 重点的唯一文档:
Since a stream is created in the unoriented state it has at that point no conversion associated with it. The conversion which will be used is determined by the LC_CTYPE category selected at the time the stream is oriented. If the locales are changed at the runtime this might produce surprising results unless one pays attention. This is just another good reason to orient the stream explicitly as soon as possible, perhaps with a call to fwide.
您可以:
- 为 C++ 流和 C 使用不同的语言环境
FILE
(参见 here):
std::ios_base::sync_with_stdio(false);
std::wcout.imbue(std::locale("ru_RU.utf8"));
- 重新打开
stdout
:
wprintf(L""); // stdout has C locale
char* new_locale = setlocale(LC_ALL, "ru_RU.UTF8");
freopen("/dev/stdout", "w", stdout); // stdout has no stream orientation
wprintf(L"Привет!\n"); // stdout is wide and ru_RU locale
- 我认为(未经测试)在 glibc 中您甚至可以使用显式语言环境重新打开
stdout
(参见 GNU opening streams):
freopen("/dev/stdout", "w,css=ru_RU.UTF-8", stdout);
std::wcout << L"Привет!\n"; // fine
- 无论如何,在做任何其他事情之前,请尽快设置语言环境。