【问题标题】:Displaying extended ASCII characters显示扩展的 ASCII 字符
【发布时间】:2022-01-14 00:00:43
【问题描述】:

在 32 位 Windows 上的 Visual Studio 2005 中,为什么我的控制台不显示从 128 到 255 的字符?

例如:

cout << "¿" << endl;  //inverted question mark

输出:

┐
Press any key to continue . . .

【问题讨论】:

  • 似乎工作得很好,你的字符集不匹配。欢迎来到遗留字符集的世界,因为 Windows 控制台似乎仍然 (!!) 不支持 Unicode。
  • Windows 控制台确实支持 Unicode。确切地说,WriteConsoleW 确实如此。 WriteConsoleA 显然没有。

标签: c++ windows visual-studio-2005 x86


【解决方案1】:

Windows 控制台窗口是纯 Unicode。它的缓冲区将文本存储为 UCS-2 Unicode(每个字符 16 位,本质上类似于原始 Unicode,对现代 21 位 Unicode 的基本多语言平面的限制)。所以一个控制台窗口可以呈现几乎所有类型的文本。

但是,对于每个字符的单个字节(并且可能还有一些可变长度编码),i/o Windows 会自动转换到控制台窗口的活动代码页。如果控制台窗口是一个 [cmd.exe] 实例,那么您可以通过命令 chcpchange codepage 的缩写)来检查它。像这样:

C:\测试> chcp 活动代码页:850 C:\测试> _

代码页 850 是基于原始 IBM PC 英语代码页 437 的编码。至少挪威 PC 上的控制台窗口默认使用 850(尽管精明的挪威人可能会将其更改为 865)。但是,这些都不是您应该使用的代码页。

最初的 IBM PC 代码页(字符编码)被称为 OEM,这是一个没有意义的首字母缩写词,Original Equipment Manufacturer。它具有适合原始 PC 文本模式屏幕的漂亮线条绘制字符。更一般地说,OEM 意味着 控制台窗口的默认代码页,其中代码页 437 只是原始代码页:它可以配置,例如每个窗口通过chcp

当微软创建 16 位 Windows 时,他们选择了另一种在 Windows 中称为 ANSI 的编码。最初的版本是 ISO Latin-1 的扩展,它在很长一段时间内都是 Internet 上的默认设置(但是,不清楚哪个先出现:微软参与了标准化)。这个原始的 ANSI 现在称为 Windows ANSI Western

ANSI 是几乎所有其他 Windows 用于非 Unicode 的代码页。控制台窗口使用 OEM。记事本、其他编辑器等使用 ANSI。

然后,当 Microsoft 开发 32 位 Windows 时,他们采用了 Latin-1 的 16 位扩展,称为 Unicode。 Microsoft 是 Unicode 联盟的创始成员。并且基本的 API,包括控制台窗口、文件系统等,都被重写为使用 Unicode。为了向后兼容,有一个转换层可以在 OEM 和 Unicode 之间转换控制台窗口,以及在 ANSI 和 Unicode 之间转换以实现其他功能。例如,MessageBoxA 是基于 Unicode 的 MessageBoxW 的 ANSI 包装器。

这样做的实际结果是,在 Windows 中,您的 C++ 源代码通常使用 ANSI 编码,而控制台窗口采用 OEM。例如让

cout << "I like Norwegian blåbærsyltetøy!" << endl;

产生纯粹的 gobbledegook... 您可以使用基于 Unicode 的控制台窗口 API 将 Unicode 直接输出到控制台窗口,避免翻译,但这很尴尬。

请注意,使用wcout 而不是cout 没有帮助:根据设计,wcout 只是从宽字符串转换为程序的窄字符集,在途中丢​​弃信息。很难相信,C++ 标准库提供了大量非常复杂的功能,这些功能毫无意义(因为这些转换可能只是由 cout 支持)。但就是这样,只是没有意义。可能这是某种类似政治的妥协,但无论如何,wcout 确实有帮助,即使它在某种程度上有意义,那么它“应该”在逻辑上对此有所帮助。

那么挪威新手程序员如何获得例如? “blåbærsyltetøy”介绍了吗?

好吧,只需将活动代码页更改为 ANSI。由于在大多数西方国家的 PC 上 ANSI 是代码页 1252,因此您可以通过

对给定的命令解释器实例执行此操作 C:\测试> chcp 1252 活动代码页:1252 C:\测试> _

现在旧的 DOS 程序,例如[edit.com](仍然存在于 Windows XP 中!)会产生一些 gobbledegook,因为 ANSI 中没有原始的 PC 字符集画线字符,而且国家字符在 ANSI 中具有不同的代码。但是,嘿,谁使用旧的 DOS 程序?不是我!

如果您希望将其作为更永久的代码页,则必须通过未记录的注册表项更改控制台窗口的配置:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage

在此键中,将OEMCP 的值更改为1252,然后重新启动

chcp 一样,或将代码页更改为 1252,会使旧的 DOS 程序呈现 gobbledegook,但会使 C++ 程序或其他现代控制台程序正常工作。

因为您在控制台窗口中的字符编码与其他 Windows 中的字符编码相同。

【讨论】:

    【解决方案2】:

    当您打印 ASCII 字符串时,Windows 会根据当前代码页在内部将其转换为 UNICODE。 CRT 还完成了从 UNICODE 到“ASCII”的转换。以下将起作用。

    #include <fcntl.h>
    #include <io.h>
    #include <stdio.h>
    #include <iostream>
    
    void
    __cdecl
    main(int ac, char **av)
    {
        _setmode(_fileno(stdout), _O_U16TEXT);
        std::wcout  << L"\u00BF";
    }
    

    【讨论】:

      【解决方案3】:

      因为 Win32 控制台使用 code page 437(又名 OEM 字体)来呈现字符,而 Windows 的其余大部分使用 Windows-1252 来呈现单字节字符代码。

      字符“¿”是 Unicode 字符倒置问号,在 Unicode、ISO 8859-1 和 Windows-1252 中具有代码点 0xBF(十进制 191)。 CP437中的code point 0xBF对应字符“┐”,即BOX DRAWINGS LIGHT DOWN AND LEFT(code point U+2510)。

      只要您使用的是 Windows 控制台,您就只能显示 CP437 中的字符,而不能显示其他字符。如果要显示其他 Unicode 字符,则需要使用不同的环境。

      【讨论】:

        【解决方案4】:

        我在 Win10 b19043 上运行。 更改为 Unicode 代码页 (65001) 允许在 CMD 窗口中打印/显示扩展的 ASCII 字符。只需在控制台或批处理文件中输入这一行,一切都会好的:

        chcp 65001 1>nul
        

        【讨论】:

          【解决方案5】:

          它可能是使用基本的 ascii 字符集实现的。 Microsoft 程序员在创建控制台时没有添加 utf-8 功能。只是猜测,因为我不是参与创建控制台的 Microsoft 程序员。

          【讨论】:

          • 你可以将 utf-8 推送到 windows 控制台。
          猜你喜欢
          • 1970-01-01
          • 2011-04-26
          • 2015-04-26
          • 1970-01-01
          • 1970-01-01
          • 2021-10-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多