源文件字符集,编译器内部字符集,执行字符集,控制台乱码问题,Qt中文问题

转载自:https://blog.csdn.net/a10929/article/details/78235793

  1. 源文件字符集:源文件本身也是文本文件,所以源文件字符集是指源文件保存时采用哪种字符集编码。VC++下源文件默认是gbk编码,如果想要更改,可以通过 文件-高级保存选项 修改某个源文件的编码方式,似乎没有什么选项能够设置创建项目时的源文件编码,需要自己一个一个设。
  2. 编译器字符集:编译器在读取源代码文件时所使用的内部字符集决定了编译器如何把读入的源代码文件字节流进行转换,转换是指从一种字符集编码的字节经过解码再编码到另一种字符集编码的字节。当然编译器内部采用什么字符集不是我们所关心的,是编译器内部的事情。
  3. 执行字符集:编译器在编译时会将 字符/字符串 常量从上一步编码得到的字节转化为相应的字符集,转化为哪种字符集决定了程序在运行时这些字符串采用了哪种字符集编码,举个例子:

printf("你好"); //程序在执行时 "你好" 这个字符串在内存中保存的是哪种字符集的编码呢?就由这个第3步决定。

  • 1

那么,编译器到底会转化为哪种字符集呢?分2种情况: 
1.
如果是窄字符/字符串”“(char为单位),那么不同的编译器可能不一样。以VC++为例,它是由系统代码页决定的,比如在中文windows系统下就采用GBK编码。 
2.
如果字符/字符串前有指定编码方式,那没什么好说的了,就采用指定的编码方式,如下:

char* s1 = u8"hello"; //窄字符串,utf-8编码 (C++11)

wchar_t* s2 =  L"hello"; //宽字符串,utf-16编码

char16_t* s3 =  u"hello"; //宽字符串,utf-16编码 (C++11)

char32_t* s4 =  U"hello"; //utf-32编码 (C++11)

 

//'\x12' : \x后面接216进制数字,可表示一个窄字符char,多个\x连起来可表示一个utf-8字符,如"\xE4\xBD\xA0"

//L'\u1234' : \u后面接416进制数字,可表示一个utf-16宽字符

//U'\U12345678' : \U后面接816进制数字,可表示一个Utf-32

VC++里如果想要强行改变执行字符集,可以加上一句预处理:

//设置执行字符集为utf-8

#if _MSC_VER >= 1600

#pragma execution_character_set("utf-8")

#endif

  • 1
  • 2
  • 3
  • 4

控制台输出乱码的问题解决

控制台的代码页默认是和系统代码页是一样的,中文windows下就是GBK,所以你用输出流函数(printf,wprintf,cout,wcout)输出GBK编码的字符串肯定没问题,现在讨论2种情况:

  • 输出宽字符串,如果直接输出是会乱码的。这里有一个函数:setlocale(),是用来程序运行时设置当前系统的区域信息。而在所有C++程序启动前,locale的默认设置setlocale(LC_ALL,”C”);会被执行,这个”C”肯定不是能支持中文的这样一个环境,而宽字符串在输出时会根据setlocale()的设置将其转为相应区域代码页的编码,当然就会出错了。所以我们可以手动设置一下locale信息就可以了:

#include <locale.h>

//使用""的话就从当前系统获取代码页,当然也可以设成具体的,比如"chs"

int main()

{

    setlocale(LC_CTYPE,"");

    wprintf(L"你好"); //这样就不会乱码了

    //...

}

  • 对于窄字符串来说,是不会作编码转换的,所以如果你输出GBK编码的窄字符串,那是没有问题的,但如果是utf-8编码的窄字符串呢?显然又会乱码,这时只能修改控制台窗口的代码页了:

//经过测试发现没有乱码,但是鼠标点到字上时会变乱,可能需要设置字体

system("chcp 65001");

printf(u8"你好");

Qt下的中文问题

以前采用 Qt + MSVC编译器 时,在程序中需要用到中文时,直接将字符串传给QString或一些Qt的函数时,会出现乱码。这是因为:Qt内部采用utf-16编码,当你将字符串传给QString或一些Qt的函数时,Qt会将默认其当作utf-8编码的字符串来转换,之前说过,VC++下执行字符集默认是GBK的,所以就会乱码。解决方法有如下几种:

  • 用QTextCodeC或QString转换

QTextCodeC* c = QTextCodec::codecForName("gbk");

QString s = c->toUnicode("你好"); //gbk转为QString

//

QString s = QString::fromLocal8Bit("你好"); //从本地系统代码页转为QString

  • 如果支持C++11,直接使用utf-8字符串 u8"你好"
  • 强行更改执行字符集,方法之前说过

Qt5之前有这3个函数,可以设置相应的编码问题:

//设置QStringc风格字符串采用哪种编码方式来处理

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); 

 

//设置tr("")时对c风格字符串采用哪种编码方式来处理

QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); 

 

//主要设置QString::from(to)Local8Bit这个函数认为的本地编码方式

QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));

Qt5中前2个函数被删除了,因为Qt5QString等对c字符串默认采用utf-8处理(以前是Latin1),所以只要采用 Qt Creator+MinGW编译器,就没有问题了。因为Qt Creator源文件默认是utf-8编码,MinGW执行字符集就是utf-8编码,所以可以直接这样用,不会乱码了:

QString s = "你好";

qDebug()<<"你好";

QMessageBox::information(nullptr,"标题","你好");

//...

参考: 
微软C/C++编译器中管理字符集的新选项 
带你玩转Visual Studio 
拨开字符编码的迷雾编译器如何处理文件编码 
控制台输出乱码问题 
QTextCodec中的setCodecForTr等终于消失了 
源码必须是UTF-8QString需要它

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值