Qt学习(13)——使用 QString
本节介绍 QString 的常见使用,包含 C++ 基本类型和 QString 的互相转换、QString 涉及的运算符、QString 子串查询和操作、利用 QTextStream 对 QString 做输入输出操作等,最后通过一个示例集成测试函数,展示 QString 用法。本节内容较多,可分几次尝试代码,凡是原理性质的内容需要理解,而罗列性质的内容不用死记的,可以到用的时候查看文档。
1、QString和QChar简介
QString是由一系列16bit字符QChar组成的字符串,以NULL字符结尾(末尾的NULL不计入字符串长度)。QChar是一个Unicode 4.0标准的字符,对于超过16bit范围的国际码字符,QString里采用相邻的一对QChar来表示。QString使用的其实是UTF-16的双字节编码,tr函数就是将UTF-8变长编码的字符串转成QString运行时的内码。UTF-8编码是属于通用的存储交换格式,但这种编码的缺点就是一个字符的长度不固定,这对字符串操作效率是有影响的,因为要先确定每个字符的长度。因此QString采用固定长度字符单元的UTF-16编码,这对程序运行时字符串比较、查询操作效率更高。上一节 中“运行时QString与多种编码格式转换” 表格中 utf16() 和 unicode() 函数都没有用 to 前缀,因为这两个函数没有做转换,它们返回的就是 QString 运行时的内码,同 data() 函数。tr 函数不仅可以用于支持国际化翻译,并且能自动将字符串的存储交换格式 UTF-8 转换成运行时的 UTF-16 内码,返回转换过后得到的QString 对象。
字符串之间经常有手动复制或者通过函数参数、函数返回值等复制操作,QString为了优化内存使用效率,避免出现大量相同内容的字符串副本,QString对复制过程采用隐式共享机制(implicit sharing),比如执行字符串对象str1 = str2时,如果这两个对象字符串内容都没有后续的改变,那么它们会指向同一块字符串数据,而如果其中之一发生改变,字符串数据块的复制过程才会发生,这样能最大程度地节省内存,而且在传QString类型参数或返回值时,避免了大量数据块的复制过程,优化了程序运行效率。
QString内码是UTF-16,而标准C++的字符串是UTF-8编码的,Qt针对标准C++字符串也提供了QByteArray类,用于操作UTF-8编码以及其他本地化字符串(如GBK、Big5)、字节数组(不以NULL结尾的纯数据)等,QByteArray类下一节会介绍。
2、基本类型与字符串互相转换
在编程时经常会出现把数值如 800 转成字符串 "800",或者反过来把字符串转成数值等情况,本小节罗列 C++ 基本的数值类型和 Qt 对这些类型的别称,然后展示这些基本类型和 QString 对象的互相转换,并编写一些测试函数来示范效果。
基本类型 | Qt别称 | 转入函数 | 转出函数 | 描述 |
short | qint16 | arg或setNum | toShort | 2 字节长度,有符号短整型。 |
unsigned short | ushort、quint16 | arg或setNum | toUShort | 2 字节长度,无符号短整型。 |
int | qint32 | arg或setNum | toInt | 4 字节长度,有符号整型。 |
unsigned int | uint、quint32 | arg或setNum | toUInt | 4 字节长度,无符号整型。 |
long | 无 | arg或setNum | toLong | 有符号长整型,对于 32 位编程 long 是 4 字节长度,对于 64 位编程是 8 字节长度。 |
unsigned long | ulong | arg或setNum | toULong | 无符号长整型,对于 32 位编程 unsigned long 是 4 字节长度,对于 64 位编程是 8 字节长度。 |
long long | qlonglong、qint64 | arg或setNum | toLongLong | 8 字节长度,有符号长长整型。 |
unsigned long long | qulonglong、quint64 | arg或setNum | toULongLong | 8 字节长度,无符号长长整型。 |
float | 默认情况下无 | arg或setNum | toFloat | 4 字节长度,单精度浮点数。 |
double | 默认情况对应 qreal | arg或setNum | toDouble | 8 字节长度,双精度浮点数。 |
这些基本的数值类型转为 QString 对象都是使用重载的 arg 或 setNum 函数,而 QString 对象转出为其他类型使用单独命名的函数。Qt 对这些类型的别称都定义在头文件 <QtGlobal> 里面,由于其他绝大多数 Qt 头文件都包含了该全局头文件,所以通常不需要自己手动去包含它的。对于上表需要说明的两点:一是 long 和 ulong 长度是根据操作系统和编译器确定的,32 位编程就是 32 位,64 位编程就是 64 位;二是实数 qreal 默认情况下都是对应 double ,例外情况是在编译 Qt 类库本身时配置了 -qreal float 选项参数,这种例外情况极少,通常都不用管的。
首先来介绍一下转入函数,对于整数类型,setNum 函数声明是完全类似的,以 int 为例:
QString & setNum(int n, int base = 10)
第一个参数就是需要转换的整数,第二个参数是转换之后的目标字符串进制基数,比如转成十六进制字符串、八进制字符串等,默认是转成十进制的字符串。setNum 函数设置好字符串内容后返回 QString 对象自身的引用。
对于浮点数类型,setNum 函数声明有些区别,以 double 为例:
QString & QString::?setNum(double n, char format = ‘g‘, int precision = 6)
第一个参数是需要转换的浮点数,第二个是转换之后的目标字符串格式(‘e‘, ‘E‘, ‘f‘, ‘g‘ , ‘G‘),第三个是目标字符串显示的浮点数精度,默认是 6 。浮点数的格式是与 C 语言类似的,如下所述:
setNum 函数示范代码:
void Test_setNum() { QString strTest; //to Hex string short numHex = 127; strTest.setNum(numHex, 16); qDebug()<<"Hex: "<<strTest; //to Oct string int numOct = 63; strTest.setNum(numOct, 8); qDebug()<<"Oct: "<<strTest; //to normal Dec string long numDec = 800; strTest.setNum(numDec); qDebug()<<"Normal: "<<strTest; //to float string float numFixed = 123.78999; strTest.setNum(numFixed, ‘f‘, 3); qDebug()<<"Fixed: "<<strTest; //to scientific double string double numScientific = 456.78999; strTest.setNum(numScientific, ‘e‘, 6); qDebug()<<"Scientific: "<<strTest; }
这个测试函数运行结果就不贴出来了,读者自己手动去试试看。
接下来重点介绍 arg 函数,这是最常用也是最具特色的。arg 函数无所不包,它的参数可以是数值类型、字符串类型,并且可以串联,格式化参数里还可以指定顺序、重复使用参数等等。对于数值类型,它的声明与 setNum 比较类似,以 int 和 double 为例:
QString arg(int a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char( ‘ ‘ )) const
QString arg(double a, int fieldWidth = 0, char format = ‘g‘, int precision = -1, QChar fillChar = QLatin1Char( ‘ ‘ )) const
注意 arg 函数声明末尾的 const,这个函数不会改变字符串对象本身的内容,而是会返回一个全新的 QString对象,所以使用这个函数时,必须用它的返回值。
对于整数类型,它的声明多出来两个:fieldWidth 是指生成的目标字符串宽度,0 表示自动设置长度,最后的 fillChar 是填充字符,如果设置的域宽比较大,多余的空位就会使用这个填充字符填满。
对于浮点数类型,多出来的 fieldWidth 也是生成的目标字符串宽度,fillChar 也是填充字符。默认的填充字符是空格,QLatin1Char 代表一个字节长度的拉丁字符,与 ASCII 码字符差不多。QLatin1Char 有对应的类 QLatin1String,因为仅支持单字节拉丁字符,不支持国际化,它应用的比较少。
arg 函数比 setNum 函数功能更强大,可以设置目标字符串宽度和填充字符。arg 函数还可以用字符串作为参数,可以将一个字符串填充到另一个里面,比如下面这个函数声明:
QString arg(const QString & a, int fieldWidth = 0, QChar fillChar = QLatin1Char( ‘ ‘ )) const
这个声明和数值类型声明差不多,也可以设置目标字符串宽度和填充字符。
函数声明介绍到这,下面看看这个函数该怎么用。arg 函数的使用方式很特别,它的串联方式也很灵活,来看看示例代码:
void Test_arg() { //使用 strResult 存储 arg 返回的新对象 QString strResult; //Dec long numDec = 800; QString strMod = QObject::tr("Normal: %1"); strResult = strMod.arg(numDec); //%1是占位符,第一个arg函数参数变量转后的字符串填充到 %1 位置 qDebug()<<"Mod: "<<strMod<<" \t Result: "<<strResult; //Oct int numOct = 63; strResult = QObject::tr("Oct: %1").arg(numOct, 4, 8, QChar(‘0‘)); //numOct转换后为4字符域宽,8进制,填充0 qDebug()<<strResult; //Hex short numHex = 127; QString strPrefix = QObject::tr("0x"); //占位符里可填充数值转的字符串,也可以直接填充原有的字符串 strResult = QObject::tr("Hex: %1%2").arg(strPrefix).arg(numHex, 0, 16); //串联:第一个arg函数参数填充到%1,第二个arg填充到%2 qDebug()<<strResult; //double double numReal = 123.78999; strResult = QObject::tr("Fixed: %1 \t Scientific: %2").arg(numReal, 0, ‘f‘).arg(numReal, 0, ‘e‘, 3); qDebug()<<strResult; //占位符可重复,也可乱序 int one = 1; int two = 2; int three = 3; strResult = QObject::tr("%1 小于 %2,%1 小于 %3,%3 大于 %2 。").arg(one).arg(two).arg(three); qDebug()<<strResult; }
上面都是通过 tr 函数封装了一个临时的 QString 对象,然后调用该临时对象的 arg 函数实现数值类型转成格式化字符串,填充到占位符里面。这个工作原理与 sprintf 等 C 语言函数类似,sprintf 函数使用 %n 、%s 之类的格式占位符,QString 的实现方式不一样,它使用 % 加数字的占位方式,%1 对应后面串联的第一个 arg 函数,%2 对应后面串联的第二个 arg 函数,以此类推。具体的 %1 或 %2 等替换后的格式,由对应的 arg 函数来决定,QString 里有非常多的重载 arg 函数,每个 arg 函数对应一个类型,因此 %1 既可以填充数值类型转化后的格式化字符串,也可以填充其他原有的字符串。下面逐个解释一下各个 arg 函数意义:
long numDec = 800;
QString strMod = QObject::tr("Normal: %1"); strResult = strMod.arg(numDec); //%1是占位符,第一个arg函数参数变量转后的字符串填充到 %1 位置 qDebug()<<"Mod: "<<strMod<<" \t Result: "<<strResult;
原文:http://www.cnblogs.com/wyxsq/p/5082206.html