C++字符有四个类型,char是1字节,wchar_t可能是2字节或4字节,char16_t和char32_t顾名思义。char和wchar_t是C++98就有的,支持也最好。char16_t和char32_t是C++11加入的,直到现在也没有很好的支持。
由于emoji这种东西的出现,支持Windows-1252/GBK/Big5已经不够用了,要支持Unicode。但是Windows中char编码是定死的,不支持Unicode。要想支持Unicode,不是说其它方法不行,而是使用wchar_t作为字符类型是最方便的做法。
iostream宽字符流对象,虽然在Windows下不支持Unicode,但是它们是写作wchar_t程序的必备武器,这是因为字符输入输出是最简单常用的程序交互形式,它们可进行编码自动转换,解决了wchar_t的交互问题,并且所有平台都有提供,不需要学习平台相关的API。
但是iostream库在Linux下有一个坑,默认情况下wcout和cout不能混用。这是因为受到Linux下的C语言stdio.h库的掣肘:
不过实际上,只要提前调用了ios::sync_with_stdio(false),wcout和cout便不会通过stdio.h进行输入输出,而是自己管理缓冲区,就避免了wcout和cout不能混用的问题。
#include <iostream>
#include <locale>
using namespace std;
int main()
{
// 不使用stdio.h进行输入输出,避免Linux/macOS下libc的宽窄流限制
ios::sync_with_stdio(false);
// 设置locale
locale::global(locale(""));
cout.imbue(locale());
wcout.imbue(locale());
// 现在可以混用cout和wcout了
cout << "Hello, 窄 world!" << endl;
wcout << L"Hello, 宽 world!" << endl;
return 0;
}
</locale></iostream>
如果只更改编码,不更改区域格式的话:
locale::global(locale(locale("C"), new codecvt_byname<wchar_t, char, mbstate_t>("")));
</wchar_t,>
实际测试中,Ubuntu 16.04下的GCC和Windows下的Visual C++ 2017、Visual C++ 2008、Mac OS X 10.11下的Clang均通过了测试,正确输出了两个字符串。
一些非常老的Mac OS X可能会报locale("")错误,但是现在所有新版Mac OS X或macOS都是用的Clang编译器,已完全不存在这个问题。
Visual C++ 2005比较特殊。这个版本的iostream本身就有bug,只要设置locale以后cout和wcout就都没办法输出中文字符串了,不过只对控制台是有bug的,对文件没有。因此如果要兼容这个版本的话,最好配合ReadConsole/WriteConsole使用。不过,大部分情况下,我们都可以改用Visual C++ 2008来解决这个问题。
Ubuntu 16.04下的GCC输出结果(Mac OS X 10.11下的Clang差不多,从略):
pc@DESKTOP-PNUCILD:~$ g++ abc.cpp
pc@DESKTOP-PNUCILD:~$ ./a.out
Hello, 窄 world!
Hello, 宽 world!
pc@DESKTOP-PNUCILD:~$
Windows 10 Build 15063下Visual C++ 2017输出结果:
D:\>cl /EHsc abc.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.10.25019 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
abc.cpp
Microsoft (R) Incremental Linker Version 14.10.25019.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:abc.exe
abc.obj
D:\>abc
Hello, 窄 world!
Hello, 宽 world!
D:\>
Windows 10 Build 15063下Visual C++ 2008输出结果:
D:\>cl /EHsc abc.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
abc.cpp
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
/out:abc.exe
abc.obj
D:\>abc
Hello, 窄 world!
Hello, 宽 world!
D:\>
Windows 10 Build 15063下Visual C++ 2005输出结果:
D:\>cl /EHsc abc.cpp
用于 80x86 的 Microsoft (R) 32 位 C/C++ 优化编译器 14.00.50727.42 版
版权所有(C) Microsoft Corporation。保留所有权利。
abc.cpp
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.
/out:abc.exe
abc.obj
D:\>abc
Hello, Hello,
D:\>abc > abc.txt
D:\>type abc.txt
Hello, 窄 world!
Hello, 宽 world!
D:\>
[修改于 7年7个月前 - 2017/06/13 01:01:55]