一個特殊的亂碼問題?

輸出中文會亂碼

但是如果在中文前加任意字母,如下圖

這樣就很奇怪了

另:我的原文件編碼用的是windows-936也就是GBK

小白久試無果,查閱了各種博客依舊無用。


VC++下無法重現,顯然不是cmd的bug,所以我懷疑是mingw的問題。題主也不要聽其他人胡說,同時不要在Windows使用一些,本來為了Linux開發的,然後被一些不是很明白Windows的程序員強行移植到Windows的工具。

還有,這跟你cpp文件用什麼編碼保存是沒有關係的。你不要把cpp文件的編碼、編譯器認為的cpp文件的編碼、和字元串編譯之後在內存中的表示的編碼,這三個東西混在一起。我發現很多自認為明白編碼的程序員都會犯下這種奇怪的錯誤,不知道為什麼。

如果你用的是VC++,不管你cpp文件用的是什麼編碼保存,只要你工程文件的配置沒有變,「這是一條測試語句」在內存中的表示是沒有區別的。


截至9/15,最新的Windows應該已經沒了這個bug,題主可以試試更新系統。

1703也有好幾個版本,以下1703都是指最早的1703創意者更新版本,如果想復現題主的問題的話可以去裝一個最早的1703。

這裡首先提供兩個連接

Windows 1703 update後CMD和powershell終端對字元串的顯示bug(已測,1607無此bug)

Windows 10 1703環境下,VS2017輸出中文存在問題?

這個問題是當時1703創意者更新後開始出現的,微軟對cmd進行了一些操作,可以認為是cmd的bug。

無論是cb自帶的那個mingw還是mingw64我都試過了,是一樣的,當然MSVC沒問題。

為什麼我這麼清楚呢?

當時我手裡有兩台電腦,一台1607,一台1703,同一個exe在1607的機子正常輸出但是在1703上就跟題主的現象一致,而且輸出內容(二進位)是完全一致的(此處記不清了,應該是一致)。

那麼微軟在1703究竟對cmd修改了嗎?

答案是肯定的。在1607中cmd有個經典的bug,就是如果你切到任意一種非英文輸入法,然後向下滾動,輸入法的名字會跟隨著你的下拉一直向上刷新,而不是乖乖的停留在左下角,這個問題1703修復了。

那麼在1703下用MinGW怎麼避免?

在程序開始的時候使用chcp指令切換到unicode代碼頁,然後全部用std::string構造中文字元串,採用cout輸出,可以正常輸出中文。但是這樣做反而會在1607下亂碼。

我當時不得已用#ifdef寫了一份代碼來區分兩個版本的系統。

(此處提一下,還是應該用wcout和wchar來處理中文)

那如何根本性解決?

  • VS大法好。
  • 更新系統。

9.22 想到點東西回來補充一下

其實正確方法還是應該先setlocale然後用wprintf來搞

wcout也應該設置imbue後再輸出。

給兩個參考

ios_base::imbue - C++ Reference

wprintf - C++ Reference

在1607中本來shift+右鍵打開的是cmd,在1703中變成了powershell,可以認為微軟其實是故意搞個bug強推一波ps(逃


抱歉,這可能不是你想要的答案:

我知道這裡容易產生坑,所以我文件編碼一定會用utf8而不是gbk,而且我一般會在linux下編程。

所謂君子不立於危牆之下。我希望你自己從危牆下面走出來,而不是別人走到危牆下去幫你。


盡量強制啟用UTF-8


這應該是 cmd 的 bug 。(似乎有誤)

以下用 2 位十六進位數表示一個位元組值,不能識別的位元組以 ?? 表示。

"這是一條測試語句"用 GBK 編碼為

D5 E2 CA C7 D2 BB CC F5 B2 E2 CA D4 D3 EF BE E4

"這且惶醪饈雜錁?"用 GBK 編碼為

D5 E2 C7 D2 BB CC F5 B2 E2 CA D4 D3 EF BE ??

(推測最後一個位元組其實是 E4)

可以看出顯示時不知為何跳過了一個位元組,導致後面的內容全部分析錯誤。

UTF-8 編碼表現會好不少,如果多跳了一個位元組,就只會毀一個字而不是毀整句。

不過 UTF-8 也只能緩解問題。我想暫時只有拿別的東西替換掉 cmd 才能解決顯示錯誤。

(或者換用更適合的開發環境)

更新:之前判斷應該有誤。

現在看來可能不是 cmd 的 bug ,而是 MinGW 鏈接的 msvcrt.dll 導致的問題。

另外是否打開 sync_with_stdio 也有影響,關閉時也出了問題。

(打開時 xsputn 使用 fwrite 寫入,關閉時用另外的工具)


在本人的機子上無法復現(IDE:Dev-C++,所用編譯器:TDM-GCC 4.9.2),題主可以嘗試更新系統。

在剛更新 Creater Update 時確實有這樣的 bug,在 MSVC 下的話則是每個漢字後都會多一個空格。當時的解決方案是改用舊版控制台,操作如下:

對控制台右鍵——屬性(或默認值)——單擊「選項」——勾選「使用舊版控制台(需要重新啟動)」。保存後重啟即可。更改後 CMD 的字體會變回默認字體(如果你之前有設定過 CMD 的字體)


這個么,先用十六進位編輯工具看看文件內容,這樣比較好分析。


編譯器默認用的utf8,但是你保存的是GBK,所以_(:з」∠)_

題主用的codeblock吧,這個問題我也遇見過,百度可以解決的。


#pragma execution_character_set("utf-8")


盡量不要在代碼中出現中文,除非你很了解各種編碼和這門編程語言。

你看代碼里中文下面的紅線多麼刺眼。


推薦閱讀:

計算機系統是如何顯示一個字元的?
GB2312、GBK、GB18030 這幾種字符集的主要區別是什麼?
為什麼有時候"元"(yuan)字會變成"刀"(dao)字?
顏文字使用的都是哪些編碼?裡面都有哪些國家的文字?

TAG:字元編碼 | UTF-8 | 編譯器 | Code::Blocks | 中文亂碼 |