2011-02-03 153 views
6

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

例如:

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

输出:

┐ 
Press any key to continue . . . 
+0

似乎工作得很好,你的charsets只是不匹配。欢迎来到遗留字符集的世界,因为它似乎Windows控制台仍然(!!)不做Unicode。 – 2011-02-03 02:22:00

+0

它是否在Unicode下? – user3234 2011-02-03 02:23:22

+2

Windows控制台确实执行Unicode。确切地说,`WriteConsoleW`就是。 `WriteConsoleA`显然没有。 – MSalters 2011-02-03 08:56:44

回答

12

一个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 850是默认的控制台窗口至少挪威PC的(虽然精明的挪威人可能会更改到865)。但是,这些都不是你应该使用的代码页。

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

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

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

然后,当Microsoft制作Windows 32位时,他们采用了拉丁文-1的一个16位扩展名为Unicode。微软是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&hellip;您可以使用基于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程序,如例如做,对于一个给定的命令解释程序实例[编辑](仍然存在于Windows XP中!)会产生一些gobbledegook,因为在ANSI中没有原始的PC字符集线条绘制字符,并且因为国家字符在ANSI中具有不同的代码。但是,嘿,谁使用旧的DOS程序?不是我!

如果你想这是一个更永久的代码页,你必须通过一个未公开的注册表项以更改的控制台窗口的配置:

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

在此项中,将OEMCP更改为1252,重新启动

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

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

0

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

+2

你可以将utf-8推送到windows控制台。 – 2011-02-03 07:53:51

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

因为Win32控制台使用code page 437(又称OEM字体)来渲染人物,而大多数Windows的其余部分使用Windows-1252单字节字符代码。

字符“¿”是Unicode字符INVERTED QUESTION MARK,它在Unicode,ISO 8859-1和Windows-1252中的代码点为0xBF(191十进制)。 CP437中的代码点0xBF与字符“┐”相对应,即BOX插图灯向下和左(代码点U + 2510)。

只要你使用Windows控制台,可以只显示在CP437而不是其他的字符。如果你想显示其他的Unicode字符,你需要使用不同的环境。