显示扩展的ASCII字符

时间:2011-02-03 02:08:03

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

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

例如:

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

输出:

┐
Press any key to continue . . .

4 个答案:

答案 0 :(得分:13)

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

但是,对于每个字符的单字节(也可能是某些可变长度编码),i / o Windows会自动转换为控制台窗口的活动代码页。如果控制台窗口是[cmd.exe]实例,则可以通过 chcp 命令检查该实例,更改代码页的缩写。像这样:

C:\test> chcp
Active code page: 850

C:\test> _

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

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

当Microsoft创建16位Windows时,他们选择Windows中已知的另一种编码 ANSI 。最初的一个是 ISO Latin-1 的扩展,很长一段时间是互联网上的默认值(但是,目前还不清楚哪个是第一个:微软参与了标准化)。此原始ANSI现在称为 Windows ANSI Western

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

然后,当微软制造Windows 32位时,他们采用了拉丁语-1的16位扩展名为 Unicode 。 Microsoft是Unicode Consortium的原始创始成员。并且基本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:\test> chcp 1252
Active code page: 1252

C:\test> _

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

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

  

HKEY_LOCAL_MACHINE \ SYSTEM \ CURRENTCONTROLSET \控制\ NLS \代码页

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

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

因为您在控制台窗口中具有与Windows其余部分相同的字符编码。

答案 1 :(得分:3)

当您打印ASCII字符串时,Windows会根据当前代码页在内部将其转换为UNICODE。还有一个从UNICODE到CRT完成的“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";
}

答案 2 :(得分:2)

因为Win32控制台使用code page 437(也就是OEM字体)来呈现字符,而其余大多数Windows使用Windows-1252来表示单字节字符代码。

字符“¿”是Unicode字符INVERTED QUESTION MARK,它在Unicode,ISO 8859-1和Windows-1252中具有代码点0xBF(十进制191)。 CP437中的代码点0xBF对应于字符“┐”,即BOX图片LIGHT DOWN AND LEFT(代码点U + 2510)。

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

答案 3 :(得分:0)

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