C++实践之Qt学习(四):Qt中的字符串

Qt中的字符串

字符串的处理始终是我们编写程序绕不开的坑。无论是信息的输入和显示,以及数值和字符串之间的转换,都需要字符串的处理,而在Qt中有一个专门的类QString来对字符串进行操作。

但是需要注意的是,QString中内部采用Unicode编码格式处理字符数据,其中一个字符占用两个字节,而在VS编译器中,字符的编码采用的是GBK编码,一个字符占用一个字节,所以一个汉字需要两个字节的存储空间。所以这里会存在各种字符编码的转换以及乱码的问题。

字符编码的坑

在Qt中如果编写一句代码:

cout << "你好" << endl;

将会输出乱码:
在这里插入图片描述
原因在于在QtCreator中,代码文件的默认编码格式是UTF-8,而输出的控制台编码则是GBK,因此在代码中直接编写的中文以UTF-8格式进行编码,输出时对编码后的数据按GBK解码,自然就出现了乱码。

可以在选项中看到当前默认编码是UTF-8:在这里插入图片描述
这个问题并不能简单的直接通过修改默认编码来解决,在Windows 10中,默认创建的文本文件也采用了UTF-8编码,但是有个比较奇特的问题就是VS也好 QtCreator(也是VS编写的)也好,当打开一个默认编码格式的源码文件进行编辑时,如果输入了汉字,则会将该文件重新保存为了ANSI编码,而如果第一个出现的汉字是“转”字,则会出现一个非常神奇的现象:汉字要转码成ANSI,但文件未能正常修改编码,还是UTF-8编码,此时汉字就乱码了。

通过多次尝试,各种配置均尝试过,没有一个有效的解决方法,因此最后的解决方法是:不做任何解决。想要得到一个正常的中文输出,可以借助Qt中的一个字符串类QString类来进行。

string s = "你好";
QString qs(s.data());
cout << string(qs.toLocal8Bit()) << endl;

上面的代码中s中的内容是经过UTF-8编码的字符串,调用其data()方法获取到了原始的字节数据,并构造成了QString,然后调用QString对象的toLocal8Bit方法转换为windows系统的GBK编码数据,最后再包装成一个string对象,得到的就是一个GBK编码的汉字字符串了。

字符串处理

有的时候我们编写一个C++项目,使用了C++标准库中的string来存储字符串,而在QT中更多的是使用QString类,它们之间的转换也比较轻松,在程序中运行时不用考虑编码问题,直接进行转换:

QString qs = QString::fromStdString(s); // s是一个string变量,转为QString
string str = qs.toStdString(); // QString对象转为string

如果使用了C++的文件流从文件中读取字符串内容,或者要将字符串内容写入文件中,需要保证文件的编码也是UTF-8,这样做就可以避免因编码不一致导致的乱码。

QString常用操作

QString类非常实用,有很多对字符串操作的方法,因此有必要简单了解下它能做哪些事情(具体的使用参看帮助文档):

转换

toInt: 将字符串转换为int整数
toDouble:将字符串转换为double小数
number:QString的静态方法,将数值转换为QString字符串
fromStdString:QString的静态方法,将标准string字符串转为QString
toStdString:QString成员函数,将QString对象转为标准string

添加字符串操作

append:在字符串的后面添加字符串

prepend:在字符串的前面添加字符串

insert:在指定的位置插入字符串

删除子串

remove:删除从指定位置开始的若干个字符

修改

trimmed:去掉字符串首尾的空格

simplified:去掉首尾的空格,同时中间连续的空格也用一个空格替换

toUpper:将字符串内的字母全部转换为大写形式

toLower:将字符串内的字母全部转换为小写形式

检索

count()、size() 和 length():都返回字符串的字符个数,这 3 个函数是相同的,但是要注意,字符串中如果有汉字,一个汉字算一个字符。

isNull() 和 isEmpty():两个函数都判读字符串是否为空,但是稍有差别。如果一个空字符串,只有“\0”,isNull() 返回 false,而 isEmpty() 返回 true;只有未赋值的字符串,isNull() 才返回 true。

indexOf():查找子串

int indexOf (const QString &str, int from = 0 , Qt::CaseSensitivity cs = Qt::CaseSensitive) const

其功能是在自身字符串内查找参数字符串 str 出现的位置,参数 from 是幵始查找的位置,Qt::CaseSensitivity cs 参数指定是否区分大小写。

lastIndexOf:查找某个字符串最后出现的位置。

startWith:检测是否是以指定的字符串开头,例如查询某个字符串是否是http协议
endsWith:检测是否是以指定的字符串结尾,例如查询某个字符串表示的文件是否是txt文件

分隔

section()函数的原型为:

QString section (const QString &sep, int start, int end = -1, SectionFlags flags = SectionDefault) const

其功能是从字符串中提取以 sep 作为分隔符,从 start 端到 end 端的字符串。

示例:

QString str2, str1="学生姓名,男,1984-3-4,汉族,山东";
str2=str1.section (",",0,0); // str2="学生姓名", 第 1 段的编号为 0
str2=str1.section (",",1,1}; // str2="男"
str2=str1.section (",",0,1}; // str2="学生姓名,男"
str2=str1.section (",",4,4); // str2="山东"