ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Qt4_字符串、字节数组和变量

2021-05-17 14:29:47  阅读:217  来源: 互联网

标签:Qt4 QByteArray 函数 QString str 字符串 QVariant 字节


字符串

我们将从 QString开始。每一个图形用户界面(GUI) 程序都会用到字符串,不仅仅是为用户界面,更多的是为数据结构所用。 C++ 本身提供两种宇符串:传统的 C语言型的,以" \0",结尾的字符数组和 std::string类。与这两种字符串不同, QString 支持 16 位 Unicode 值。Unicode码以 ASCII 码和 Latin-1码为子集,具有它们常用的数字值。但由于 QString是 16位的;它可以表示数千种其他字符以表达世界上绝大多数的语言。

当使用 QString时,我们不必担心那些诸如如何分配足够的内存空间或确保数据以"\0"结尾等晦涩难懂的细节。从概念上说,可以将 QString看成 QChar 向量。 QString可以嵌入"\0"字符。 length()函数会返回包括被嵌入"\0"字符的整个字符串的大小。

QString为连接两个字符串提供了一个二进制+操作符,还为在字符串后追加字符串提供了+=操作符。因为 QString在行数据的末端自动预分配内存空间,因此通过重复添加字符来建立字符串就相当快捷了。下面是一个结合使用+和+=的例子:

QString str = "User: "; 
str += userName + "\n";

以下的 QString::append() 函数与+=操作符的功能相同:

str = "User";
str.append(userName); 
str.append("\n"); 

使用 QString的 sprintf()函数则是连接字符串的另一种完全不同的方法:

str.sprintf("%s %.lf%%", "perfect competition", 100.0); 

这个函数支持与 C++库sprintf()函数相同的格式说明符。在之前的例子中, str 被赋值为"perfect competition 100.0%"。

从其他字符串或者数组来建立一个字符串的另一种方法是使用arg():

st r '" QSt ring ("%1 %2 (%3s-%4s)") 
.arg( "permissive") .arg("society") .arg(1950) .arg(1970); 

在这个例子中,“permissive” 会取代" %1",“society” 会取代"%2",“1950” 会取代"%3",而 “1970"会取代”%4"。相应的结果为"permissive society (1950s-1970s) “。arg()的重载可以处理各种数据类型。对于控制宇段长度、数值基数或者浮点精度等,一些重载有额外的参数。相较于 sprintf()而言, arg()通常是一个更好的解决方案,因为是它类型安全的,完全支持 Unicode 编码,并且允许译码器对”%n"参数进行重新排序。

通过使用 QString::number()静态函数, QString 可以将数字转换为字符串:

str = QString::number(59.6); 

或者也可以使用 setNum() 函数:

str.setNum(59.6); 

还可以使用 tolnt()、toLongLong()、toDouble()等来完成从字符串到数字的逆转换。例如:

bool ok; 
double d = str.toDouble(&ok); 

这些函数接受一个任选的指向 bool 变量的指针,并且根据转换成功与否来将变量值设为 true或false 如果转换没有完成,这些函数将返回0。

一旦有了字符串,我们通常都希望从字符串中提取出所需的部分。 mid() 函数返回在给定位置(第一个参数)开始且达到给定长度(第二个参数)的子串。例如,下面的代码在控制台上打印出"pays":

QString str = "polluter pays principle"; 
qDebug() << str.mid(9, 4); 

如果省略第二个参数, mid() 函数返回在给定位置开始到字符串末端结束的子串。例如,下面的代码在控制台上打印出"pays principle" :

QString str = "polluter pays principle"; 
qDebug() << str.mid(9); 

也可以使用 left()和 right() 函数来完成相似的任务。它们俩都可以接收字符的数量 并且返回字符串的前 n个字符或最后 n个字符。例如,下面的代码在控制台上打印出 “polluter principle”:

QStrirg str = "polluter pays principle"; 
qDebug() << str.left(8) << " "<< str.right(9);

如果想查明一个字符串是否包含一个特定的字符、子串或者正则表达式,可以使用QString中indexOf()函数:

QString str = "the middle bit";
int i = str.indexOf("middle");

这会将i设置为4。在失败时,indexOf()函数返回-1,并且接收一个可以的开始位置和区分大小写的标记。

如果仅仅想要检查字符串是否以某种字符(串)开始或者结束,则可以使用startsWith()和endsWith()函数:

if (url.startsWith("http:") && url.endsWith(".png")) 
    ...

上面的代码就比下面的代码更简单、快捷:

if (url.left(5) == "http:" && url. right(4) == ".png") 

利用==操作符进行字符串比较是区分大小写的。如果要比较那种用户可见的字符串, localeAwareCompare()函数通常是一个不错的选择;如果比较并不区分大小写,则可以使用 toUpper()或toLower()函数,例如:

if (fileName.toLower() == "readme.txt") 
    ...

如果想使用一个字符串来代替另一个字符串中的某一部分,可以使用 replace():

QString str = "a cloudy day"; 
str.replace(2, 6, "sunny");

字符串的结果是"a smy day" 。上面的代码可以用 remove()和 insert()重新写为:

str.remove(2, 6); 
str. insert(2, "sunny"); 

首先,我们去掉从第二个位值开始的 6个宇符,字符串因此变为"a day"气(含有两个空格 ),然后在第二个位置插人"sunny"。

replace()函数的重载版本让第二个参数代替所有第一个参数出现的地方。例如,下面是使用"∓"代替字符串中所有的"&":

str.replace("&", "&amp;"); 

我们经常需要删除一个字符串中空白处的空格(比如空格符、制表符、换行符等 )。 QString有一个可以从字符串的两端删除空白处的空格的函数:

QString str ="  BOB \t THE  \nDOG \n"; 
qDebug() << str.trimmed(); 

字符串 str 描述如下:
在这里插入图片描述
由trimmed() 返回的字符串为:
在这里插入图片描述
当处理用户输人数据时,除了从字符串的两端删除空白处的空格特外,通常还想用简单的空格符代替字符串内部每一连续空白处的空格:

QString str ="  BOB \t THE  \nDOG \n";
qDebug() <<str.simplified(); 

simplified()返回的字符串为:
在这里插入图片描述
使用 QString::split(),可以把一个字符串分成一些QStringList 子串:

QString str = "polluter pays principle";
QStringList words = str.split(" "); 

在上面的例子中,我们把宇符串 "polluter pays principle"分成了三个子串, “polluter”、“pays"和"principle”。

使用 join()函数, QStringList 中的项可以连接起来形成一个单一的字符串。在每一对被连接的字符串之间都要插人 join()的参数。例如,下面是如何创建一个由 QStringList 包含的所有字符串组成的、按字母表顺序排列且由换行符分隔的简单字符串:

words.sort(); 
str = words.join("\n"); 

当对字符串进行操作时,通常需要判断字符串是否为空。这可以通过调用 isEmpty()或者检查length()是否为 0来完成。
大多数情况下,从 const char *字符串到 QString的转换是自动完成的,例如:

str +=" (1878)"; 

这里,我们采用无格式形式为 QString 加上一个 const char *。为了明确地将 QString转换为const char* ,可以只使用一个 QString强制转换,或者调用 fromAscii()或fromLatin1()。

字节数组

要将 QString 转换为 const char*,可以使用 toAscii()或 toLatin1()函数,它们返回 QByteArray,而利用 QByteArray::data()或 QByteArray::constData(),可以将 QByteArray 转换为constData()。例如:

printf("User: %s\n" , str.toAscii().data()); 

为了方便起见, Qt 提供了 qPrintable()宏用来执行与序列 toAscii().constData():相同的功能:

printf("User: %s\n", qPrintabte(str)); 

当在 QByteArray 上调用 data()或 constData()时,返回的字符串属于 QByteArray 对象。这就意味着不必为内存泄漏而担心了, Qt 将为我们重新收回内存。另一方面,必须注意不要太长时间地使用指针。如果 QByteArray 没有存储在一个变量中,那么它将在声明的末端自动删除。

QByteArray 类有一个与 QString很相似的应用编程接口。诸如 left()、right()、mid()、toLower()、toUpper()、trimmed()和 simplified()等函数,在 QByteArray中的语义形式与在 QString中的相同。

QByteArray对于存储原始的二进制数据以及 8 位编码的文本字符串非常有用。一般说来,我们推荐使用 QString而不是 QByteArray来存储文本,因为 QString支持 Unicode 编码。

为方便起见, QByteArray 自动保证"最后一个项之后的项"总为"\0",这使得利用 const char*可以很容易地将 QByteArray 传递给一个函数。 QByteArray 还支持嵌入的"\0"宇符,以允许我们存储任意的二进制数据。

在某些情况下,我们需要在同一个变量中存储不同类型的数据。一种方法是像 QByteArray或QString一样,对数据进行编码。例如,字符串可以支持文本值或者以字符串形式支持数字值。这些方法很灵活,但是它抛弃了 C++的一些优点,尤其是类型的安全性和效率。Qt提供了一个更加灵巧的方法,也就是 QVariant,来处理那些能够支持不同数据类型的变量。

变量

QVariant 类可以支持许多种 Qt 类型的值,除了基本的 C++ 数字类型(如 double int) ,还包括QBrush、QColor、QCursor、 QDateTime、QFont、QKeySequence、QPalette、QPen、Pixrnap、QPoint、QRect、QRegion、QSize和 QString。 QVariant类也支持容器类,如 QMap <QString,QVariant> QStringList和QList<QVariant>

在项视图类、数据库模块和 Settings 中广泛使用了变量,变量允许我们读写项数据、数据库数据以及任意与 QVariant 兼容的用户首选参数。

通过容器类的嵌套值,可以利用 QVariant创建任意复杂的数据结构:

QMap<QString,QVariant> pearMap; 
pearMap["Standard"] = 1.95; 
pearMap["Organic"] = 2.25; 
QMap<QString, QVariant> fruitMap;
fruitMap["Orange"] = 2.10; 
fruitMap["Pineapple"] = 3.85; 
frtlitMap["Pear"] = pearMap;

这里,我们利用字符串键(产品名)和浮点数(价格)或者映射的值创建一个映射。顶级映射包括三个键:“Orange”、“Pear”、“Pineapple”。与"Pear"键相关联的值是一个包含两个键(“Standard"和"Organic”)的映射。当遍历一个支持变量值的映射时,需要使用type()来检查变量保持所支持的类型,以便做出适当的反应。

创建这样的数据结构是非常吸引人的,因为能够以任意方式组织数据。但是QVariant的便利性是以降低效率及可读性为代价的。通常,定义一个适当的C++类来存储随时可能的数据,是值得的。

Qt的元对象系统使用QVariant,因此它也是QtCore模块的一部分。但是,当与QtGui模块相连时,QVariant可以存储与图形用户界面相关的类型,例如QColor、QFont、QIcon、QImage和QPixmap:

QIcon icon("open.png");
QVariant variant = icon;

为了从QVariant中获得与图形用户界面相关的值,可以使用如下的QVariant::value<T>()模板成员函数:

QIcon icon = variant.value<QIcon>();

value<T>()函数也可以用非图形用户界面数据类型和QVariant之间进行转换,但实际上对于非图形界面类型,通常使用to…()作为非图形用户界面数据类型的转换函数[例如toString()]。

如果自定义数据类型提供了默认的构造函数和副本构造函数的话,QVariant也可以用来存储它们。为此,必须首先使用Q_DECLARE_METATYPE()宏注册数据类型,尤其是在类定义下的头文件中:

Q_DECLARE_METATYPE(BusinessCard);

这使我们可以使用如下的方式来编写代码:

BusinessCard businessCard;
QVariant variant = QVariant::fromValue(businessCard);
...
if(variant.canConvert<BusinessCard>()){
   BusinessCard card = variant.value<BusinessCard>();
   ...
}

由于编译器的局限性,在MSVC 6中,这些模板成员函数并不可用。如果需要用到这个编译器,可以用qVariantFromValue()、qVariantValue<T>()和qVariantCanConvert<T>()全局函数来代替。

如果自定义数据类型采用<<和>>操作符来完成从QDataStream的读写,就可以使用qRegisterMetaTypeStreamOperators<T>()来注册这些自定义数据类型。这就可以利用QSettings在其他类型之中存储自定义数据类型的首选参数。例如:

qRegisterMetaTypeStreamOperator<BusinessCard>("BusinessCard");

标签:Qt4,QByteArray,函数,QString,str,字符串,QVariant,字节
来源: https://blog.csdn.net/qq_36314864/article/details/116710154

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有