QT QString 很全的使用 (转)
QString,QByteArray, 和QVariant這三個(gè)類和容器有許多相同之處,并且在一些情況下可以被當(dāng)作特殊的容器。 同樣,像容器,這些類使用隱式共享來(lái)優(yōu)化內(nèi)存和速度。
我們將從QString開(kāi)始。 字符串被每個(gè)GUI程序所使用,不僅是用戶界面而且還有數(shù)據(jù)結(jié)構(gòu)。 C++原生提供兩種字符串: 傳統(tǒng)的C風(fēng)格以''結(jié)尾的字符數(shù)組和std::string類。 與這些不同,QString使用16-bit Unicode值。 Unicode 包含 ASCII 和 Latin-1 這個(gè)子集和它們的普通數(shù)值。 而QString是16-bit,所以它可以表示世界上絕大多數(shù)語(yǔ)言的字符。 Unicode的更多信息,請(qǐng)看十七章。
當(dāng)使用QString時(shí),我們不必操心如此隱秘的細(xì)節(jié)像分配足夠的內(nèi)存或著是數(shù)據(jù)是''結(jié)尾的。 總的來(lái)說(shuō),QString可以被認(rèn)為是一個(gè)QChar向量。一個(gè)QString能嵌入''字符。length()函數(shù)返回整個(gè)字符串大小,包括嵌入的''。
QString提供一個(gè)二元+操作符來(lái)連接兩個(gè)字符串和一個(gè)+=操作符來(lái)向一個(gè)字符串追加字符串。 因?yàn)镼String在字符串的結(jié)尾處自動(dòng)預(yù)分配內(nèi)存,所以通過(guò)反復(fù)追加字符來(lái)增加一個(gè)字符串是非常快的。 這是一個(gè)+和+=結(jié)合的例子:
QString str = "User: "; str += userName + "
";
還有一個(gè)QString::append()函數(shù)與+=操作符有這一樣的功能:
str = "User: "; str.append(userName); str.append("
");
組合字符串的一個(gè)完全不同的方式是使用QString的sprintf()函數(shù):
str.sprintf("%s %.1f%%", "perfect competition", 100.0);
支持同樣的格式說(shuō)明符像C++庫(kù)的sprintf()函數(shù)。 在上面的例子中,str被賦值為 "perfect competition 100.0%"。
從另外一個(gè)字符串或數(shù)字來(lái)構(gòu)建字符串還有另外一種方式,就是使用arg():
str = QString("%1 %2 (%3s-%4s)") .arg("permissive").arg("society").arg(1950).arg(1970);
在這個(gè)例子中,"%1"被"permissive"替換,"%2被"society"替換,"%3"被"1950"替換,而"%4"被 "1970"替換。 結(jié)果是"permissive society (1950s-1970s)"。arg()重載支持各種各樣的數(shù)據(jù)類型。 某些重載有附加參數(shù)來(lái)控制域?qū)挘瑪?shù)字基數(shù),或浮點(diǎn)精度。 通常,arg()是比sprintf()更好的解決方案,因?yàn)樗穷愋桶踩╰ype-safe)的,完全支持Unicode,并且允許translators對(duì)"%n"參數(shù)重新排序。
QString能將數(shù)字轉(zhuǎn)換為字符串,通過(guò)使用靜態(tài)函數(shù)QString::number():
str = QString::number(59.6);
或者使用setNum()函數(shù):
str.setNum(59.6);
逆向變換,就是將一個(gè)字符串轉(zhuǎn)換為一個(gè)數(shù)字,使用的是toInt(),toLongLong(),toDouble(),等等。 例如:
bool ok; double d = str.toDouble(&ok);
這些函數(shù)接受一個(gè)可選的bool類型的指針并設(shè)置這個(gè)bool變量為TRue或false,這取決于轉(zhuǎn)換成功與否。 如果轉(zhuǎn)換失敗,這些函數(shù)返回0。
一旦我們有一個(gè)字符串,我們經(jīng)常想要提取它的一些部分。mid()函數(shù)返回一個(gè)給定起始位置(第一個(gè)參數(shù))和長(zhǎng)度(第二個(gè)參數(shù))的字串。 例如,下面的代碼在控制臺(tái)上打印"pays":[*]
[*]使用實(shí)用的qDebug() << arg語(yǔ)法需要包含頭文件,而qDebug("...", arg)語(yǔ)法在任何至少包含一個(gè)Qt頭文件的文件中可用。
QString str = "polluter pays principle"; qDebug() << str.mid(9, 4);
如果省略第二個(gè)參數(shù),mid()返回從指定的起始位置到這個(gè)字符串結(jié)尾的子串。 例如,下面的代碼在控制臺(tái)上打印"pays principle":
QString str = "polluter pays principle"; qDebug() << str.mid(9);
還有l(wèi)eft()和right()函數(shù),它們也執(zhí)行類似的工作。 他們倆都接受一個(gè)表示字符數(shù)量的數(shù)字,n,并返回并返回最前面或最后面的n個(gè)字符。 例如,下面的代碼在控制臺(tái)上打印"polluter principle":
QString str = "polluter pays principle"; qDebug() << str.left(8) << " " << str.right(9);
如果我們希望找出一個(gè)字符串是否包含某個(gè)字符,字串,或正則表達(dá)式,我們可以使用QString的indexOf()函數(shù)中的一個(gè):
QString str = "the middle bit"; int i = str.indexOf("middle");
i將被置為4。indexOf()函數(shù)返回-1在失敗時(shí),并接受一個(gè)可選的起始位置和大小寫敏感標(biāo)志。
如果我們希望檢查一個(gè)字符串是否是以某物開(kāi)始或結(jié)束,我們可以使用startsWith()和endsWith()函數(shù):
if (url.startsWith("http:") && url.endsWith(".png")) ...
這個(gè)要比下面的簡(jiǎn)單快速:
if (url.left(5) == "http:" && url.right(4) == ".png") ...
使用==操作符的字符串比較是大小寫敏感的。 如果我們正在比較用戶級(jí)(user-visible)字符串,localeAwareCompare()經(jīng)常是正確的選擇,并且如果我們希望大小寫不敏感,我們可以用toUpper()或toLower()。 例如:
if (fileName.toLower() == "readme.txt") ...
如果我們希望用一個(gè)字符串替換另一個(gè)字符串的某一部分,可以用replace():
QString str = "a cloudy day"; str.replace(2, 6, "sunny");
結(jié)果是"a sunny day"。 可以改用remove()和insert():
str.remove(2, 6); str.insert(2, "sunny");
首先,我們刪除從位置2開(kāi)始的6個(gè)字符,產(chǎn)生一個(gè)字符串"a day"(有兩個(gè)空格),然后我們?cè)谖恢?處插入"sunny"。
有重載版本的replace(),它們能將所有出現(xiàn)第一個(gè)參數(shù)的地方用第二個(gè)參數(shù)替換。 例如,這是如何將所有出現(xiàn)"&"的地方用"&"來(lái)替換:
str.replace("&", "&");
一個(gè)經(jīng)常的需求是過(guò)濾掉字符串中的空白符(如空格,制表符,和換行符)。QString有一個(gè)函數(shù)能從字符串的兩端刪除空白符:
QString str = " BOB THE
DOG
"; qDebug() << str.trimmed();
字符串str可被描述為:
trimmed()返回的字符串是:
當(dāng)處理用戶輸入時(shí),我們經(jīng)常希望將一個(gè)或多個(gè)內(nèi)部空白符替換為單個(gè)空格,另外還要過(guò)濾掉兩端的空白符。 這就是simplified()函數(shù)所做的:
QString str = " BOB THE
DOG
"; qDebug() << str.simplified();
simplified()返回的字符串是:
一個(gè)字符串能被分成為一個(gè)裝有子串的QStringList,通過(guò)使用QString::split():
QString str = "polluter pays principle"; QStringList words = str.split(" ");
在上面的例子,我們把"polluter pays principle"分成三個(gè)子串: "polluter", "pays", 和 "principle"。split()函數(shù)有一個(gè)可選的第三個(gè)參數(shù)(譯者注:Qt4.4版應(yīng)該是第二個(gè)參數(shù))用來(lái)決定保留(缺省)還是丟棄空的子串。
QStringList能被組成單個(gè)的字符串,通過(guò)使用join()。join()的參數(shù)被插入到每對(duì)被組合的字符串之間。 例如,下面展示的是如何創(chuàng)建單個(gè)的字符串,它由QStringList中的字符串組成,字符串之間按字母順序排序并用換行符分開(kāi):
words.sort(); str = words.join("
");
當(dāng)處理字符串時(shí),我們經(jīng)常需要判斷一個(gè)字符串是否是空。 調(diào)用isEmpty()或檢查length()是否為0就可以達(dá)到目的。
在大多數(shù)情況下,從const char *字符串到QString的轉(zhuǎn)換是自動(dòng)的,例如:
str += " (1870)";
這里我們將一個(gè)const char *加到一個(gè)QString上,沒(méi)有任何約束。 要將一個(gè)const char *顯示轉(zhuǎn)換成一個(gè)QString,就簡(jiǎn)單地使用一個(gè)QStringcast,或者調(diào)用fromAscii()或fromLatin1()。 (See Chapter 17 for an explanation of handling literal strings in other encodings.)
要將一個(gè)QString轉(zhuǎn)換為一個(gè)const char *,就使用toAscii()或toLatin1()。 這些函數(shù)返回一個(gè)QByteArray,它能被轉(zhuǎn)換為一個(gè)const char *,通過(guò)使用QByteArray::data()或QByteArray::constData()。 例如:
printf("User: %s
", str.toAscii().data());
為了方便,Qt提供qPrintable()宏,它執(zhí)行和toAscii().constData()順序相同的操作。
printf("User: %s
", qPrintable(str));
當(dāng)我們?cè)谝粋€(gè)QByteArray上調(diào)用data()或constData(),返回的字符串屬于QByteArray對(duì)象所有。 這意味著我們不用擔(dān)心內(nèi)存泄漏;Qt將會(huì)為我們回收內(nèi)存。 另一方面,我們小心不能使用這個(gè)指針太長(zhǎng)時(shí)間。如果QByteArray沒(méi)有保存在一個(gè)變量中,在語(yǔ)句結(jié)束時(shí),它將會(huì)被自動(dòng)刪除。
QByteArray有著與QString相似的API。 像left(),right(),mid(),toLower(),toUpper(),TRimmed(), 和simplified()在QByteArray中和QString中相應(yīng)的函數(shù)有著同樣的語(yǔ)義。QByteArray對(duì)存儲(chǔ)純二進(jìn)制數(shù)據(jù)(raw binary data)和8-bit編碼文本字符串有用。 一般地,我們推薦使用QString來(lái)存儲(chǔ)文本而不是用QByteArray,因?yàn)镼String支持Unicode。
為了方便,QByteArray自動(dòng)確保the "one past the last"byte總是 '',使得傳遞一個(gè)QByteArray給一個(gè)帶有const char *類型參數(shù)的函數(shù)時(shí)操作變得簡(jiǎn)單。QByteArray還支持內(nèi)嵌的''字符,這允許我們用它來(lái)存儲(chǔ)任意二進(jìn)制數(shù)據(jù)(arbitrary binary data)。
在有些情況下,我們需要用共一個(gè)變量存儲(chǔ)不同類型的數(shù)據(jù)。 一種處理是將數(shù)據(jù)編碼成一個(gè)QByteArray或一個(gè)QString。 例如,一個(gè)字符串可以保存一個(gè)文本值或一個(gè)數(shù)字值以字符串形式。 這些處理是靈活的,卻抹殺了C++的好處,尤其是類型安全和效率。 Qt提供一個(gè)更潔凈的方式來(lái)處理支持不同類型的變量。QVariant。
QVariant類支持許多Qt類型的值,包括QBrush,QColor,QCursor,QDateTime,QFont,QKeySequence,QPalette,QPen,QPixmap,QPoint,QRect,QRegion,QSize, 和QString, 和 基本的C++數(shù)值類型,像double和int。QVariant類還支持容器:QMap<qstring,qvariant>,QStringList, 和QList。
可變類型(Variants )被條目視圖類(item view classes),數(shù)據(jù)庫(kù)模塊,和QSettings所廣泛使用,它允許我們讀寫條目數(shù)據(jù),數(shù)據(jù)庫(kù)數(shù)據(jù),和用戶參數(shù)等任何兼容于QVariant的類型。 我們已經(jīng)看過(guò)第三章中這樣的例子,我們傳遞了一個(gè)QRect,一個(gè)QStringList,和一對(duì)bool作為可變類型給QSettings::setValue(),并作為可變類型對(duì)它們解引用。
創(chuàng)建任意復(fù)雜的數(shù)據(jù)結(jié)構(gòu)是可能的,通過(guò)用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; fruitMap["Pear"] = pearMap;
我們已經(jīng)創(chuàng)建了一個(gè)map,它的鍵是字符串(產(chǎn)品名),它的值是浮點(diǎn)數(shù)(價(jià)格)或maps。 頂級(jí)map包含三個(gè)鍵: "Orange", "Pear", 和"Pineapple"。 與"Pear"鍵相關(guān)聯(lián)的值是一個(gè)map,它包含兩個(gè)鍵("Standard" 和"Organic")。 當(dāng)在持有可變類型值的容器上迭代時(shí),我們需要用type()來(lái)檢查可變類型所持有的類型以便我們做出適當(dāng)?shù)捻憫?yīng)。
像這樣創(chuàng)建數(shù)據(jù)結(jié)構(gòu)是很吸引人的,因?yàn)槲覀兛梢杂梦覀兿矚g的方式組織數(shù)據(jù)。 然而QVariant的方便導(dǎo)致了性能和可讀性的損耗。 一般地,只要有可能,用它定義一個(gè)適當(dāng)?shù)腃++類來(lái)存儲(chǔ)我們的數(shù)據(jù)是值得的。
QVariant被Qt的元對(duì)象系統(tǒng)所使用并且因此是QtCore模塊的一部分。 不過(guò),當(dāng)我們連接上QtGui模塊,QVariant能存儲(chǔ)GUI-related類型,如QColor,QFont,QIcon,QImage, 和QPixmap:
QIcon icon("open.png"); QVariant variant = icon;
為了從QVariant將GUI-related類型值解引用,我們可以使用QVariant::value()模板函數(shù)像下面這樣:
QIcon icon = variant.value();
value()還用于non-GUI數(shù)據(jù)類型和QVariant之間的轉(zhuǎn)換,但實(shí)踐中我們一般為non-GUI類型使用to...()轉(zhuǎn)換函數(shù)(例如,toString())。
QVariant還可以被用來(lái)保存自定義數(shù)據(jù)類型,假如它們提供一個(gè)缺省構(gòu)造函數(shù)和一個(gè)拷貝構(gòu)造函數(shù)。 為了這個(gè)能工作,我們必須首先使用Q_DECLARE_METATYPE()宏注冊(cè)類型,放在頭文件中類定義的下方:
Q_DECLARE_METATYPE(BusinessCard)
這使我們像這樣寫代碼:
BusinessCard businessCard; QVariant variant = QVariant::fromValue(businessCard); ... if (variant.canConvert()) { BusinessCard card = variant.value(); ... }
因?yàn)榫幾g器的限制,這些模板函數(shù)在MSVC 6中不可用。如果你需要使用這個(gè)編譯器,用全局函數(shù)qVariantFromValue(),qVariantValue(), 和qVariantCanConvert()來(lái)代替。
如果自定義數(shù)據(jù)類型有<<和>>操作符為了寫讀一個(gè)QDataStream,我們可以用qRegisterMetaTypeStreamOperators()注冊(cè)它們。 此外,這使得通過(guò)QSettings來(lái)存儲(chǔ)自定義數(shù)據(jù)類型的參數(shù)成為可能。 例如:
qRegisterMetaTypeStreamOperators("BusinessCard");
這章的重點(diǎn)是Qt容器,以及QString,QByteArray, 和QVariant。 除了這些類,Qt還提供一些其他的容器。 一個(gè)是QPair<t1, t2="">,它簡(jiǎn)單地存儲(chǔ)兩個(gè)值,類似于std::pair<t1, t2="">。 另一個(gè)是QBitArray,我們將在第十九章第一節(jié)使用它。 最后是QVarLengthArray<t,prealloc>,QVector的一個(gè)底層替代品(low-level alternative)。 因?yàn)樗跅I项A(yù)分配內(nèi)存并且不是隱式共享,所以它的開(kāi)銷要比QVector小,這使得它適合高效的循環(huán)(tight loops)。
Qt的算法,包括一些沒(méi)有在這里提到的像qCopyBackward()和qEqual(),在Qt的文檔http://doc.trolltech.com/4.1/algorithms.html里有描述。 Qt容器的更多信息,包括它們的時(shí)間復(fù)雜度和增長(zhǎng)策略,參見(jiàn)http://doc.trolltech.com/4.1/containers.html。
總結(jié)
以上是生活随笔為你收集整理的QT QString 很全的使用 (转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Excel表格怎么给文字插入双下划线 添
- 下一篇: 学信网app在线验证可以延期几次 在线验