使用printf将em dash打印到控制台窗口? 一个简单的问题:我正在编写C++的聊天室程序(但主要是C风格),我正试图打印“帮助显示一个命令列表…”到输出窗口。虽然我可以使用两个连字符(-)来实现大致相同的效果,但我宁愿使用em破折号(-)printf()似乎不支持打印em破折号。相反,控制台只是在原处打印字符ù,尽管直接在提示符中输入em破折号效果很好

使用printf将em dash打印到控制台窗口? 一个简单的问题:我正在编写C++的聊天室程序(但主要是C风格),我正试图打印“帮助显示一个命令列表…”到输出窗口。虽然我可以使用两个连字符(-)来实现大致相同的效果,但我宁愿使用em破折号(-)printf()似乎不支持打印em破折号。相反,控制台只是在原处打印字符ù,尽管直接在提示符中输入em破折号效果很好,c++,c,windows,visual-studio,windows-console,C++,C,Windows,Visual Studio,Windows Console,如何显示这个简单的Unicode字符 查看Windows alt键代码,我发现alt+0151是“-”,alt+151是“ù”,这很有趣。这与我的问题有关,还是一个简单的巧合 windows是unicode(UTF-16)系统。控制台unicode也是如此。如果您想要打印unicode文本,您需要(而且这是最有效的)使用 在这种情况下,二进制文件将是宽字符-(2字节0x2014)并按原样打印 如果为输出控制台调用ansi(多字节)函数,如writeconolea或WriteFile,则控制台首先

如何显示这个简单的Unicode字符

查看Windows alt键代码,我发现alt+0151是“-”,alt+151是“ù”,这很有趣。这与我的问题有关,还是一个简单的巧合

windows是unicode(UTF-16)系统。控制台unicode也是如此。如果您想要打印unicode文本,您需要(而且这是最有效的)使用

在这种情况下,二进制文件将是宽字符
-
(2字节
0x2014
)并按原样打印

如果为输出控制台调用ansi(多字节)函数,如
writeconolea
WriteFile
,则控制台首先通过将多字节字符串转换为unicode,并将使用返回的值就地代码页。如果使用大于0x80的字符,这里(翻译)可能会出现问题

首先,编译器可能会给您警告:文件包含一个无法在当前代码页(数字)中表示的字符。以Unicode格式保存文件以防止数据丢失。(). 但即使将源文件保存为Unicode格式,也可以:

wprintf(L"ù"); // no warning
printf("ù"); //warning C4566
因为
L“ù”
二进制文件中保存为宽字符字符串(原样)-这里一切正常,没有任何问题和警告。但是
“ù”
保存为字符字符串(单字节字符串)。编译器需要将宽字符串“ù”从源文件转换为二进制(.obj文件,链接器从该文件创建pe)。和编译器一起使用CP_ACP(当前系统默认的Windows ANSI代码页)

那么,如果你说call
printf(“ù”)

  • unicode字符串“ù”将转换为多字节
    WideCharToMultiByte(CP\u ACP,)
    这将在编译时进行。生成的多字节字符串将保存在二进制文件中
  • 控制台将运行时字符串转换为多字节字符串 通过
    MultiByteToWideChar(GetConsoleOutputCP(),…)
    和 打印此字符串
  • 因此您得到了两种转换:
    unicode->CP\u ACP->multi-byte->GetConsoleOutputCP()->unicode

    默认情况下
    GetConsoleOutputCP()==CP\u OEMCP!=CP_ACP
    即使您在编译程序的计算机上运行该程序。(特别是在另一台计算机上,使用另一个
    CP\u OEMCP

    不兼容转换中的问题-使用了不同的代码页。但是,即使将控制台代码页更改为
    CP\u ACP
    ,转换也可能会错误地翻译某些字符

    关于CRT api
    wprintf
    ——接下来的情况是:

    wprintf
    首先使用内部当前值将给定字符串从unicode转换为多字节(注意crt区域设置独立于控制台区域设置,不同于控制台区域设置)。然后使用多字节字符串调用
    WriteFile
    。控制台将此多字节字符串转换回unicode

    unicode->current\u crt\u locale->multi-byte->GetConsoleOutputCP()->unicode

    因此,为了使用
    wprintf
    我们需要首先将当前crt区域设置设置为
    GetConsoleOutputCP()

    但无论如何,我在这里查看(在我的comp上)屏幕上的
    -
    ,而不是
    -
    。如果调用
    PrintString(L“-”),则
    --
    也是如此(在这之后使用了
    WriteConsoleW

    所以,唯一可靠的方法是打印任何unicode字符(windows支持)-使用WriteConsoleWapi。

    windows是unicode(UTF-16)系统。控制台unicode也是如此。如果您想要打印unicode文本,您需要(而且这是最有效的)使用

    在这种情况下,二进制文件将是宽字符
    -
    (2字节
    0x2014
    )并按原样打印

    如果为输出控制台调用ansi(多字节)函数,如
    writeconolea
    WriteFile
    ,则控制台首先通过将多字节字符串转换为unicode,并将使用返回的值就地代码页。如果使用大于0x80的字符,这里(翻译)可能会出现问题

    首先,编译器可能会给您警告:文件包含一个无法在当前代码页(数字)中表示的字符。以Unicode格式保存文件以防止数据丢失。(). 但即使将源文件保存为Unicode格式,也可以:

    wprintf(L"ù"); // no warning
    printf("ù"); //warning C4566
    
    因为
    L“ù”
    二进制文件中保存为宽字符字符串(原样)-这里一切正常,没有任何问题和警告。但是
    “ù”
    保存为字符字符串(单字节字符串)。编译器需要将宽字符串“ù”从源文件转换为二进制(.obj文件,链接器从该文件创建pe)。和编译器一起使用CP_ACP(当前系统默认的Windows ANSI代码页)

    那么,如果你说call
    printf(“ù”)

  • unicode字符串“ù”将转换为多字节
    WideCharToMultiByte(CP\u ACP,)
    这将在编译时进行。生成的多字节字符串将保存在二进制文件中
  • 控制台将运行时字符串转换为多字节字符串 通过
    MultiByteToWideChar(GetConsoleOutputCP(),…)
    和 打印此字符串
  • 所以你有两个转换
    char sz[16];
    sprintf(sz, ".%u", GetConsoleOutputCP());
    setlocale(LC_ALL, sz);
    wprintf(L"—");
    
    #include <stdio.h>
    #include <io.h>
    #include <fcntl.h>
    
    int main()
    {
        //other stuff
        _setmode(_fileno(stdout), _O_U16TEXT);
        wprintf(L"#help — display a list of commands...");