打印 wstring 的方法是将其转换为基于 UTF-8 字符的字符串。严重地wchar_t 毫无意义在Windows或其他各种平台库之一之外,不幸的是,在意识到它是一个坏主意之前,它们就采用了wchar_t。
// move to clang and libc++ then
#include <codecvt>
int main(){
std::wstring_convert<std::codecvt_utf8<wchar_t>,wchar_t> convert; // converts between UTF-8 and UCS-4 (given sizeof(wchar_t)==4)
std:wstring s = L"日本";
std::cout << convert.to_bytes(s);
}
只是为了解释您显示的代码中出了什么问题;
char* locale = setlocale(LC_ALL, "");
std::cout << "locale: " << locale << std::endl; // "C" for me
这里的区域设置字符串是应用更改后的区域设置名称。既然你说你得到“C”,那就意味着你正在使用“C”语言环境。通常情况下,人们会得到一个类似“en_US.UTF-8”的名称,但无论出于何种原因,您的环境都没有正确设置。你表明$LANG
设置正确,但其他区域设置环境变量之一可能设置不同。
无论如何,您都使用“C”语言环境,它只需要支持基本字符集。我相信在 OS X 上你会得到的行为是char
会直接转换为相同的wchar_t
值,且仅wchar_t
支持范围内的值char
将转换回来。这实际上与使用基于 ISO 8859-1 的区域设置相同,因此日语字符将不起作用。
如果您确实坚持要让这种基于区域设置的东西工作,那么您需要获得一个合适的区域设置,即使用 UTF-8 的区域设置。您可以找出您的环境出了什么问题,也可以使用不可移植的显式区域设置名称。
std::wcout.imbue(std::locale("en_US.UTF-8"));
std::wcout << L"¡Hola!\n";
std::wcout << L"日本\n";
另外,如果您使用 libstdc++,您应该知道它在 OS X 上无法正确支持区域设置。您必须使用 libc++ 才能使 OS X 的区域设置名称(例如“en_US.UTF-8”)正常工作。