Windows 控制台窗口是纯 Unicode。它的缓冲区将文本存储为 UCS-2 Unicode(每个字符 16 位,本质上类似于原始 Unicode,对现代 21 位 Unicode 的基本多语言平面的限制)。所以一个控制台窗口可以呈现几乎所有类型的文本。
但是,对于每个字符的单个字节(并且可能还有一些可变长度编码),i/o Windows 会自动转换到控制台窗口的活动代码页。如果控制台窗口是一个 [cmd.exe] 实例,那么您可以通过命令 chcp(change 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 中的字符编码相同。