我正在尝试编写一个简单的命令行应用程序来自学日语,但似乎无法打印Unicode字符.我错过了什么?
#include <iostream>
using namespace std;
int main()
{
wcout << L"???????\n";
wcout << L"Hello World\n"
system("pause");
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,仅显示"按任意键继续".在Visual C++ 2013上测试过.
这在Windows上并不容易.即使您设法将文本发送到Windows控制台,仍然需要配置cmd.exe才能显示日语字符.
#include <iostream>
int main() {
std::cout << "???????\n";
}
Run Code Online (Sandbox Code Playgroud)
这适用于以下任何系统:
目前大多数平台默认使用UTF-8进行所有这些编码,因此可以使用与上述类似的代码支持整个Unicode范围.不幸的是,Windows不是这些平台之一.
wcout << L"???????\n";
Run Code Online (Sandbox Code Playgroud)
在这一行中,字符串文字数据(在编译时)从源编码转换为执行宽编码,然后(在运行时)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";
Run Code Online (Sandbox Code Playgroud)
这里wcout将正确地将字符串转换为UTF-8,如果输出被写入文件而不是控制台,那么该文件将包含正确的UTF-8数据.但是,Windows控制台即使在此处配置为接受UTF-8数据,也不会接受以这种方式写入的UTF-8数据.
有几个选择:
完全避免使用标准库:
DWORD n;
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), L"???????\n", 8, &n, nullptr);
Run Code Online (Sandbox Code Playgroud)使用会破坏标准代码的非标准魔法咒语:
#include <fcntl.h>
#include <io.h>
_setmode(_fileno(stdout), _O_U8TEXT);
std::wcout << L"???????\n";
Run Code Online (Sandbox Code Playgroud)
设置此模式后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"));
Run Code Online (Sandbox Code Playgroud)使用任何这些方法,cmd.exe将尽可能显示正确的文本,我的意思是它将显示不可读的框.七个小盒子,用于给定的字符串.

您可以将文本从cmd.exe复制到notepad.exe或其他任何内容以查看正确的字形.
| 归档时间: |
|
| 查看次数: |
5341 次 |
| 最近记录: |