C++ std::wcout 输出乱码
遇到问题
最近使用 C++ 遇到了中文处理问题,今天下午想测试 C++ 宽字符使用时,发现如下程序并不能如愿输出汉字。
1 | int main() |
在网上多处搜索处理方法后仍不能解决,于是自己探索了一波。收获蛮大的,于是记录下。
该文章程序及结果皆在 Linux 环境下。
结论
结论是我在一些程序中总结出来的,其中若有错误,希望指正。
- Linux 下
printf
和wprintf
不能混用,即同时使用。具体原因可自行搜索,网上有很多资料。 - C++ 中默认情况下
std::cout
与std::wcout
分别与printf
和wprintf
同步,维护共同缓冲区。为方便理解,我们可以假设std::cout
调用printf
,std::wcout
调用wprintf
(这里只是假设,方便我们理解)。 - 综合上述 1、2 两条,可知在开启
sync_with_stdio
情况下std::cout
及std::wcout
不能混用。 先使用std::cout
后使用std::wcout
会造成std::wcout
输出乱码,先使用std::wcout
的话std::cout
压根不能输出东西。 关闭情况下两者可混用。 - C 语言库中设置
locale
函数为setlocale()
, C++ 语言库中设置std::locale
函数为std::locale::global()
。可认为 C 语言库和 C++ 库分别有不同的locale
。setlocale()
函数仅设置 C 语言中的locale
,而std::locale::global()
函数两者都会设置。 - 开启
sync_with_stdio
情况下,可认为std::cout
与std::wcout
使用的是 C 语言中的locale
。而关闭情况下则使用 C++ 自己的std::locale
。 std::wcout
输出中文时依靠地区locale
,故我们在使用其输出中文之前要设置locale
。- 在开启
sync_with_stdio
情况下,想用std::wcout
输出汉字要设置 C 语言中的locale
,使用两种方法都可以。而关闭情况下,只能使用 C++ 的方法,且要在关闭同步之前设置,也可以使用std::wcout.imbus( std::locale("") )
单独设置。
其他收获
std::cout
中 c 表示字符,std::wcout
中 wc 表示宽字符。
测试程序
这里展示部分测试程序及运行结果(Ubuntu 下),测试程序可根据结论中的几点自行结合测试。
开启 sync_with_stdio (默认)
1 | int main() |
??????
“你能输出中文” 共 6 个汉字,输出中共 6 个问号。 wstr
中有多少个汉字,输出中就多少个 ?
1 | int main() |
你能输出中文
1 | int main() |
你好
wcout 输出乱码
1 | int main() |
??????
cout
并不会输出
关闭 sync_with_stdio
1 | int main() |
输出为空
1 | int main() |
你能输出中文?
1 | int main() |
你好
1 | int main() |
你好
你能输出中文?