先要說(shuō)的是QString。
之所以把QString單獨(dú)拿出來(lái),是因?yàn)閟tring是很常用的一個(gè)數(shù)據(jù)結(jié)構(gòu),甚至在很多語(yǔ)言中,比如JavaScript,都是把string作為一種同int等一樣的基本數(shù)據(jù)結(jié)構(gòu)來(lái)實(shí)現(xiàn)的。
每一個(gè)GUI程序都需要string,這些string可以用在界面上的提示語(yǔ),也可以用作一般的數(shù)據(jù)結(jié)構(gòu)。C++語(yǔ)言提供了兩種字符串的實(shí)現(xiàn):C風(fēng)格的 字符串,以'\0‘結(jié)尾;std::string,即標(biāo)準(zhǔn)模版庫(kù)中的類(lèi)。Qt則提供了自己的字符串實(shí)現(xiàn):QString。QString以16位 Uniode進(jìn)行編碼。我們平常用的ASCII等一些編碼集都作為Unicode編碼的子集提供。關(guān)于編碼的問(wèn)題,我們會(huì)到以后的時(shí)候再詳細(xì)說(shuō)明。
在使用QString的時(shí)候,我們不需要擔(dān)心內(nèi)存分配以及關(guān)于'\0'結(jié)尾的這些注意事項(xiàng)。QString會(huì)把這些問(wèn)題解決。通常,你可以把 QString看作是一個(gè)QChar的向量。另外,與C風(fēng)格的字符串不同,QString中間是可以包含'\0'符號(hào)的,而length()函數(shù)則會(huì)返回 整個(gè)字符串的長(zhǎng)度,而不僅僅是從開(kāi)始到'\0'的長(zhǎng)度。
同Java的String類(lèi)類(lèi)似,QString也重載的+和+=運(yùn)算符。這兩個(gè)運(yùn)算符可以把兩個(gè)字符串連接到一起,正像Java里面的操作一樣。QString可以自動(dòng)的對(duì)占用內(nèi)存空間進(jìn)行擴(kuò)充,這種連接操作是恨迅速的。下面是這兩個(gè)操作符的使用:
QString str = "User: " ;
str += userName + "\n" ;
QString的append()函數(shù)則提供了類(lèi)似的操作,例如:
str = "User: " ;
str.append(userName);
str.append("\n" );
C語(yǔ)言中有printf()函數(shù)作為格式化輸出,QString則提供了一個(gè)sprintf()函數(shù)實(shí)現(xiàn)了相同的功能:
str.sprintf("%s %.1f%%" , "perfect competition" , 100.0);
這句代碼將輸出:perfect competition 100.0%,同C語(yǔ)言的printf()一樣。不過(guò)前面我們也見(jiàn)到了Qt提供的另一種格式化字符串輸出的函數(shù)arg():
str = QString("%1 %2 (%3s-%4s)" )
.arg("permissive" ).arg("society" ).arg(1950).arg(1970);
這段代碼中,%1, %2, %3, %4作為占位符,將被后面的arg()函數(shù)中的內(nèi)容依次替換,比如%1將被替換成permissive,%2將被替換成society,%3將被替換成 1950,%4將被替換曾1970,最后,這句代碼輸出為:permissive society (1950s-1970s). arg()函數(shù)比起sprintf()來(lái)是類(lèi)型安全的,同時(shí)它也接受多種的數(shù)據(jù)類(lèi)型作為參數(shù),因此建議使用arg()函數(shù)而不是傳統(tǒng)的 sprintf()。
使用static的函數(shù)number()可以把數(shù)字轉(zhuǎn)換成字符串。例如:
QString str = QString::number(54.3);
你也可以使用非static函數(shù)setNum()來(lái)實(shí)現(xiàn)相同的目的:
QString str;
str.setNum(54.3);
而一系列的to函數(shù)則可以將字符串轉(zhuǎn)換成其他基本類(lèi)型,例如toInt(), toDouble(), toLong()等。這些函數(shù)都接受一個(gè)bool指針作為參數(shù),函數(shù)結(jié)束之后將根據(jù)是否轉(zhuǎn)換成功設(shè)置為true或者false:
bool ok;
double d = str.toDouble(&ok);
if (ok)
{
// do something...
} else {
// do something...
}
對(duì)于QString,Qt提供了很多操作函數(shù),例如,使用mid()函數(shù)截取子串:
QString x = "Nine pineapples" ;
QString y = x .mid(5, 4); // y == "pine"
QString z = x .mid(5); // z == "pineapples"
mid()函數(shù)接受兩個(gè)參數(shù),第一個(gè)是起始位置,第二個(gè)是取串的長(zhǎng)度。如果省略第二個(gè)參數(shù),則會(huì)從起始位置截取到末尾。正如上面的例子顯示的那樣。
函數(shù)left()和rigt()類(lèi)似,都接受一個(gè)int類(lèi)型的參數(shù)n,都是對(duì)字符串進(jìn)行截取。不同之處在于,left()函數(shù)從左側(cè)截取n個(gè)字符,而right()從右側(cè)開(kāi)始截取。下面是left()的例子:
QString x = "Pineapple" ;
QString y = x.left(4); // y == "Pine"
函數(shù)indexOf()返回字符串的位置,如:
QString x = "sticky question" ;
QString y = "sti" ;
x.indexOf(y); // returns 0
x.indexOf(y, 1); // returns 10
x.indexOf(y, 10); // returns 10
x.indexOf(y, 11); // returns -1
函數(shù)startsWith()和endsWith()可以檢測(cè)字符串是不是以某個(gè)特定的串開(kāi)始或結(jié)尾,例如:
if (url.startsWith("http:" ) && url.endsWith(".png" ))
{
}
這段代碼等價(jià)于
if (url.left(5) == "http:" && url.right(4) == ".png" )
{
}
不過(guò),前者要比后者更加清楚簡(jiǎn)潔,并且性能也更快一些。
QString還提供了replace()函數(shù)供實(shí)現(xiàn)字符串的替換功能;trimmed()函數(shù)去除字符串兩側(cè)的空白字符(注意,空白字符包括空 格、Tab以及換行符,而不僅僅是空格);toLower()和toUpper()函數(shù)會(huì)將字符串轉(zhuǎn)換成小寫(xiě)大寫(xiě)字符串;remove()和 insert()函數(shù)提供了刪除和插入字符串的能力;simplified()函數(shù)可以將串中的所有連續(xù)的空白字符替換成一個(gè),并且把兩端的空白字符去 除,例如" \t ”會(huì)返回一個(gè)空格" "。
將const char *類(lèi)型的C風(fēng)格字符串轉(zhuǎn)換成QString也是很常見(jiàn)的需求,簡(jiǎn)單來(lái)說(shuō),QString的+=即可完成這個(gè)功能:
str += " (1870)" ;
這里,我們將const char * 類(lèi)型的字符串" (1870)"轉(zhuǎn)換成為QString類(lèi)型。如果需要顯式的轉(zhuǎn)換,可以使用QString的強(qiáng)制轉(zhuǎn)換操作,或者是使用函數(shù)fromAscii()等。為了 將QString類(lèi)型轉(zhuǎn)成const char *字符串,需要進(jìn)行兩步操作,一是使用toAscii()獲得一個(gè)QByteArray類(lèi)型對(duì)象,然后調(diào)用它的data()或者constData()函 數(shù),例如:
printf("User: %s\n" , str.toAscii().data());
為了方便使用,Qt提供了一個(gè)宏qPrintable(),這個(gè)宏等價(jià)于toAscii().constData(),例如:
printf("User: %s\n" , qPrintable(str));
我們調(diào)用QByteArray類(lèi)上面的data()或者constData()函數(shù),將獲得QByteArray內(nèi)部的一個(gè)const char*類(lèi)型的字符串,因此,我們不需要擔(dān)心內(nèi)存泄漏等的問(wèn)題,Qt會(huì)替我們管理好內(nèi)存。不過(guò)這也暗示我們,注意不要使用這個(gè)指針太長(zhǎng)時(shí)間,因?yàn)槿绻?QByteArray被delete,那么這個(gè)指針也就成為野指針了。如果這個(gè)QByteArray對(duì)象沒(méi)有被放在一個(gè)變量中,那么當(dāng)語(yǔ)句結(jié)束 后,QbyteArray對(duì)象就會(huì)被delete,這個(gè)指針也就被delete 了。
接下來(lái)說(shuō)說(shuō)QString和QByteArray之間的轉(zhuǎn)換 ,這里說(shuō)兩種,都是從網(wǎng)上搜到的。
第一種,數(shù)據(jù)流的方式,這里只說(shuō)從QByteArray轉(zhuǎn)向QString。
QByteArray encodedString = "xxx";
QTextCodec *codec = QTextCodec::codecForName("KOI8-R");
QString string = codec->toUnicode(encodedString);
[另外]
char ch_str[10] = "搜索";
QString str = QString::fromLocal8Bit(ch_str);
第二種,常用的,網(wǎng)上看到的。
//常用參數(shù)類(lèi)型:char *字符串, QByteArray字符數(shù)組, QString字符串
//需要轉(zhuǎn)換:char * ---轉(zhuǎn)--- QByteArray ---需要調(diào)用QByteArray類(lèi)的構(gòu)造函數(shù)
char* --------------QByteArray(const char*)-----------> QByteArray
char* str;
QByteArray byte(str);
char* --------------QString(const char*)-------------->QString
char* str;
QString string(str);
QByteArray -------------data()-------------------->char*
QByteArray byte;
char* str = byte.data();
QByteArray ------------QString()------------------->QString
QByteArray byte;
QString string(byte);
QString --------------toAscii()--------------------> QByteArray
QString string;
QByteArray byte = string.toAscii();
QString -------------qPrintable()------------------>char*
QString string;
char* str = qPrintable(string);
或QString --------toLatin1()------QByteArray----------data()--------->char*
QString string;
QByteArray ba=string.toLatin1();
const char* str = ba.data();