关于乱码,没遇到皆大欢喜,遇到了头痛不已。在Visual Studio中程序遇到乱码,需要明确三个概念,那么问题就好解决了。
三个字符集概念
源码字符集
MSVC中/source-charset
即源代码文本文件的字符集,NodePad++、记事本、VS Code这样类似的文本编辑器,可以打开源文件看一下你的字符集(文件编码)。
源代码文本文件是以二进制的形式存在硬盘里的,无论中文英文都一样,当你输入一个汉字后保存关闭,这个汉字就会按照你指定的字符集转换成二进制编码保存下去的,当你在以这个格式打开文件时候,就再按照你指定的字符集把二进制转回来。如果两次使用不同的字符集,也就会出现乱码了。
执行字符集
MSVC中 /execution-charset
在C++里 const char* str = "我"; ,执行字符集决定了这行代码在编译器进行编译的时候,str 存储的字节到底是什么,你可能会说源码字符集不是已经决定了这个”我”的二进制表示了么?没错,但是这个执行字符集就是让你在这里对它再解释一次。比如我源码字符集可能是UTF8的,但是我可以通过执行字符集来让最终str 存储的是GBK的字节编码。
解析字符集
最终要还原显示这些二进制字节编码的时候,就需要用到它。比如通过printf() 把前面的str 显示到控制台时,这个printf() 就会按照解析字符集来解析这些字节编码,找到指定字符显示出来。
Visual Studio中的字符集分析
默认情况下,Visual Studio 会检测字节顺序标记,以确定源文件是否采用编码的 Unicode 格式,例如 UTF-16 或 UTF-8。 如果未找到字节顺序标记,则假定源文件在当前代码页中编码,除非使用 /source-charset 或 /utf-8 选项指定字符集名称或代码页。 Visual Studio 允许将 C++ 源代码保存在任意几个字符编码中。
代码页是一个字符集,可以包括数字、标点符号和其他标志符号。 不同的语言和区域设置可能使用不同的代码页。 例如,ANSI 代码页 1252 适用于英语和大多数欧洲语言;而 OEM 代码页 932 则适用于日本汉字。
上述为MIcrosoft的官方论述,有点绕。简而言之,对于执行字符集,Visual Studio默认根据系统的Locale来决定执行字符集,一般大家都是Windows中文系统,Locale是中国,那么就是GBK编码。对于解析字符集,如果没有手动更改的话,Visual Studio的标准输入输出(printf ,cout )到命令行也是根据系统Locael决定的,也就是GBK。
如何使用UTF-8
为了全过程都能正常显示,不乱码,那应该三个阶段都需要设置为UTF-8。
源字符集和执行字符集设置为 UTF-8
可以使用 /utf-8 选项将源字符集和执行字符集指定为使用 UTF-8 编码的字符集。 它等效于在命令行上指定 /source-charset:utf-8 /execution-charset:utf-8 。
在 Visual Studio 开发环境中设置此编译器选项
- 打开项目“属性页” 对话框。 有关详细信息,请参阅在 Visual Studio 中设置 C++ 编译器和生成属性。
- 选择“配置属性”>“C/C++”>“命令行”属性页。
- 在“附加选项”中,添加
/utf-8 选项以指定首选编码。 - 选择“确定”以保存更改 。
解析字符集设置为 UTF-8
SetConsoleCP 函数设置与调用进程关联的控制台所使用的输入代码页。 控制台使用其输入代码页将键盘输入转换为相应的字符值。
BOOL WINAPI SetConsoleCP(
_In_ UINT wCodePageID
);
在mian()函数中加入以下代码
std::cout << "GetConsloeCP" << GetConsoleCP() << std::endl;
SetConsoleOutputCP(65001);
std::cout << "GetConsloeCP" << GetConsoleOutputCP() << std::endl;
qDebug() << QTextCodec::codecForLocale()->name();
QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8"));
qDebug() << QTextCodec::codecForLocale()->name();
另外,C++11可以指定字符串字面量的执行字符集了,const char* str = u8"我"; 在字符串前面加u8 就可以了。
/source-charset(设置源字符集) | Microsoft Docs
/utf-8(将源字符集和执行字符集设置为 UTF-8) | Microsoft Docs
SetConsoleCP 函数 - Windows Console | Microsoft Docs
代码页 | Microsoft Docs
代码页标识符 - Win32 apps | Microsoft Docs
MSVC中C++ UTF8中文编码处理探究
|