關於 wcout 輸出中文的問題

2021-10-10 12:14:36 字數 1850 閱讀 8372

1. cout

場景1: 在原始檔中定義 const char* str = "中文" 在 vc++ 編譯器上,由於windows環境用 gbk編碼,所以字串 "中文" 被儲存為 gbk內碼,編譯器也把 str 指向乙個包含有 gbk編碼的唯讀記憶體空間(因為是const)。用 cout 輸出 str 時,由於中文windows環境用gbk編碼,所以把gbk編碼的 str 內容輸出到控制台,沒問題。 

場景2: 在linux 下編輯乙個檔案 const char* str = "中文", 由於linux普遍使用 utf8 編碼,所以在原始檔裡, "中文" 被儲存為 utf8內碼。然後在windows中開啟這個原始檔,由於windows使用gbk編碼,所以vc++ 按照gbk去解釋被儲存為 utf8 內碼的 "中文", 顯示為亂碼。

2. wcout

在原始檔中定義 const wchar_t* str = l"中文" 在 vc++ 編譯器上,由於指定了l,所以字串 "中文" 被儲存為unicode內碼(ucs2),編譯器也把 str 指向乙個包含有 unicode 編碼的唯讀記憶體空間。用 wcout 輸出 str 時, wcout 首先呼叫 wcstombs() (即根據當前 local 轉換, 如果沒有設定local,則是經典的c local, 不認識中文)把 str 的內容轉換後交給控制台,結果自然什麼都不顯示. (除錯**可以知道vc++ 2010 實現是乙個字元乙個字元輸出,呼叫 wctomb_s) 

原理

我們知道 cout 和 wcout 分別是 basic_ostream 的特化版本, 而 basic_ostream 呼叫 basic_streambuf 實際執行輸出動作,針對 wchar_t,basic_streambuf有專門的特化函式,呼叫 fputwc 輸出乙個寬字元,而 fputwc 需要呼叫 wctomb_s 把寬字元轉換後再輸出。我們知道wctomb_s 是依賴 locale 的由於預設情況下是c locale,所以用中文內碼呼叫 wctomb_s 會失敗。

解決辦法

設定當前系統的locale 替代預設的 "c" locale, 使 wctomb_s 等函式可以正常工作。

以下3種方法中的任意一種都可以達到目的。

1. c函式設定全域性locale 

setlocale(lc_all, ""); 

2. c++ 設定全域性locale 

std::locale::global(std::locale("")); 

2. 單獨為 wcout 設定乙個 locale 

std::locale loc(""); 

std::wcout.imbue(loc); 

結論

和windows api 不同 c++中的各種 w版本的類或者函式並不能提高效能,因為它們都需要用 wc..to..mb 之類的函式轉換為ansi相容編碼然後呼叫標準庫函式。

或者,如果庫函式的實現者願意,針對windows系統,寬字元的fputwc可以直接呼叫unicode版本的windows api而不用轉換。但是這些都跟c++語言本身沒有什麼關係。 

由於windows核心是unicode的,所以直接用 unicode 字串呼叫 windows api會有一點點好處。

c++設計者的出發點: 我不管你用什麼字元編碼,與c++無關,要輸出時:如果是單位元組字元或者多位元組字元,直接輸出;如果是寬字元,則根據local轉換為多位元組字元,然後再輸出。

即使將來unicode過時了(假設,假設而已),也不要緊,只要定義好新的local即可。對於c語言也是這樣。windows設計者的出發點:統一使用 unicode 寬字元,解決一切問題。

學習筆記 wcout輸出中文

include boost locale.hpp include iostream include string int main 也列印出東西,但是認為zhang.變數是個整數,而不是字串 std cout output cout zhang ucs16 5f20 zhang ucs16 5f20...

關於python中文輸出亂碼的處理

用python跟中文打交道的時候,常遇到輸出無法識別的亂碼,比如 1 亂碼 tnsnames.ora lnk 2 報錯 unicodedecodeerror ascii codec can t decode byte 0xb9 in position 23 ordinal not in range ...

關於中文亂碼的問題

關於中文亂碼 保證 charset 和 pageencoding的編碼一致,且都支援中文,通常建議取值為utf 8 還需保證了瀏覽器的顯示的字元編碼和請求的jsp頁面的編碼一致。獲取中文引數值 在獲取任何引數值之前設定,請求的字元編碼就可以了 request.setcharacterencoding...