This question already has answers here:
Is it possible to cout an EM DASH on Linux and Windows? [duplicate]
(2个答案)
3年前关闭。
一个简单的问题:我正在为一个类用C++(但主要是C风格)编写一个聊天室程序,并且试图在输出窗口中打印“#help —显示命令列表...”。 。虽然我可以使用两个连字符(-)来达到大致相同的效果,但我宁愿使用破折号(-)。
如何显示这个简单的Unicode字符?
查看Windows的alt键代码,我发现alt + 0151是“—”而alt + 151是“ù”是很有趣的。这与我的问题有关,还是一个简单的巧合?
在这种情况下,您的二进制文件中将使用宽字符
如果为输出控制台调用了ansi(多字节)功能(例如
首先,编译器会警告您:该文件包含一个无法在当前代码页(数字)中表示的字符。以Unicode格式保存文件以防止数据丢失。 (C4819)。但即使您以Unicode格式保存源文件,也可以执行以下操作:
因为
那么,如果您说致电
Unicode字符串“ù”将转换为多字节 中控制台它运行时将您的多字节字符串转换为
宽字符由
打印此字符串
因此您获得了2次转化:
默认情况下,即使您在编译它的计算机上运行程序,
转换不兼容的问题-使用了不同的代码页。但是,即使将控制台代码页更改为
关于CRT api
所以要使用
但是无论如何,我在屏幕上(在我的电脑上)查看
因此,只有可靠的方式才能打印任何Unicode字符(Windows支持)-使用WriteConsole W api。
(2个答案)
3年前关闭。
一个简单的问题:我正在为一个类用C++(但主要是C风格)编写一个聊天室程序,并且试图在输出窗口中打印“#help —显示命令列表...”。 。虽然我可以使用两个连字符(-)来达到大致相同的效果,但我宁愿使用破折号(-)。
printf()
似乎不支持打印破折号。取而代之的是,尽管直接在提示符中输入破折号也可以,但控制台只是在其位置打印出了字符ù。如何显示这个简单的Unicode字符?
查看Windows的alt键代码,我发现alt + 0151是“—”而alt + 151是“ù”是很有趣的。这与我的问题有关,还是一个简单的巧合?
最佳答案
Windows是Unicode(UTF-16)系统。以及控制台unicode。如果要打印unicode文本-您需要(这是最有效的),请使用 WriteConsoleW
BOOL PrintString(PCWSTR psz)
{
DWORD n;
return WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), psz, (ULONG)wcslen(psz), &n, 0);
}
PrintString(L"—");
在这种情况下,您的二进制文件中将使用宽字符
—
(2字节0x2014
),控制台将其按原样打印。如果为输出控制台调用了ansi(多字节)功能(例如
WriteConsoleA
或WriteFile
),则控制台首先通过 MultiByteToWideChar
将多字节字符串转换为unicode,并在适当的地方使用CodePage来使用 GetConsoleOutputCP
返回的值。如果您使用的字符> 0x80,则这里(翻译)可能会出现问题首先,编译器会警告您:该文件包含一个无法在当前代码页(数字)中表示的字符。以Unicode格式保存文件以防止数据丢失。 (C4819)。但即使您以Unicode格式保存源文件,也可以执行以下操作:
wprintf(L"ù"); // no warning
printf("ù"); //warning C4566
因为
L"ù"
保存为宽字符字符串(按原样)在二进制文件中-此处一切正常,没有任何问题和警告。但是"ù"
保存为字符字符串(单字节字符串)。编译器需要将二进制文件中的宽字符串“ù”从源文件转换为多字节字符串(.obj文件,链接器将从中创建pe)。和 WideCharToMultiByte
与CP_ACP一起用于编译器(当前系统默认的Windows ANSI代码页。)那么,如果您说致电
printf("ù");
会怎样?WideCharToMultiByte(CP_ACP, )
,这将在编译时进行。生成的多字节字符串将保存在二进制文件宽字符由
MultiByteToWideChar(GetConsoleOutputCP(), ..)
和打印此字符串
因此您获得了2次转化:
unicode -> CP_ACP -> multi-byte -> GetConsoleOutputCP() -> unicode
默认情况下,即使您在编译它的计算机上运行程序,
GetConsoleOutputCP() == CP_OEMCP != CP_ACP
也是如此。 (尤其是在另一台具有另一个CP_OEMCP
的计算机上)转换不兼容的问题-使用了不同的代码页。但是,即使将控制台代码页更改为
CP_ACP
,转换也可能会错误地翻译某些字符。关于CRT api
wprintf
-接下来是这种情况:wprintf
首先使用内部locale将给定的字符串从unicode转换为多字节(请注意,crt语言环境独立且与控制台语言环境不同)。然后使用多字节字符串调用WriteFile
。控制台将此多字节字符串转换回unicodeunicode -> current_crt_locale -> multi-byte -> GetConsoleOutputCP() -> unicode
所以要使用
wprintf
,我们需要先将当前crt语言环境设置为GetConsoleOutputCP()
char sz[16];
sprintf(sz, ".%u", GetConsoleOutputCP());
setlocale(LC_ALL, sz);
wprintf(L"—");
但是无论如何,我在屏幕上(在我的电脑上)查看
-
而不是—
。因此,如果在此之后立即调用-—
(使用PrintString(L"—");
),则将为WriteConsoleW
。因此,只有可靠的方式才能打印任何Unicode字符(Windows支持)-使用WriteConsole W api。
关于c++ - 使用printf将短划线打印到控制台窗口? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46226592/