如何最小化修改代码实现跨平台正确打印西里尔字符абв?
跨平台正确打印Unicode字符的C++最小化修改方案
嘿,这个跨平台输出Unicode字符的问题我太熟悉了!本质是Linux和Windows的控制台编码、标准流默认配置差异搞的鬼。先看看你的原代码和问题输出:
原代码
#include <iostream> int main() { std::cout << "abc" << std::endl; std::wcout << L"abc" << std::endl; std::cout << "абв" << std::endl; std::wcout << L"абв" << std::endl; return 0; }
原平台输出差异
Linux系统输出:
abc
abc
абв
012Windows系统输出(缺少最后一行):
abc
abc
рст
最小化修改后的代码
只需要加平台相关的编码配置代码,核心逻辑完全不动:
#include <iostream> #if defined(_WIN32) #include <windows.h> #endif int main() { // 统一配置控制台和标准流的编码匹配 #if defined(_WIN32) // Windows下强制控制台输出用UTF-8,同时给宽字符流绑定正确locale SetConsoleOutputCP(CP_UTF8); std::wcout.imbue(std::locale("")); #else // Linux下给宽字符流绑定系统默认UTF-8 locale即可 std::wcout.imbue(std::locale("")); #endif // 原逻辑完全保留 std::cout << "abc" << std::endl; std::wcout << L"abc" << std::endl; std::cout << "абв" << std::endl; std::wcout << L"абв" << std::endl; return 0; }
修改原因拆解
咱们逐个平台说为啥要这么改:
- Linux侧:默认
std::wcout用的是"C"locale,只会处理ASCII字符,遇到абв这种Unicode宽字符就会乱转成012。给wcout绑定系统默认的locale(一般是UTF-8),就能正确把宽字符转成控制台支持的UTF-8编码输出。而std::cout本来输出的就是UTF-8多字节字符串,Linux控制台默认支持,所以不需要额外改。 - Windows侧:
- 控制台默认用的是GBK类的本地编码,
std::cout输出的UTF-8字符串会被当成GBK解析,所以абв变成了рст。用SetConsoleOutputCP(CP_UTF8)把控制台输出编码设为UTF-8,就能让cout的输出正确显示。 - 默认的
std::wcout同样因为locale问题,无法把宽字符转成控制台编码,直接输出失败导致最后一行消失。绑定空字符串的locale(会自动匹配系统当前的UTF-8配置),就能解决宽字符流的转换问题。
- 控制台默认用的是GBK类的本地编码,
这样改完之后,两边的控制台都会正确输出四行内容:abc、abc、абв、абв,完全符合预期。
内容的提问来源于stack exchange,提问作者sigil
相关产品推荐
相关产品推荐

