博客 / 詳情

返回

VSCode + GCC編譯器(MinGW)開發環境中文字符亂碼問題踩坑與解決辦法

@[toc]

問題背景

在較長一段時間裏,C/C++開發者所使用的集成開發環境(IDE)要麼是比較重量級的VS(Visual Studio),要麼是Codeblocks·、·Visual C++ 6.0等輕量級IDE,又或者是諸如notepad++、sublime text等文本編輯器+GCC編譯器+命令行工具的組合式開發環境。這幾種開發方式要麼太過龐大比較吃硬件資源,比如VS動輒就要佔用幾十個G的硬盤空間,要麼雖然輕量但是沒有友好的代碼提示和自動化的編譯鏈接運行過程,開發體驗並不是很友好。

近幾年來,隨着VSCode(Visual Studio Code)的流行,越來越多的開發者選擇以此來作為個人的集成開發環境。使用VSCode開發C/C++程序可以下載安裝VSCode官方的C/C++ for Visual Studio Code插件實現開發過程中的代碼提示、調試、運行等功能,但是需要自行安裝C/C++編譯器,筆者是用的是GCC編譯器MinGW。具體開發環境的搭建過程在此不作講解,本文關注點在於開發過程中遇到的中文字符相關的亂碼問題。

問題描述

測試代碼

  1. 英文字符串文本文件 es_src.txt

    Chinese
  2. 中文字符串文本文件 ch_src.txt

    中文
  3. main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main()
    {
     char str_es[] = "Chinese";
     char str_ch[] = "中文";
     char str[30];
    
     // 讀英文字符串的文本文件測試
     printf("讀文件測試:\n");
     FILE *fpr_es = fopen("es_src.txt", "r");
     while (fgets(str, 30, fpr_es) != NULL)
     {
         printf("strcmp(%s, %s)=%d\n", str_es, str, strcmp(str_es, str));
     }
     fclose(fpr_es);
    
     // 直接打印含中文字符串測試
     printf("請輸入英文字符串“Chinese”:\n");
     // 讀入英文字符串
     scanf("%s", str);
     printf("直接打印測試:\n");
     // 直接打印英文字符串
     printf("str=%s\n", str);
     // 與英文字符串常量進行比較
     printf("strcmp(%s, %s)=%d\n", str_es, str, strcmp(str_es, str));
    
     // 英文字符串寫入文件測試
     printf("寫文件測試:\n");
     FILE *fpw_es = fopen("es_tar.txt", "w");
     fprintf(fpw_es, "%s\n%s\n", str_es, str);
     fclose(fpw_es);
     printf("寫入完成!\n");
    
     // 讀中文字符串的文本文件測試
     printf("讀文件測試:\n");
     FILE *fpr_ch = fopen("ch_src.txt", "r");
     while (fgets(str, 30, fpr_ch) != NULL)
     {
         printf("strcmp(%s, %s)=%d\n", str_ch, str, strcmp(str_ch, str));
     }
     fclose(fpr_ch);
    
     // 直接打印中文字符串測試
     printf("請輸入中文字符串“中文”:\n");
     // 讀入中文字符串
     scanf("%s", str);
     printf("直接打印測試:\n");
     // 直接打印中文字符串
     printf("str=%s\n", str);
     // 與中文字符串常量進行比較
     printf("strcmp(%s, %s)=%d\n", str_ch, str, strcmp(str_ch, str));
    
     // 中文字符串寫入文件測試
     printf("寫文件測試:\n");
     FILE *fpw_ch = fopen("ch_tar.txt", "w");
     fprintf(fpw_ch, "%s\n%s\n", str_ch, str);
     fclose(fpw_ch);
     printf("寫入完成!\n");
    
     system("pause");
     return 0;
    }

    測試結果

  4. 控制枱輸出結果
    可以看到
    (a) 從文件中讀取英文字符串並打印可以正常顯示;直接打印英文字符串常量和直接打印從鍵盤讀入的英文字符串均正常顯示,使用strcmp進行比較結果為0。
    (b) 從文件中讀取中文字符串並打印可以正常顯示;直接打印中文字符串常量可以正常顯示,但是沒有顯示出從鍵盤讀入的中文字符串,使用strcmp進行比較結果也不為0。
    在這裏插入圖片描述
讀文件測試:
strcmp(Chinese, Chinese)=0 
請輸入英文字符串“Chinese”:
Chinese
直接打印測試:
str=Chinese
strcmp(Chinese, Chinese)=0
寫文件測試:
寫入完成!
讀文件測試:
strcmp(中文, 中文)=0      
請輸入中文字符串“中文”:  
中文
直接打印測試:
str=
strcmp(中文, )=1
寫文件測試:
寫入完成!
Press any key to continue . . .
  1. 英文字符串文本文件 es_tar.txt
    英文字符串常量和從鍵盤讀入的英文字符串均正常寫入到文件中。

    Chinese
    Chinese
    
  2. 中文字符串文本文件 ch_tar.txt
    中文字符串常量正常寫入到文件,而從鍵盤讀入的中文字符串寫入到文件中的是亂碼

    中文
    
    

    現象描述

    在使用VSCode + MinGW作為集成開發環境時,在不修改默認設置的情況下執行有中文字符的字符串操作時,通常會遇到以下幾個問題:

  3. 直接打印含中文字符的字符串常量,比如printf("中文")或者printf("%s", "中文"),均可正常顯示;但是打印由鍵盤讀入的含中文字符的字符串時,如scanf("%s", str); printf("%s", str);,含中文字符的字符串str無法正常顯示(不顯示,或者顯示為亂碼)。
  4. 在讀文件操作中,可以成功讀入文本文件中的中文字符串,並且與中文字符串常量比較結果相等;但是在寫文件操作中,寫入文件的中文字符串常量能正常顯示,但是由鍵盤讀入的中文字符串則無法正常顯示(不顯示,或者顯示為亂碼)。

簡而言之,從鍵盤讀入的中文字符串無法正常顯示和寫入文件

問題分析

已知信息:

  1. Windows(中文)默認的字符集是Windows-936(GBK)。
  2. 默認配置下,VSCode使用其內置集成終端運行編譯後的exe可執行文件,使用chcp命令可知此終端使用的字符集編碼是65001,即UTF-8編碼。
  3. 默認配置下,VSCode中新建的文件使用的編碼也是UTF-8。
  4. 默認配置下,GCC編譯器MinGW的內部默認編碼是UTF-8。
    可能的原因:
    由鍵盤讀入的中文字符串使用的是GBK編碼,但是程序運行過程中使用的都是UTF-8編碼。

    解決方案

    既然讀入的中文字符是GBK編碼無法修改,那就把其他相關的地方全都改成gbk編碼即可。

    修改默認配置

    1. 已經存在的文件全部使用gbk編碼重新保存。

    修改文件編碼1
    修改文件編碼2

    2. 在工程目錄下新建.vscode目錄,如果已存在則跳過此步驟。
    3. 在.vscode目錄中新建settings.jsonlaunch.json兩個文件,已有則跳過。
    4. settings.json文件添加以下內容,使文件全部變成gbk編碼:
    {
     "files.encoding": "gbk"
    }
    5. launch.json中修改以下內容,使用外置控制枱運行編譯後程序:
    {
     "configurations": [
         {
             ...
             "externalConsole": true,
             ...
         }
     ],
     "version": "2.0.0"
    }

修改後測試代碼的運行結果

  1. 控制枱輸出
    運行結果

    讀文件測試:
    strcmp(Chinese, Chinese)=0
    請輸入英文字符串“Chinese”:
    Chinese
    直接打印測試:
    str=Chinese
    strcmp(Chinese, Chinese)=0
    寫文件測試:
    寫入完成!
    讀文件測試:
    strcmp(中文, 中文)=0
    請輸入中文字符串“中文”:
    中文
    直接打印測試:
    str=中文
    strcmp(中文, 中文)=0
    寫文件測試:
    寫入完成!
    請按任意鍵繼續. . .
  2. es_tar.txt

    Chinese
    Chinese
    
  3. ch_tar.txt

    中文
    中文
    

以上為全部內容,歡迎批評指正。

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.