显示扩展的ASCII字符

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

例如:

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

输出:

 ┐ Press any key to continue . . . 

Solutions Collecting From Web of "显示扩展的ASCII字符"

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

但是,对于每个字符的单个字节(也可能对于某些可变长度编码),I / O Windows将自动转换为控制台窗口的活动代码页 。 如果控制台窗口是一个[cmd.exe]实例,那么你可以通过命令chcp来检查,这是修改代码页的缩写。 喜欢这个:

 C:\ test> chcp
有效代码页:850

 C:\ test> _

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

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

当微软创建16位Windows时,他们选择了另一种在Windows中称为ANSI的编码。 原来是ISO Latin-1的延伸,这在很长一段时间是互联网上的默认设置(然而,不清楚哪一个是第一个:微软参与了标准化)。 这个原始的ANSI现在被称为Windows ANSI Western

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

然后,当微软制造Windows 32位时,他们采用了称为Unicode的Latin-1的16位扩展。 微软是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支持)。 但是,这是毫无意义的。 也许这是一些政治上的妥协,但无论如何,即使这样做有意义,那么它“应该”在逻辑上帮助这一点。

那么挪威新手程序员如何得到“blåbærsyltetøy”呢?

那么,只需将活动代码页更改为ANSI即可。 由于在大多数西方国家的个人电脑上,ANSI是代码页1252,所以你可以通过给定的命令解释器实例来做到这一点

 C:\ test> chcp 1252
有效代码页:1252

 C:\ test> _

现在老的DOS程序(如Windows XP仍然存在)会生成一些gobbledegook,因为原来的PC字符集的线条绘制字符不在ANSI中,而且由于国家字符在ANSI中有不同的代码。 但是,嘿,谁使用旧的DOS程序? 不是我!

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

HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \控制\ NLS \代码页

在此键中,将OEMCPOEMCP为1252,然后重新启动

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

由于您在控制台窗口中的字符编码方式与Windows的其他部分相同。

当您打印一个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"; } 

由于Win32控制台使用代码页437 (aka 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字符,你需要使用不同的环境。

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