一文帶你徹底搞定C++中文輸出亂碼的問題
1. 問題背景
今天在群里看到一段挺有趣的 C++ 代碼,用模板方法模式描述傳統(tǒng)放羊娃與現(xiàn)代放羊娃的一生:
每天放羊 → 賣羊賺錢 → 結(jié)婚 → 生孩子 → 孩子繼續(xù)放羊……
代碼寫得沒毛病,可一運行,終端里卻蹦出一堆“口口口”或“燙燙燙”的亂碼。
很多同學(xué)第一反應(yīng)是“是不是代碼寫錯了?”
其實,90% 的 C++ 中文亂碼都不是代碼問題,而是“編碼不一致”導(dǎo)致的顯示錯位。
2. 復(fù)現(xiàn)場景
把簡化后的代碼貼出來,方便大家復(fù)現(xiàn):
#include <iostream>
int main() {
std::cout << "每天放羊..." << std::endl;
std::cout << "賣羊賺錢..." << std::endl;
std::cout << "用錢娶媳婦..." << std::endl;
return 0;
}期望輸出:
每天放羊...
賣羊賺錢...
用錢娶媳婦...
實際輸出(Windows 默認(rèn) cmd):
ÿþÿÿÿÿÿÿÿÿ...
¡¡¡¡...
ÓÃǮȢϱ¸¾...
3. 亂碼成因
一句話總結(jié):“源文件編碼” ≠ “控制臺編碼”。
| 環(huán)節(jié) | 常見編碼 |
|---|---|
| 源文件(.cpp) | UTF-8(無 BOM) |
| Windows 控制臺 | 默認(rèn)代碼頁 936(GBK) |
當(dāng)編譯器把 UTF-8 下的 每(0xE6 0xAF 0x8F)原封不動地交給控制臺時,控制臺按 GBK 去解碼,于是 0xE6AF 被當(dāng)成一個 GBK 字符,自然面目全非。
4. 解決方案
方案一:讓控制臺使用 UTF-8(推薦)
在 main() 里加兩行,僅 Windows 有效:
#ifdef _WIN32
#include <cstdlib>
#endif
int main() {
#ifdef _WIN32
system("chcp 65001"); // 切到 UTF-8 代碼頁
#endif
std::cout << "每天放羊..." << std::endl;
...
}- 優(yōu)點:undefined• 不改源文件編碼,跨平臺無感;undefined• VS / VSCode / CLion 通用;undefined• 不影響后續(xù)移植到 Linux/macOS。
- 注意事項:undefined• 需確保源文件保存為 UTF-8 無 BOM(VSCode / CLion 默認(rèn)即可)。undefined• Windows 7 以下老系統(tǒng)可能在
chcp 65001后字體缺失,需手動把控制臺字體改成“Lucida Console”或“Consolas”。
方案二:讓源文件使用 GBK
用記事本 / VSCode / CLion 把 .cpp 另存為 → 編碼選 GBK/ANSI。
無需改動代碼,直接編譯運行即可。
缺點:undefined• 換到 Linux/macOS 或 CI 環(huán)境容易再次亂碼;undefined• 團隊協(xié)作時需統(tǒng)一編碼;undefined• 與 CMake、Clang-Tidy 等工具鏈默認(rèn) UTF-8 沖突。
方案三:IDE 一鍵設(shè)置
| IDE | 操作路徑 |
|---|---|
| Visual Studio 2022 | 文件 → 另存為 → 保存按鈕下拉 → “編碼保存” → 簡體中文(GB2312) |
| VSCode | 右下角“UTF-8” → 重新打開帶編碼 / 另存為帶編碼 → GB2312 |
| CLion | Settings → Editor → File Encodings → Global/Project Encoding → GBK |
5. 完整示例(方案一)
#include <iostream>
#ifdef _WIN32
#include <cstdlib>
#endif
class ShepherdBoyLife {
public:
void liveLife() {
herdSheep();
sellSheep();
marry();
haveChild();
childGrowsUp();
}
virtual ~ShepherdBoyLife() = default;
protected:
void herdSheep() { std::cout << "每天放羊...\n"; }
void sellSheep() { std::cout << "賣羊賺錢...\n"; }
virtual void marry() = 0;
virtual void haveChild() = 0;
void childGrowsUp() {
std::cout << "孩子長大了...\n";
}
};
class TraditionalShepherdBoy : public ShepherdBoyLife {
protected:
void marry() override { std::cout << "用錢娶媳婦...\n"; }
void haveChild() override { std::cout << "生兒育女...\n"; }
};
int main() {
#ifdef _WIN32
system("chcp 65001 > nul");
#endif
std::cout << "=== 傳統(tǒng)放羊娃的一生 ===\n";
TraditionalShepherdBoy boy;
boy.liveLife();
return 0;
}6. 延伸閱讀
- Windows 代碼頁一覽:
chcp 936(GBK)、chcp 65001(UTF-8)。 - C++20 起可用
std::format+std::print直接輸出 UTF-8,跨平臺更省心。 - Linux/macOS 終端默認(rèn) UTF-8,一般無需額外設(shè)置。
到此這篇關(guān)于一文帶你徹底搞定C++中文輸出亂碼的問題的文章就介紹到這了,更多相關(guān)C++中文輸出亂碼解決內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++分析類的對象作類成員調(diào)用構(gòu)造與析構(gòu)函數(shù)及靜態(tài)成員
終于到了對象的初始化和清理的最后階段了,在這里分享一個cpp里有多個類時,一個類的對象作為另一個類成員的時候構(gòu)造函數(shù)和析構(gòu)函數(shù)調(diào)用的時機。還有一個靜態(tài)成員也是經(jīng)??嫉降狞c,在這篇博客將會詳解其概念并舉出案例鞏固,讓我們開始2022-05-05
OpenCV獲取圖像中直線上的數(shù)據(jù)具體流程
對圖像進(jìn)行處理時,經(jīng)常會有這類需求:客戶想要提取出圖像中某條直線或者ROI區(qū)域內(nèi)的感興趣數(shù)據(jù),進(jìn)行重點關(guān)注,怎么操作呢,下面小編通過實例代碼介紹下OpenCV獲取圖像中直線上的數(shù)據(jù),一起看看吧2021-11-11
C語言中的fscanf()函數(shù)與vfscanf()函數(shù)使用
這篇文章主要介紹了C語言中的fscanf()函數(shù)與vfscanf()函數(shù)使用,是C語言入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-08-08

