2013-03-21 71 views
3

我使用開發的C++,窗口7字符使用「爲 uXXXX」格式顯示錯誤的字符

我試圖使用打印出非ASCII字符定義:

#include <locale.h> 
#include <iostream> 
#include <cstdlib> 
#include <windows.h> 
#include <conio.h> 
#include <stdio.h> 

using namespace std; 

int main() 
{ 
    setlocale(LC_ALL,"en_US.UTF-8"); 
    char a='\u0041'; //Should display 'A' 
    cout<<a<<endl; 
    a='\u2639'; //Should display '☹' 
    cout<<a<<endl; 
    system("PAUSE"); 
} 

在這個例子中,大寫字母A顯示正確。使用wxDev,simply字符不會顯示任何內容。使用Dev(我需要用於最終的程序),我會得到一個擴展的ascii字符(這是一個與∥類似的符號,但有多個符號,看起來像這樣,我不知道它是哪一個)。

在Dev和wxDev中,☹都顯示爲?。

我在一些關於如何正確顯示unicode字符的初步搜索之後添加了setlocale,但我還沒有找到任何解決方案。

我不能使用不同的編譯器或修改系統設置來使其工作。 (是的,這是一個學校項目,不是,項目不需要特殊字符;我只是想讓它看起來更好)。如果修改這些設置無法正常工作,那也是非常有用的信息。

非常感謝您的幫助。

編輯:使用開發,不wxDev,

char a='\u0041'; //should be A 
cout<<a; 

我得到一個錯誤:\ u0041是不是有效的普遍性

如果我使用的wchar_t作爲數據類型:

wchar_t a = '\u2639'; 
cout<<a<<endl; 

輸出爲39097.

+14

'所以char a ='\ u2639''是不可能做到你想要什麼,因爲'char'(定義)是一個字節,並且'\ u2639'不能放在一個字節中(至少當一個字節是八位時,因爲它幾乎總是)。對於替代品,您可以嘗試使用谷歌搜索「寬字符」或「wchar」。 – ruakh 2013-03-21 22:01:51

回答

3

通用字符名稱(UCN)是一種將t o編譯器中要表示的角色。只要您可以將基本源字符傳送到編譯器,那麼每個編譯器都會看到相同的UCN,因此會看到您表示的是相同的字符。

這是相對於在源字面上寫字符:

char a = '☹'; 

由於編譯器只需要支持基本源字符的編譯器甚至可以是不能夠處理該代碼。它實際看到的取決於編譯器使用的源編碼。一個編譯器可能會看到你想要的字符,而另一個編譯器看到

char a = 'Â☐¹'; 

然而,僅僅是因爲UCNs能夠指定字符的編譯器並不意味着:

  • 編譯器的執行字符集包含字符或
  • 數據類型char可以表示字符值

在你的情況下,主要問題是執行字符集是沒有字符'☹'的Windows代碼頁(可能是CP1252)之一。所以當編譯器將字符'☹'轉換成執行字符集時,轉換會產生'?'而不是你想要的。

我的編譯器設置執行字符不包括字符「☹」,但它發生,所以我的編譯器說有一個多字節表示:

error: character too large for enclosing character literal type 
    char a = '☹'; 
      ^

要真正理解這個主題中,您需要了解編碼,字符集,它們如何在翻譯的C++階段中發揮作用,以及它們如何與編譯器處理字符和字符串文字有關。而且,語言環境真的與這些沒有任何關係; locales處理運行時行爲,而您的問題完全在於您的編譯器編譯時處理編碼。


在使用UTF-8無處不在以下工作平臺:

#include <iostream> 

int main() { 
    std::cout << "☹\n"; 
} 

注意上面使用字符串文字而不是字符文字,讓角色可以擴大其多字節表示。

不幸的是Windows不支持Unicode這種方式。在Windows上它更復雜:

#include <Windows.h> 
#include <cwchar> 

int main() { 
    wchar_t const *a = L"\u2639\n"; 
    DWORD numOfCharsWritten; 
    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), a, wcslen(a), &numOfCharsWritten, NULL); 
} 

不幸的是,即使上面的代碼是不太可能顯示你想要什麼,因爲在Windows控制檯通常沒有配置到能夠顯示Unicode字符「☹」。相反,您可能需要查看控制檯(可能是CP437)使用的OEM編碼,查找所需字符的編碼,然後打印出該值。例如CP437具有「☺」字代替,你可以打印出這樣的:

#include <iostream> 

int main() { 
    std::cout << "\x01\n"; // ☺ has the value 0x01 in CP 437 
} 
+0

如果你用'chcp 65001'運行控制檯,並將字體改爲比默認字體更古老的字體,不應該使用'std :: cout <<「☹\ n」;'如果源文件保存在UTF-8和編譯器可以配置爲不做任何事情嗎?它只是直接傳遞源字節,控制檯可以使用代碼頁65001解釋它們。在PHP中只有char *字符串的情況下也是這樣。 – Esailija 2013-03-23 14:25:57

+0

雖然阻止編譯器在源編碼和其執行編碼之間進行轉換(通過將文件另存爲無簽名的UTF-8),但它會工作,但會打破寬字符文字。而且沒有其他方法可以用VC++來實現。 – bames53 2013-03-24 04:30:32

+0

謝謝你的一個很好的解釋!這也是可以理解的。我會看看我是否可以修復代碼頁,但如果不能,我至少明白爲什麼它現在不起作用。 – helloworld112358 2013-03-26 12:32:54