Unicode无法打印

3

我有以下的C++代码

char* locale = setlocale(LC_ALL, "German"); // Get the CRT's current locale.
std::locale lollocale(locale);
setlocale(LC_ALL, locale); // Restore the CRT.
wcout.imbue(lollocale); // Now set the std::wcout to have the locale that we got from the CRT.

COORD cur = { 0, 0 };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cur);
wcout << L"Enemy " << this->enemyStrengthLeft << L"/" << this->enemyStrength << endl;
wcout << L"◄";
for (int i = 0; i < 20; i++) {
  if (i % 2 == 0)
    wcout << L"■";
  else
    wcout << L" ";
}
wcout << L"►" << endl;

当我执行它时,Unicode字符不在cmd窗口中显示,我该怎么办?
编辑:
我使用的字体是Lucida Console。
第二次编辑:
如果有帮助的话,我正在运行Windows 7 Enterprise SP1 64位下的Visual Studio 2013 Express for Desktop。

那看起来像是Windows系统,如果是的话,在向标准输出发送宽字符串之前需要使用 _setmode(_fileno(stdout), _O_WTEXT); - Cubbi
字符没有显示的方式是什么?它们被省略了,替换了,还是在第一个Unicode字符后整个输出流“停止”了? - MicroVirus
@MicroVirus,它们只是没有显示出来。 - Knerd
考虑使用 boost::nowide 吗?在 Windows 下它可以让一些事情变得不那么糟糕。 - Rook
@Hook,老实说我想继续使用Windows API,但如果没有其他解决方案,我可能会看看 :) - Knerd
显示剩余5条评论
1个回答

3

Windows标准库不太支持Unicode。通过标准库将任意Unicode打印到控制台可以实现,但不太方便,并且我知道的所有方法都有不愉快的副作用。

只需使用Windows API:

std::wstring s = L"◄ ■ ►";
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), s.c_str(), s.size(), nullptr, nullptr);

顺便提一下,您用于获取区域设置并还原它的代码并不是您想象中的那样,并且有更好的方法。

char* locale = setlocale(LC_ALL, "German"); // Get the CRT's current locale.
std::locale lollocale(locale);
setlocale(LC_ALL, locale); // Restore the CRT.

setlocale函数返回的是函数运行后实际生效的语言环境名称。因此,你总是会得到一个德语语言环境的名称,并且全局语言环境将不会恢复到其原始值。如果你真的想获取当前设置的语言环境,那么可以通过传递nullptr而不是语言环境名称来实现:

char const *locale = std::setlocale(LC_ALL, nullptr);

这会获取当前的语言环境,但是你需要知道,除非在某一时刻改变了语言环境,否则它将是 "C" 语言环境。 C 和 C++ 程序总是从这个语言环境开始。 "C" 语言环境不一定让您使用基本源字符集之外的字符(该字符集甚至不包括 ASCII 的全部,更不用说像'ä'、'ö'、'ü'、'ß'、'◄'、'■'和'►'这样的字符了)。

如果要获取用户计算机配置的语言环境,则可以将名称留空。 您还可以将流赋予此语言环境,而无需烦恼全局语言环境。

cout.imbue(std::locale("")); // just imbue a stream

char const *locale = std::setlocale(LC_ALL, ""); // set global locale to user's preferred locale, and get the name of that locale.

可以运行,但我有点好奇为什么这个可以运行而我的解决方案不行。我的解决方案对于德语中的ä、ö、ü和ß非常完美... - Knerd
1
因为这些字符是与您的区域设置相关的字符集成员,并且它们的表示恰好与当前控制台输出代码页中的编码相同。(区域设置编码为cp1252,控制台代码页为cp850。) - bames53
非常感谢您的解决方案,我已经使用了它 :) - Knerd
请参阅http://blog.kalmbachnet.de/?postid=98,您需要在CRT中启用Unicode支持:`_setmode(_fileno(stdout), _O_U16TEXT);`。 - Jochen Kalmbach
2
@JochenKalmbach 是的,那是其中一种选择。缺点是你必须消除所有基于字符的输出,因为启用该模式后 printfcout 等会崩溃。 - bames53
@JochenKalmbach 这是VS2012:http://imgur.com/euoKAEc。也许在VS2013中已经修复了。 - bames53

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接