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="山东"