Qt中的字符串操作
3.1 概述
對於一個應用程序來說,文本操作幾乎是無處不在的,無論是窗體應用還是控制檯應用都難免要做諸如顯示,輸入,處理文本之類的操作。因此字符串作爲文本的載體也就必不可少,大多數編程語言都直接或者間接的提供了字符串類型以方便我們操作字符串,比如C++標準庫提供的字符串類std::string。Qt作爲一個跨平臺開發框架實現了自己的字符串類型QString,該類型廣泛應用於Qt應用程序中,也是各種Qt圖形用戶控件的基礎。鑑於上面這些考慮以及自己學習中遇到的麻煩,決定先從QString來入手各種組件的學習。
3.2 通過QDebug輸出調試信息
在正式接觸QString之前我們先來看一下在Qt中如何向控制檯輸出信息,假設要向控制檯輸出Hello,World!,在C++學習中我們最常用的做法就是:
//直接輸出string literals
std::cout<<"Hello,World!"<<std::endl;
//輸出String類的對象
std::string str("Hello,String!");
std::cout<<str<<std::endl;
在Qt應用程序開發中當然也可以這樣做,能否成功使用std::cout來輸出這些字符串依賴於輸出操作符能否正確的識別作爲右操作數的字符串,在C++中這些操作已經通過**重載輸出操作符<<**來完成了。而在Qt中因爲其內部控件大量使用QString類型,這種類型不能被輸出操作符識別,因此這樣的方法也就不可行:
QString str("Hello,QString!");
std::cout<<str<<std<<endl; //會報錯,輸出操作符不認識QString類型
爲了完成這些Qt內置數據類型的正確輸出,在Qt中我們通常使用qDebug()(嚴格來說這不是函數,而是一個定義在頭文件QtGlobal中的宏),他有下面兩種常見的用法,第一種方法中qDebug()就類似與C語言的庫函數printf(),對於控制檯應用程序該函數會把參數輸出到控制檯:
qDebug("Items in list: %d", myList.size());
另一種用法更加簡潔,如同C++操作輸出流的方法,這種方法需要包含頭文件QDebug才能正常使用(因爲該方法中會用到QDebug對象):
#include <QDebug>
#include <QString>
QString qStr("Hello,QString!");
qDebug()<<qStr;//使用qDebug輸出結尾默認已經換行,用不着endl
注意兩點:
- 上面提到qDebug宏在頭文件QtGlobal中定義,不過由於該頭文件在大多數其他頭文件中已經被包含,所以不用手動再次包含。比如在Qt主程序中默認包含的QCoreApplication文件中就有QtGlobal。
- 在引入QDebug頭文件後,qDebug宏會返回一個QDebug類的實例。
- 如果定義了宏QT_NO_DEBUG_OUTPUT,則qDebug會失效。
3.3 QString對象的構造和訪問
知道了如何對QString進行輸出之後,就可以進一步來看QString類的用法了,首先先了解一下QString是什麼,閱讀官方文檔之後大概可以摘出來下面幾點:
- QString是由QChars構成的序列,而QChars支持UNICODE編碼
- QString支持std::string和std::wstring的相互轉換
- QString底層實現採用 implicit sharing (copy-on-write) 技術來減少內存開支和不必要的數據拷貝。
- 跨各種平臺,由Qt保證。
然後我們注意考察QString的常見用法,首先是創建字符串,最簡單地,我們可以*通過一個C風格字符串(const char )來初始化一個QString:
QString str = "Hello,World!";
也可以通過QChars數組的方式來構造一個字符串,此時必須指定字符數組大小,否則會一直找到’\0’才停止:
const QChar data[5] = {'H','e','l','l','o'};
QString str(data,5);
const QChar data1[6] = {'H','e','l','l','o','\0'};
QString str(data1);
還有一種方法是通過resize()調整QString的大小,然後爲每一個元素逐一賦值,而字符串的訪問有兩種方法,對於普通字符串可以直接使用運算符[],得到一個可以用作賦值運算左值的字符引用:
QString str;
str.resize(4);
str[0] = QChar('U');
str[1] = QChar('n');
str[2] = QChar(0x10e3);
str[3] = QChar(0x03a3);
對於常量字符串,或者其他要求只讀的場合,可以用QString的at方法來取得索引位置的字符:
const QString str("gabcdefg");
//遍歷字符串,找到其中介於a-f之間的字符並輸出提示信息
for (int i = 0; i < str.size(); ++i) {
if (str.at(i) >= QChar('a') && str.at(i) <= QChar('f'))
qDebug() << "Found character in range [a-f]";
}
用於索引QString中的字符的函數除了at以外還有mid,ledf,right等:
const QChar at(int position) const
QString mid(int position, int n = -1) const
QString left(int n) const
QString right(int n) const
現在小結並列舉一下QString類的全部構造函數:
QString(const QByteArray &ba) //通過字節數組構造,會轉換爲UNICODE
QString(const char *str) //通過C風格字符串構造
QString(QString &&other) //移動構造函數
QString(const QString &other) //複製構造函數
QString(QLatin1String str) //通過Latin-1編碼(單字節編碼,兼容ASCII)的字符串構造
QString(int size, QChar ch) //通過size個QChar構造
QString(QChar ch) //通過一個QChar構造長度爲1的QString
QString(const QChar *unicode, int size = -1) //通過QChar數組構造,如果不指定size則檢查到'\0'停止
QString() //空字符串
3.4 QString的比較
QString可以和字符串字面值之間進行比較:
QString qStr5 = "string";
if(qStr5 == "string"){
qDebug()<<"true";
}
if(qStr5 != "String"){
qDebug()<<"false";
}
QString重載的比較運算髮非常多,具體信息可以在Qt官方文檔查看。
3.5 類型轉換
3.5.1 不同類型字符串之間的轉換
Qt還提供了QString和C風格字符串之間的轉換方法,*如果要將C風格字符串轉換爲QString類型直接使用QString(const char )構造函數即可,上面的例子已經展示過了。QString對象向C風格字符串轉換則可以使用qPrintable宏來完成:
qDebug()<<qPrintable(qStr5);
//下面的做法是錯誤的
const char *cStr = qPrintable(qStr5);
qDebug()<<cStr;
**需要注意的是,qPrintable宏返回的const char 在這條語句之後便無效了,再使用該指針會引發指針錯誤,因此qPrintable通常只用於實參要求const char 的場合。
3.5.2 QString轉數值類型
此處直接使用QString對象的toInt(), toLongLong(), toDouble()等方法即可:
QString str = "12";
int i = str.toInt();//i = 12
QString str1 = "1234.56";
str1.toFloat();
bool ok;
QString str2 = "R2D2";
str2.toFloat(&ok);
QString str3 = "1234.56 Volt";
str3.toFloat(&ok);
這些函數使用方法大抵類似,就不用一一舉例了。
注意這些函數可以接收一個布爾指針,如果該指針不是nullptr,則轉換成功時把指針置true,失敗時置爲false。
3.5.3 數值類型轉QString
通過調用QString對象的成員函數setNum():
QString str;
str.setNum(1234);
3.6 處理字符串
3.6.1 追加字符串
QString str = "and";
//追加到開頭
str.prepend("rock "); // str == "rock and"
//追加到結尾
str.append(" roll"); // str == "rock and roll"
//指定位置處插入字符串
str.insert(5,"Hello");
下面列出insert的全部重載版本:
QString & insert(int position, const QString &str)
QString & insert(int position, QChar ch)
QString & insert(int position, const QChar *unicode, int size)
QString & insert(int position, const QStringRef &str)
QString & insert(int position, QLatin1String str)
QString & insert(int position, const char *str)
QString & insert(int position, const QByteArray &str)
3.6.2 替換字符串
QString str = "rock and roll";
str.replace(5, 3, "&"); // str == "rock & roll"
replace的全部重載版本:
QString & replace(int position, int n, const QString &after)
QString & replace(int position, int n, QChar after)
QString & replace(int position, int n, const QChar *unicode, int size)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & replace(const QChar *before, int blen, const QChar *after, int alen, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & replace(QLatin1String before, QLatin1String after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & replace(QLatin1String before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & replace(const QString &before, QLatin1String after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & replace(QChar ch, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & replace(QChar c, QLatin1String after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & replace(const QRegExp &rx, const QString &after)
QString & replace(const QRegularExpression &re, const QString &after)
3.6.3 刪除子串
利用remove從字符串中刪除某一子串,下面是最簡單的例子,通過其實位置和長度兩個參數來指定子串:
QString s = "Montreal";
s.remove(1, 4);
// s == "Meal"
各種重載版本如下:
QString & remove(int position, int n)
QString & remove(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & remove(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & remove(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QString & remove(const QRegExp &rx)
QString & remove(const QRegularExpression &re)
3.6.4 查找子串
indexOf會返回子串在字符串中首次出現的位置:
QString x = "Hello,WoHelrld!";
QString y = "Hel";
x.indexOf(y);
x.indexOf(y, 1); //第二個參數是指定起始位置,默認爲0
該函數有很多重載版本,如下:
int indexOf(QLatin1String str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
int indexOf(QChar ch, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
int indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
int indexOf(const QStringRef &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
int indexOf(QStringView str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
int indexOf(const QRegExp &rx, int from = 0) const
int indexOf(QRegExp &rx, int from = 0) const
int indexOf(const QRegularExpression &re, int from = 0) const
int indexOf(const QRegularExpression &re, int from, QRegularExpressionMatch *rmatch) const
count會得到某個子字符串的出現次數:
QString s = "Hello World";
qDebug() << s.count("l");
查找該字符串是否以某個子字符串開始或者結束:
QString s = "hello,qstring!";
bool b1 = s.startsWith("hel");
bool b2 = s.endsWith("ing");
3.7 其他常用方法
3.7.1 分割字符串:
QString str = "a,,b,c";
QStringList list1 = str.split(','); // list1: [ "a", "", "b", "c" ]
3.7.2 大小寫轉換:
返回的是一個全大寫,或者全爲小寫的字符串拷貝。
QStrig str = "abcdefg";
str.toUpper();
str.toLower();
3.7.3 獲取字符串長度
獲取字符串長度有兩個方法,他們是一樣的:
QString str = "Returns the number of characters in this string. Equivalent to size().";
str.length();
str.size();