我试图弄清楚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、Linux4.12、glibc 2.26、libstdc++6-10.2.1
发布于 2020-12-06 10:54:27
在未来的setlocale调用中是否需要处理setlocale(LC_ALL,NULL)?
不,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");问题是,流有自己的区域设置,在流方向被更改为wide的点上确定。
// 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流与I18N的唯一文档强调了我的:
由于流是在无定向状态下创建的,因此此时没有与其相关联的转换。将使用的转换由在流面向LC_CTYPE时选定的类别确定。如果在运行时更改了区域设置,这可能会产生令人惊讶的结果,除非有人注意。这只是另一个很好的理由,让我们尽快明确地定位这条溪流,或许可以通过呼叫fwide来实现。
您可以:
FILE使用单独的区域设置(参见这里):
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 stdout (参见GNU开放流):
freopen("/dev/stdout", "w,css=ru_RU.UTF-8", stdout);
std::wcout << L"Привет!\n"; // finehttps://stackoverflow.com/questions/65166777
复制相似问题