打印Unicode字符C ++

时间:2013-09-19 20:14:07

标签: c++ unicode

我正在尝试编写一个简单的命令行应用程序来自学日语,但似乎无法打印Unicode字符。我错过了什么?

#include <iostream>
using namespace std;

int main()
{
        wcout << L"こんにちは世界\n";
        wcout << L"Hello World\n"
        system("pause");
}

在此示例中,仅显示“按任意键继续”。在Visual C ++ 2013上测试。

3 个答案:

答案 0 :(得分:6)

这在Windows上并不容易。即使您设法将文本发送到Windows控制台,仍然需要配置cmd.exe才能显示日语字符。


#include <iostream>

int main() {
  std::cout << "こんにちは世界\n";
}

这适用于以下任何系统:

  • 编译器的源代码和执行编码包括字符。
  • 输出设备(例如,控制台)需要与编译器的执行编码具有相同编码的文本。
  • 可以使用具有相应字符的字体(通常不是问题)。

目前,大多数平台默认使用UTF-8进行所有这些编码,因此可以使用与上述类似的代码支持整个Unicode范围。不幸的是,Windows不是这些平台之一。

wcout << L"こんにちは世界\n";

在这一行中,字符串文字数据(在编译时)从源编码转换为执行范围编码,然后(在运行时)wcout使用它所灌注的语言环境来转换wchar_t数据char数据输出。出现问题的地方是,默认语言环境只需要支持基本源字符集中的字符,这些字符集甚至不包括所有ASCII字符,更不用说非ASCII字符。

因此转换会导致错误,导致wcout处于错误状态。在wcout再次运行之前必须清除错误,这就是第二个print语句不输出任何内容的原因。


您可以通过使用可成功转换字符的区域设置wcout来为有限范围的字符解决此问题。不幸的是,以这种方式支持整个Unicode范围所需的编码是UTF-8;虽然Microsoft的流实现支持其他多字节编码,但它特别不支持UTF-8。

例如:

wcout.imbue(std::locale(std::locale::classic(), new std::codecvt_utf8_utf16<wchar_t>()));

SetConsoleOutputCP(CP_UTF8);

wcout << L"こんにちは世界\n";

这里wcout会正确地将字符串转换为UTF-8,如果输出被写入文件而不是控制台,则文件将包含正确的UTF-8数据。但是,Windows控制台即使在此处配置为接受UTF-8数据,也不会接受以这种方式写入的UTF-8数据。


有几个选择:

  • 完全避免使用标准库:

    DWORD n;
    WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"こんにちは世界\n", 8, &n, nullptr);
    
  • 使用违反标准代码的非标准魔法咒语:

    #include <fcntl.h>
    #include <io.h>
    
    _setmode(_fileno(stdout), _O_U8TEXT);
    std::wcout << L"こんにちは世界\n";
    

    设置此模式后,std::cout << "Hello, World";将崩溃。

  • 使用低级IO API和手动转换:

    #include <codecvt>
    #include <locale>
    
    SetConsoleOutputCP(CP_UTF8);
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> convert;
    std::puts(convert.to_bytes(L"こんにちは世界\n"));
    

使用这些方法中的任何一种,cmd.exe都会尽可能显示正确的文本,我的意思是它会显示不可读的框。七个小盒子,用于给定的字符串。

Little Boxes

您可以将文本从cmd.exe复制到notepad.exe或其他任何内容以查看正确的字形。

答案 1 :(得分:3)

有关于在Windows控制台中处理Unicode的整篇文章

http://alfps.wordpress.com/2011/11/22/unicode-part-1-windows-console-io-approaches/
http://alfps.wordpress.com/2011/12/08/unicode-part-2-utf-8-stream-mode/

基本上,您可以根据streambufstd::cout(或std::wcout)实现自己的WriteConsoleW并享受编写UTF-8(或您想要的任何Unicode)到Windows控制台,不依赖于区域设置,控制台代码页,甚至不使用宽字符 它可能看起来不是很简单,但它是方便且可重复使用的解决方案,它还能够为您提供便携式utf8无处不在的用户代码。请不要因为我的英语而打败我:)

答案 2 :(得分:-1)

或者您可以将Windows区域设置更改为日语。

相关问题