66qstring linux 中文,QString 与中文问题

博客探讨了QString在处理中文字符时可能出现的乱码问题,详细解释了源代码编码、编译器选择以及QString的工作原理。问题主要集中在GBK和UTF-8编码的转换上,通过QTextCodec设置默认编码可以解决。文章强调了明确字符串编码、理解Unicode和窄字符串转换的重要性,并提供了解决乱码的方案。

下面这个小程序,估计大家会感到比较亲切。似乎有相当多的中文用户尝试写过这样的代码:

#include

#include

int main(int argc, char **argv)

{

QApplication app(argc, argv);

QString a= "我是汉字";

QLabel label(a);

label.show();

return app.exec();

}

编码,保存,编译,运行,一切都很顺利,可是结果呢:

多数用户看到

其他用户看到

ÎÒÊǺº×Ö

æˆ‘æ˜¯æ±‰å —

出乎意料,界面上中文没显示出来,出现了不认识字符。于是开始用搜索引擎搜索,开始上论坛发帖或抱怨

最后被告知,下面的语句之一可以解决问题:

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));

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

两条指令挨个一试,确实可以解决(多数用户是第一条,其他用户是第二条)。那么,为什么会这样呢?

两种乱码什么时候出现

对这个问题,我想大家可能都有话说。在继续之前,我们先列个表,看看两种乱码分别在那种情况下出现:

我们只列举大家最常用的3个编译器(微软VS的中的cl,Mingw中的g++,Linux下的g++),源代码分别采用 GBK 和 不带BOM的UTF-8 以及 带BOM的UTF-8这3中编码进行保存。

源代码的编码

编译器

结果

GBK

cl

1

*

mingw-g++

1

*

g++

1

UTF-8(不带BOM)

cl

2

mingw-g++

2

g++

2

*

UTF-8(带BOM)

cl

1

mingw-g++

2

g++

编译失败

采用3种不同编码保存的源代码文件,分别用3种不同的编译器编译,形成9种组合,除掉一种不能工作的情况,两种乱码出现的情况各占一半。

从中我们也可以看出,乱码和操作系统原本是没有关系的。但我们在 Windows 一般用的GBK,linux一般用的是不带BOM的UTF-8。如果我们只考虑带*的情况,也可以说两种乱码和系统有关。

QString 为什么会乱码呢

真的是 QString 乱码了吗?我们可以问问自己,我们抱怨的对象是不是搞错了?

继续之前,先明确几个概念:

明确概念0:

"我是汉字" 是C语言中的字符串,它是char型的窄字符串。上面的例子可写为

const char * str = "我是汉字";

QString a= str;

或char str[] = "我是汉字";

QString a= str;

明确概念1:

源文件是有编码的,但是这种纯文本文件却不会记录自己采用的编码

这个是问题的根源,不妨做个试验,将前面的源代码保存成GBK编码,用16进制编辑器能看到引号内是ce d2 ca c7 ba ba d7 d6这样8个字节。

现在将该文件拷贝到正体(繁体)中文的Windows中,用记事本打开会什么样子呢?

...

QString a= "扂岆犖趼";

QLabel label(a);

label.show();

...

那么放到欧美人的Windows系统中,再用记事本打开呢?

...

QString a= "ÎÒÊǺº×Ö";

QLabel label(a);

label.show();

...

同一个文件,未做任何修改,但其中的8个字节ce d2 ca c7 ba ba d7 d6,对用GBK的大陆人,用BIG5的港澳台同胞,以及用Latin-1的欧洲人看来,看到的却是完全不同的文字。

明确概念2:

如同我们都了解的'A'与'\x41'等价一样。

GBK编码下的const char * str = "我是汉字"

等价于const char * str = "\xce\xd2\xca\xc7\xba\xba\xd7\xd6";

当用UTF-8编码时,等价于const char * str = "\xe6\x88\x91\xe6\x98\xaf\xe6\xb1\x89\xe5\xad\x97";

注意:这个说法不全对,比如保存成带BOM的UTF-8,用cl编译器时,汉字本身是UTF-8编码,但程序内保存时却是对应的GBK编码。

明确概念3:

QString 内部采用的是Unicode。

QString内部采用的是 Unicode,它可以同时存放GBK中的字符"我是汉字",BIG5中的字符"扂岆犖趼" 以及Latin-1中的字符"ÎÒÊǺº×Ö"。

一个问题是,源代码中的这8个字节"\xce\xd2\xca\xc7\xba\xba\xd7\xd6",该怎么转换成Unicode并存到 QString 内?按照GBK、BIG5、Latin-1还是其他方式...

在你不告诉它的情况下,它默认选择了Latin-1,于是8个字符"ÎÒÊǺº×Ö"的unicode码被存进了QString中。最终,8个Latin字符出现在你期盼看到4中文字符的地方,所谓的乱码出现了

QString 工作方式

const char * str = "我是汉字";

QString a= str;

其实很简单的一个问题,当你需要从窄字符串 char* 转成Unicode的QString字符串的,你需要告诉QString你的这串char* 中究竟是什么编码?GBK、BIG5、Latin-1

理想情况就是:将char* 传给QString时,同时告诉QString自己的编码是什么:

就像下面的函数一样,QString的成员函数知道按照何种编码来处理 C 字符串QString QString::fromAscii ( const char * str, int size = -1 )

QString QString::fromLatin1 ( const char * str, int size = -1 )

QString QString::fromLocal8Bit ( const char * str, int size = -1 )

QString QString::fromUtf8 ( const char * str, int size = -1 )

单QString 只提供了这几个成员函数,远远满足不了大家的需求,比如,在简体中文Windows下,local8Bit是GBK,可是有一个char串是 BIG5 或 Latin-2怎么办?

那就动用强大的QTextCodec吧,首先QTextCodec肯定知道自己所负责的编码的,然后你把一个char串送给它,它就能正确将其转成Unicode了。QString QTextCodec::toUnicode ( const char * chars ) const

可是这个调用太麻烦了,我就想直接QString a= str;

或QString a(str);

这样用怎么办?

这样一来肯定没办法同时告诉 QString 你的str是何种编码了,只能通过其他方式了。这也就是开头提到的QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));

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

设置QString默认采用的编码。而究竟采用哪一个,一般来说就是源代码是GBK,就用GBK,源代码是UTF-8就用UTF-8。但有一个例外,如果你保存成了带BOM的UTF-8而且用的微软的cl编译器,此时仍是GBK。

<think>好的,用户之前问了关于QTextStream(stdout)输出多余字符串的问题,现在又接着问QString如何输出汉字。这说明用户可能在开发Qt应用时遇到了中文显示的问题,尤其是涉及到控制台输出和QString的使用。需要先回顾之前的回答,确保这次的回答在逻辑上连贯,并覆盖用户可能的新需求。 首先,用户可能在使用QString存储中文字符时遇到了乱码问题,或者在输出到控制台或界面时显示不正常。这可能涉及到编码问题QString的内部机制以及不同平台下的处理差异。需要分步骤分析可能的原因和解决方案。 首先,QString本身是使用UTF-16编码的,可以处理Unicode字符,包括汉字。但如果源代码文件的编码编译器解释的不一致,可能会导致编译时字符串被错误转换。例如,在Windows下,如果源代码是GBK编码,而编译器默认使用UTF-8,那么直接写中文字符串可能会出错。 其次,输出到控制台时,控制台的编码设置也很关键。比如在Windows的命令提示符下,默认编码是GBK,而Qt默认使用UTF-8,这会导致输出乱码。这时候需要正确设置QTextStream的编码或者转换编码格式。 另外,用户可能在使用qDebug()输出QString时没有正确处理,导致输出的是UTF-16的转义序列而不是可读的汉字。需要提醒用户使用toLocal8Bit()或者设置全局编码。 还可能涉及到跨平台的问题,比如在Linux和macOS下默认使用UTF-8,可能不需要额外设置,但在Windows下需要特别注意编码转换。 需要总结常见的几种场景,比如直接输出、文件操作、界面显示等,并给出相应的解决方法,如设置编码、使用QTextCodec、转换字符串格式等。同时要提醒用户注意源代码的保存编码,以及编译器设置,避免源头错误。 最后,要确保回答结构清晰,步骤明确,让用户能够逐步排查和解决问题。可能还需要给出示例代码,帮助用户理解如何正确使用QString输出汉字。</think>在Qt中使用`QString`输出汉字时,需要特别注意**编码设置**和**输出方式**,否则容易出现乱码。以下是具体原因和解决方案: --- ### **1. 直接输出QString问题** #### 错误示例: ```cpp QString str = "你好"; qDebug() << str; // 输出类似: "\u4F60\u597D" QTextStream(stdout) << str; // 可能乱码 ``` **原因**: - `QString`内部使用UTF-16编码,而控制台或流可能默认使用其他编码(如Windows的GBK)。 - `qDebug()`默认输出Unicode转义字符而非原文。 --- ### **2. 解决方案** #### **方法1:转换为本地编码(推荐)** 使用`toLocal8Bit()`将QString转换为控制台支持的编码(如Windows的GBK): ```cpp QString str = "你好"; // 输出到控制台 QTextStream(stdout) << str.toLocal8Bit() << Qt::endl; // 或使用qDebug qDebug() << str.toLocal8Bit().constData(); // 输出:"你好" ``` #### **方法2:统一使用UTF-8编码** 若系统控制台支持UTF-8(如Linux/macOS),可强制设置编码: ```cpp QTextStream out(stdout); out.setCodec("UTF-8"); // 设置编码 out << "你好" << Qt::endl; // 或直接转换QString QString str = "你好"; out << str.toUtf8(); // 显式转为UTF-8字节流 ``` #### **方法3:修改源代码文件编码** 确保源代码文件保存为UTF-8格式(**重要!**): - 在Qt Creator中: 菜单栏 → **编辑** → **Select Encoding** → 选择UTF-8并保存。 - 在代码中添加BOM头(仅Windows需要): ```cpp #pragma execution_character_set("utf-8") // MSVC专用 ``` --- ### **3. 跨平台适配** #### Windows特殊处理 Windows控制台默认不支持UTF-8,需额外配置: ```cpp #include <windows.h> int main() { SetConsoleOutputCP(65001); // 设置控制台为UTF-8模式 QTextStream out(stdout); out.setCodec("UTF-8"); out << "你好" << Qt::endl; return 0; } ``` --- ### **4. 输出到GUI控件** 若输出到`QLabel`、`QTextEdit`等控件,无需转换编码(Qt自动处理UTF-16): ```cpp QString str = "你好"; QLabel *label = new QLabel(str); // 直接显示汉字 ``` --- ### **5. 文件读写中的汉字** 写入文件时指定编码: ```cpp QFile file("test.txt"); if (file.open(QIODevice::WriteOnly)) { QTextStream out(&file); out.setCodec("UTF-8"); // 文件保存为UTF-8 out << "你好"; } ``` --- ### **总结** | 场景 | 解决方案 | |--------------------|------------------------------------------| | 控制台输出(Windows) | `str.toLocal8Bit()` + 设置控制台编码 | | 控制台输出(Linux) | 直接使用UTF-8 | | GUI控件显示 | 直接使用QString | | 文件读写 | 显式设置文件编码(如UTF-8) | **关键点**: 1. 确保源代码文件编码编译器一致(推荐UTF-8)。 2. 根据输出目标(控制台、文件、GUI)动态转换编码。 3. 在Windows中优先使用`toLocal8Bit()`或配置控制台支持UTF-8。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值