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