mingw控制台中文亂碼


亂碼原因

直接先用一段話講亂碼原因,看不懂老老實實就往下看吧

其實我用Sublime或者VSCode等編輯器寫代碼出現的控制台中文亂碼問題是編譯器mingw輸出的數據使用的是UTF-8編碼,而控制台用了GBK編碼來解析它

其實編碼只要統一,用UTF8或者GBK都行,但用了錯誤的編碼去解析文件就會出錯。

問題來源

如果我們寫輕量代碼(比如寫算法題)也用VS之類的IDE,就太不划算了;雖然也有Codeblocks、Dev C++這樣的小一點的IDE,但用起來還是可以發現讓人很不爽的缺點。

之前嘗試用VS Code寫C++代碼,挺不錯的,好看方便。但問題就是難配置,最大的問題是控制台中文亂碼,我搞了好久都沒搞好,今天終於解決了。

在網上找到一段話是這么講的:

Windows(中文)默認的字符集是Windows-936(GBK),mingw的內部是GCC,而GCC編譯器默認編譯的時候是按照UTF-8解析和輸出的,當未指定字符集時一律當作UTF-8進行處理,於是造成亂碼。

根據上邊這段話,我有點靈感,但還是有疑問,見下。

問題分析

我電腦的CMD編碼設置的是UTF-8,代碼文件的編碼也是UTF-8,如果mingw默認按UTF-8處理的話,可以看到這里用的編碼全都是UTF-8,那應該不會出現亂碼的。

但我們確實看到了亂碼啊!?

當我去看我的注冊表(見下圖),發現代碼鏈接、編譯后生成的可執行文件有一個單獨的注冊表,這似乎說明我們運行的可執行文件並不是我們口中的那個CMD(按Win+R、cmd打開的那個CMD)。所以@roadwide整理的網上的改CMD編碼啊什么的,可能搞錯了問題的方向,不過也算一個方法吧,但似乎對我不適用。我之前也是搞錯了方向。
Console注冊表.png

如下圖所示,我們運行的可執行文件,也就是那個彈出來的控制台,它的編碼是GBK。現在我們應該知道亂碼的原因了。

可執行文件編碼.png

整個過程是這樣的:

  1. 我們代碼的編碼是UTF-8
  2. 把UTF-8編碼的代碼交給mingw,它也默認當做UTF-8處理(目前為止這是正確的)
  3. mingw處理后生成的數據還是UTF-8編碼(目前為止還是正確的)
  4. 把mingw處理后的數據(UTF-8編碼)給cmd(目前為止也是正確的)
  5. cmd按GBK編碼處理它(UTF-8),這時出現錯誤,所以出現亂碼

解決方案

我們可以修改mingw的輸出,讓它在編譯時使用GBK編碼輸出,然后再讓CMD去顯示。


處理中文亂碼只需要設置兩個(核心只有一個)編譯參數,即在tasks.jsontasks中的args中添加-fexec-charset=GBK-finput-charset=UTF-8,下邊tasks.json中的第14、15行。


這個解決方案中代碼文件的編碼是UTF-8,控制台編碼是GBK,令mingw實現編碼轉換。

下面的.vscode配置是我在網上找到的比較新的VS Code配置,可以作為參考,具體不做解釋,想了解可以去看文章末的參考網址。

tasks.json

// 用來編譯
{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [{
        "label": "Build",   // 任務的名字叫Build(編譯),注意是大小寫區分的,等會在launch中調用這個名字
        "type": "shell",    // 任務執行的是shell命令
        "command": "g++",   // 命令是g++
        "args": [           //參數
            "-g",           // 調試
            
            //
            "-fexec-charset=GBK",   // 處理mingw中文編碼問題
            "-finput-charset=UTF-8",// 處理mingw中文編碼問題
            //
            
            "${file}", //當前文件路徑,包括所在目錄絕對路徑和文件名
            "-o",      //對象名,不進行編譯優化
            "${fileDirname}/exes/${fileBasenameNoExtension}.exe", //當前目錄下exes文件夾下的exe文件,exe文件名為 當前文件名(去掉擴展名).exe
        ],
        // 所以以上部分,就是在shell中執行下面這行語句(以我E盤中一個main.cpp為例)
        // g++ -g  -fexec-charset=GBK -finput-charset=UTF-8 e:\Study\Programming\Code\Algo\PTABasicLevelCPP\main.cpp -o e:\Study\Programming\Code\Algo\PTABasicLevelCPP/exes/main.exe
        "group": {
            "kind": "build",
            "isDefault": true
            // 任務分組,tasks是個數組,意味着可以執行多個task
            // 在build組的任務們,可以通過在Command Palette(F1) 輸入run build task來運行
            // 當然,如果任務分組是test,你就可以用run test task來運行 
        },
        "problemMatcher": [
            "$gcc" // 使用gcc捕獲錯誤
        ],
    }]
}

-fexec-charset=GBK是令mingw按GBK編碼生成exe文件。

-finput-charset=UTF-8是令mingw按UTF-8編碼處理。(經測試這個參數可以不設置)

launch.json

{
    "version": "0.2.0",
    "configurations": [

        {
        "name": "C++ Launch (GDB)", // 調試時程序員看到的名字
        "preLaunchTask": "Build",   // launch之前會運行的任務,這個名字一定要跟tasks.json中的任務名一致
        "type": "cppdbg",           // 經測試,不可刪除
        "request": "launch",        // 經測試,不可刪除
        "program": "${fileDirname}/exes/${fileBasenameNoExtension}.exe", //運行當前打開文件的目錄下exes文件夾中名字和當前文件相同,但擴展名為exe的程序
        "args": [],                 // 運行程序是默認是沒有參數的
        "stopAtEntry": false,       // 選為true則會在打開控制台后停滯,暫時不執行程序
        "cwd": "${workspaceFolder}",// 當前工作路徑:當前文件所在的工作空間
        "environment": [],
        "externalConsole": true,    // 是否使用外部控制台,
        "MIMode": "gdb",
        "miDebuggerPath": "D:\\WorkingSoftware\\MinGW\\bin\\gdb.exe",   //調試器路徑
        "setupCommands": [{
            "description": "Enable pretty-printing for gdb",
            "text": "-enable-pretty-printing",
            "ignoreFailures": true
        }]
    }]
}
// https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations
// author: huihut
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team        
// ${file}: the current opened file                     
// ${fileBasename}: the current opened file's basename 
// ${fileDirname}: the current opened file's dirname    
// ${fileExtname}: the current opened file's extension  
// ${cwd}: the current working directory of the spawned process

參考鏈接

中文亂碼參考1

中文亂碼參考2

VS Code配置參考


作者:@臭咸魚

轉載請注明出處:https://www.cnblogs.com/chouxianyu/

歡迎討論和交流!



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM