2011-02-03 197 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字符,你需要使用不同的環境。