亂碼原因
直接先用一段話講亂碼原因,看不懂老老實實就往下看吧
其實我用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編碼啊什么的,可能搞錯了問題的方向,不過也算一個方法吧,但似乎對我不適用。我之前也是搞錯了方向。
如下圖所示,我們運行的可執行文件,也就是那個彈出來的控制台,它的編碼是GBK。現在我們應該知道亂碼的原因了。
整個過程是這樣的:
- 我們代碼的編碼是UTF-8
- 把UTF-8編碼的代碼交給mingw,它也默認當做UTF-8處理(目前為止這是正確的)
- mingw處理后生成的數據還是UTF-8編碼(目前為止還是正確的)
- 把mingw處理后的數據(UTF-8編碼)給cmd(目前為止也是正確的)
- cmd按GBK編碼處理它(UTF-8),這時出現錯誤,所以出現亂碼
解決方案
我們可以修改mingw的輸出,讓它在編譯時使用GBK編碼輸出,然后再讓CMD去顯示。
處理中文亂碼只需要設置兩個(核心只有一個)編譯參數,即在tasks.json
中tasks
中的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
參考鏈接
作者:@臭咸魚
轉載請注明出處:https://www.cnblogs.com/chouxianyu/
歡迎討論和交流!