QT QString 很全的使用 (轉)

來源:互聯網
上載者:User

標籤:

QString, QByteArray, 和 QVariant這三個類和容器有許多相同之處,並且在一些情況下可以被當作特殊的容器。 同樣,像容器,這些類使用隱式共用來最佳化記憶體和速度。

我們將從QString開始。 字串被每個GUI程式所使用,不僅是使用者介面而且還有資料結構。 C++原生提供兩種字串: 傳統的C風格以‘\0‘結尾的字元數組和std::string類。 與這些不同,QString使用16-bit Unicode值。 Unicode 包含 ASCII 和 Latin-1 這個子集和它們的普通數值。 而QString是16-bit,所以它可以表示世界上絕大多數語言的字元。 Unicode的更多資訊,請看十七章。

當使用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 %.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);

如果我們希望找出一個字串是否包含某個字元,字串,或Regex,我們可以使用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 \t THE \nDOG \n"; qDebug() << str.trimmed();

字串str可被描述為:

trimmed()返回的字串是:

當處理使用者輸入時,我們經常希望將一個或多個內部空白符替換為單個空格,另外還要過濾掉兩端的空白符。 這就是simplified()函數所做的:

QString str = " BOB \t THE \nDOG \n"; 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("\n");

當處理字串時,我們經常需要判斷一個字串是否是空。 調用isEmpty()或檢查length()是否為0就可以達到目的。

在大多數情況下,從const char *字串到QString的轉換是自動的,例如:

str += " (1870)";

這裡我們將一個const char *加到一個QString上,沒有任何約束。 要將一個const char *顯示轉換成一個QString,就簡單地使用一個QString cast,或者調用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\n", str.toAscii().data());

為了方便,Qt提供qPrintable()宏,它執行和toAscii().constData()順序相同的操作。

printf("User: %s\n", 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總是 ‘\0‘,使得傳遞一個QByteArray給一個帶有const char *型別參數的函數時操作變得簡單。 QByteArray還支援內嵌的‘\0‘字元,這允許我們用它來儲存任意位元據(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 很全的使用 (轉)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.