2011-09-21 66 views
7

我試圖打印出wchar_t *字符串。 代碼低於:char vs wchar_t

#include <stdio.h> 
#include <string.h> 
#include <wchar.h> 

char *ascii_ = "中日友好"; //line-1 
wchar_t *wchar_ = L"中日友好"; //line-2 

int main() 
{ 
    printf("ascii_: %s\n", ascii_); //line-3 
    wprintf(L"wchar_: %s\n", wchar_); //line-4 
    return 0; 
} 

//Output 
ascii_: 中日友好 

問:

  1. 顯然我不應該分配CJK字符爲char *指針線-1,但我只是做了,而且線路輸出-3是正確的,那麼爲什麼?第3行中的printf()怎麼能給我非ascii字符?它以某種方式知道編碼嗎?

  2. 我假設第2行和第4行的代碼是正確的,但爲什麼我沒有得到任何第4行的輸出?

+0

你使用什麼編譯器? GCC默認爲大多數平臺的Utf-8。似乎是一個編碼問題給我。 – cyco130

+0

@ cyco130,是的,海灣合作委員會 – Alcott

回答

8

首先,在源代碼中使用非ascii字符通常不是一個好主意。可能發生的情況是中文字符被編碼爲UTF-8,它與ascii一起使用。

現在,至於爲什麼wprintf()不工作。這與流方向有關。每個流只能設置爲正常或寬。一旦設置,它就不能改變。它是第一次使用它。 (這是由於printf引起的ascii)。之後wprintf將不會工作,因爲方向不正確。

換句話說,一旦你使用printf()你需要繼續使用printf()。同樣,如果您以wprintf()開頭,則需要繼續使用wprintf()

您不能混合printf()wprintf()。 (除了Windows)

編輯:

回答關於爲什麼wprintf線本身並不甚至工作的問題。這可能是因爲代碼正在編譯,因此中日友好的UTF-8格式存儲在wchar_中。但是,wchar_t需要4字節的unicode編碼。 (在Windows中2個字節)

所以這是我能想到的兩個選項:

  1. 不要打擾wchar_t,只是堅持多字節char秒。這是簡單的方法,但如果用戶的系統未設置爲中文區域設置,則可能會中斷。
  2. 使用wchar_t,但您需要使用unicode轉義序列對中文字符進行編碼。這顯然會使其在源代碼中無法讀取,但它可以在任何可以打印漢字字體的機器上工作,而不管區域設置如何。
+0

如果使用unicode escape seq,我必須找出每個中文單詞的seq,對吧?這將是相當多的工作要做,:P – Alcott

+1

正確。不過,我相信這是很常見的,你可以在網上找到一個工具,你可以複製和粘貼中文文本,它會給你unicode轉義序列。爲了保持代碼的可讀性,可以將轉義序列旁邊的實際中文文本保留爲註釋。 – Mysticial

+0

感謝Mysticial – Alcott

6

第1行不是ascii,它是編譯器在編譯時使用的多字節編碼。在可能是UTF-8的現代系統上。 printf不知道編碼。它只是發送字節到標準輸出,只要編碼匹配,一切都很好。

您應該意識到的一個問題是第3行和第4行一起調用未定義的行爲。您不能在同一個FILEstdout)上混合基於字符和寬字符io。第一次操作後,FILE有一個「方向」(無論是字節還是寬),然後任何嘗試執行相反方向的操作都會導致UB。

+0

我把註釋掉了printf()行,我有一些輸出,但不是中文字符。爲什麼? – Alcott

+0

本地的編碼可能是錯誤的。 –

+0

區域設置的編碼?如何解決它? – Alcott

1

您忽略了一個步驟,因此錯誤地思考。

您在磁盤上有一個包含字節的C文件。你有一個「ASCII」字符串和一個寬字符串。

ASCII字符串將字節與第1行中的字節完全相同並輸出。 只要用戶側的編碼與程序員側的編碼相同,此功能就可以工作。

寬字符串首先將給定的字節解碼爲unicode碼點並存儲在程序中 - 也許這在您身邊出錯。在輸出時,它們根據用戶側的編碼再次編碼。這確保了這些字符按照它們的意圖發出,而不是像它們輸入的那樣。

您的編譯器會採用錯誤的編碼,或者您的輸出終端設置錯誤。