官术网_书友最值得收藏!

3.2 字節(jié)數(shù)組類QByteArray

字節(jié)數(shù)組類QByteArray提供一個(gè)字節(jié)數(shù)組,用于存儲(chǔ)原始字節(jié)。使用QByteArray類比使用char *更方便。該類在串口通信中經(jīng)常被使用,因?yàn)榇谕ㄐ艛?shù)據(jù)都是一個(gè)一個(gè)的8位字節(jié)流。

3.2.1 初始化

通常有兩種方法可以初始化QByteArray類的對(duì)象。

第一種方法是通過(guò)const char *將其傳遞給構(gòu)造函數(shù)。例如,以下代碼創(chuàng)建一個(gè)大小為5個(gè)字節(jié)的字節(jié)數(shù)組,數(shù)據(jù)為“Hello”:

    QByteArray ba("Hello");

雖然我們定義了5個(gè)字節(jié)長(zhǎng)度的字節(jié)數(shù)組對(duì)象,索引范圍從0到4,但是系統(tǒng)自動(dòng)會(huì)在字節(jié)數(shù)組對(duì)象結(jié)尾添加一個(gè)'\0'字符,這是為了某些場(chǎng)合使用方便。所以,我們?cè)谒饕?的位置可以得到字符數(shù)據(jù)'\0',比如:

第二種方法是使用resize()設(shè)置數(shù)組的大小,并初始化每個(gè)數(shù)組元素。

    QByteArray ba;
    ba.resize(6);
    ba[0] = 0x3c;
    ba[1] = 0xb8;
    ba[2] = 0x64;
    ba[3] = 0x18;
    ba[4] = 0xca;

QByteArray類使用從0開(kāi)始的索引值,就像C++數(shù)組一樣。在調(diào)用resize()后,新分配的字節(jié)具有未定義的值。要將所有字節(jié)設(shè)置為特定值,可以調(diào)用fill()函數(shù),該函數(shù)的原型聲明如下:

    QByteArray &QByteArray::fill(char ch, int size = -1)

其中,參數(shù)ch是要給字節(jié)數(shù)組設(shè)置的字符;size如果不是-1,就表示重新要為字節(jié)數(shù)組開(kāi)辟的空間大小。比如:

第一次調(diào)用fill()函數(shù)后,ba所有空間的內(nèi)容都是字符o了;第二次調(diào)用fill()函數(shù)后,因?yàn)閒ill()函數(shù)的第二個(gè)參數(shù)size是2,所以會(huì)重新調(diào)整ba的空間大小,變?yōu)?個(gè)字節(jié),而且內(nèi)容重新設(shè)置為"XX"。

3.2.2 訪問(wèn)某個(gè)元素

訪問(wèn)QByteArray類對(duì)象中的某個(gè)元素主要有4種方式,分別為[]、at()、data[]和constData[]。其中,[]和data[]方式為可讀可寫(xiě),at()和constData[]方式僅為可讀。如果只是進(jìn)行讀操作,則通過(guò)at()和constData[]方式的訪問(wèn)速度最快,因?yàn)楸苊饬藦?fù)制處理。

at()可以比operator []()更快,就是因?yàn)榍罢卟粫?huì)發(fā)生深層復(fù)制。

【例3.2】 訪問(wèn)QByteArray類對(duì)象中的單個(gè)數(shù)據(jù)

(1)啟動(dòng)Qt Creator 4.8.2,新建一個(gè)控制臺(tái)項(xiàng)目,項(xiàng)目名為test。

(2)在main.cpp中輸入如下代碼:

qDebug()會(huì)輸出ba[2]對(duì)應(yīng)的字符,ASCII碼為0x64的字符是'd'。

(3)按Ctrl+R快捷鍵運(yùn)行項(xiàng)目,結(jié)果如圖3-2所示。

圖3-2

3.2.3 截取子字符串

要一次提取多個(gè)字節(jié),可使用函數(shù)left()、right()或mid()。

(1)函數(shù)left()返回從索引0位置開(kāi)始、長(zhǎng)度為len的子字節(jié)數(shù)組,該函數(shù)的原型聲明如下:

    QByteArray left(int len)

其中,參數(shù)len表示從數(shù)組左邊開(kāi)始要截取的字節(jié)數(shù)組的長(zhǎng)度,如果len大于原來(lái)整個(gè)字節(jié)數(shù)組的長(zhǎng)度,則返回整個(gè)字節(jié)數(shù)組。下列代碼演示了函數(shù)left()函數(shù)的使用:

      QByteArray x("Pineapple");
      QByteArray y = x.left(4);
      // y == "Pine"

(2)函數(shù)right()用來(lái)獲取從字節(jié)數(shù)組最后一個(gè)字節(jié)數(shù)據(jù)開(kāi)始,向前面截取len個(gè)字節(jié)并返回截取的子字節(jié)數(shù)組。該函數(shù)的原型聲明如下:

    QByteArray right(int len)

其中,參數(shù)len表示從右邊開(kāi)始要截取的子字節(jié)數(shù)組的長(zhǎng)度,如果len大于原來(lái)整個(gè)字節(jié)數(shù)組的長(zhǎng)度,則返回整個(gè)字節(jié)數(shù)組。下列代碼演示了函數(shù)right()函數(shù)的使用:

    QByteArray x("Pineapple");
    QByteArray y = x.right(5);
    // y == "apple"

(3)函數(shù)mid()返回從指定索引位置開(kāi)始,向右邊(即后面)長(zhǎng)度為len的子字節(jié)數(shù)組。該函數(shù)的原型聲明如下:

    QByteArray mid(int pos, int len = -1)

其中,參數(shù)pos表示開(kāi)始截取的索引,索引值從0開(kāi)始;len表示要截取的子字節(jié)數(shù)組的長(zhǎng)度,如果len為-1(默認(rèn)值)或pos+len大于原字節(jié)數(shù)組的長(zhǎng)度,則返回從pos開(kāi)始一直到右邊剩下的全部字節(jié)數(shù)組。下列代碼演示了函數(shù)mid()函數(shù)的使用:

3.2.4 獲取字節(jié)數(shù)組的大小

可以用成員函數(shù)size、length和count來(lái)獲取字節(jié)數(shù)組的大小。除了名字不同,這3個(gè)函數(shù)是等同的,函數(shù)的原型聲明如下:

    int size();
    int length();
    int count();

這3個(gè)函數(shù)返回字節(jié)數(shù)組中的字節(jié)數(shù)。Size()函數(shù)的用法如下:

      QByteArray ba("Hello");
      int n = ba.size();       // n == 5

執(zhí)行后,n等于5。可見(jiàn),size()并不包含字符串末尾自動(dòng)添加的'\0'。另外,如果以字符串形式初始化,中間有'\0',則size()不會(huì)統(tǒng)計(jì)'\0'及其后面的字符。

    QByteArray ba2("He\0llo");
    int n = ba2.size();      // n == 2

執(zhí)行后,n等于2。通過(guò)resize分配空間,然后通過(guò)逐個(gè)賦值來(lái)進(jìn)行初始化的話,中間某個(gè)字節(jié)數(shù)據(jù)是'\0',并不會(huì)被size()函數(shù)截?cái)唷1热纾?/p>

3.2.5 數(shù)據(jù)轉(zhuǎn)換與處理

從串口讀取到的QByteArray數(shù)據(jù)一般需要進(jìn)行提取和解析,此時(shí)就需要將QByteArray數(shù)據(jù)轉(zhuǎn)換為各種類型的數(shù)據(jù)。常用的轉(zhuǎn)換包括:

(1)轉(zhuǎn)為Hex,用于顯示十六進(jìn)制,這點(diǎn)在調(diào)試時(shí)特別有用,因?yàn)榇蠖郒EX碼是沒(méi)有字符顯示的,如0x00、0x20等。

(2)轉(zhuǎn)為不同進(jìn)制數(shù)值并顯示,如二進(jìn)制、八進(jìn)制、十進(jìn)制和十六進(jìn)制等數(shù)值。

(3)轉(zhuǎn)為整數(shù)類型、浮點(diǎn)類型等的數(shù)據(jù)類型。

(4)字母大小寫(xiě)進(jìn)行轉(zhuǎn)換。

(5)轉(zhuǎn)為字符串類型。

1. Hex轉(zhuǎn)換(十六進(jìn)制轉(zhuǎn)換)

QByteArray類的公有靜態(tài)函數(shù)QByteArray::fromHex可以把十六進(jìn)制編碼的數(shù)據(jù)轉(zhuǎn)換為字符(char)類型的數(shù)據(jù),并存儲(chǔ)到QByteArray類對(duì)象中。該函數(shù)的原型聲明如下:

    QByteArray fromHex(const QByteArray &hexEncoded)

其中,參數(shù)hexEncoded是十六進(jìn)制編碼的字節(jié)數(shù)組。由于該函數(shù)并不檢查參數(shù)的有效性,因此遇到非十六進(jìn)制數(shù)據(jù)則直接略過(guò),然后繼續(xù)處理剩余的數(shù)據(jù)。下列代碼演示了fromHex()函數(shù)的使用:

字符'5'和'1'為一組,轉(zhuǎn)為十六進(jìn)制數(shù)據(jù)0x51,0x51對(duì)應(yīng)的十進(jìn)制數(shù)據(jù)是81,ASCII碼為81的字符是'Q'。

與fromHex()相逆的函數(shù)是toHex(),該函數(shù)將字節(jié)數(shù)組中十六進(jìn)制的數(shù)值編碼轉(zhuǎn)化為字符,它的原型聲明如下:

    QByteArray toHex()

下列代碼演示了toHex()函數(shù)的使用:

索引為0的字節(jié)數(shù)據(jù)為0x30,直接轉(zhuǎn)為兩個(gè)字符'3'和'0'。

2. 數(shù)值轉(zhuǎn)換與輸出

盡管QByteArray類是一個(gè)集合,但也可以作為一個(gè)特殊形式的數(shù)值來(lái)用,其靈活的轉(zhuǎn)換格式可大大方便各種格式數(shù)據(jù)轉(zhuǎn)換與顯示的需求,如顯示二進(jìn)制和十六進(jìn)制、顯示科學(xué)記數(shù)和指定小數(shù)位的數(shù)值。QByteArray類的公有靜態(tài)函數(shù)number可以完成這些功能。該函數(shù)可以將某個(gè)整數(shù)轉(zhuǎn)為某種進(jìn)制的字符數(shù)組,函數(shù)number的原型聲明如下:

    QByteArray number(int n, int base = 10)

其中,參數(shù)n是要轉(zhuǎn)變的整數(shù);base是要進(jìn)行轉(zhuǎn)換的進(jìn)制,進(jìn)制取值范圍為2到36,即從二進(jìn)制到三十六進(jìn)制。該函數(shù)返回整數(shù)n對(duì)應(yīng)的base進(jìn)制的字符數(shù)組。下列代碼演示了number()函數(shù)的使用:

與此公有靜態(tài)函數(shù)功能類似的公有函數(shù)是setNum(),該函數(shù)也是將某個(gè)整數(shù)轉(zhuǎn)為某種進(jìn)制的字符數(shù)組,函數(shù)的原型聲明如下:

    QByteArray & setNum(int n, int base = 10)

其中,參數(shù)n是要轉(zhuǎn)變的整數(shù);base是要進(jìn)行轉(zhuǎn)換的進(jìn)制,進(jìn)制取值范圍為2到36,即從二進(jìn)制到三十六進(jìn)制。該函數(shù)返回整數(shù)n對(duì)應(yīng)的base進(jìn)制的字符數(shù)組。下列代碼演示了setNum()函數(shù)的使用:

        QByteArray ba;
        int n = 63;
        ba.setNum(n);   // ba == "63"
        ba.setNum(n, 16);  // ba == "3f"

因?yàn)椴皇庆o態(tài)函數(shù),所以要用對(duì)象來(lái)調(diào)用。此外,根據(jù)setNum()函數(shù)第一個(gè)參數(shù)的類型,setNum()函數(shù)可以有多種版本,比如:

    QByteArray &QByteArray::setNum(ushort n, int base = 10)
    QByteArray &QByteArray::setNum(short n, int base = 10)
    QByteArray &QByteArray::setNum(uint n, int base = 10)
    QByteArray &QByteArray::setNum(qlonglong n, int base = 10)

用法類似,只是n的取值范圍不同。

除了整數(shù)之外,還能把數(shù)值按指定格式和小數(shù)位轉(zhuǎn)換輸出,所調(diào)用的函數(shù)依舊是number(),只不過(guò)參數(shù)形式變了:

    QByteArray number(double n, char f = 'g', int prec = 6)

其中,參數(shù)n是要進(jìn)行轉(zhuǎn)換的實(shí)數(shù);f表示轉(zhuǎn)換格式,取值如下:

· e:采用指數(shù)法表示實(shí)數(shù),此時(shí)實(shí)數(shù)的格式如[-]9.9e[+|-]999。

· E:格式同e,不過(guò)E要大寫(xiě)。

· f:普通小數(shù)表示法,此時(shí)格式如[-]9.9。

· g:使用e或f格式,第三個(gè)參數(shù)表示有效數(shù)字位的個(gè)數(shù)。

· G:使用E或f格式,第三個(gè)參數(shù)表示有效數(shù)字位的個(gè)數(shù)。

當(dāng)參數(shù)f為'e'、'E'或'f '時(shí),prec表示十進(jìn)制小數(shù)點(diǎn)后小數(shù)部分的位數(shù);當(dāng)f為'g'或'G'時(shí),prec表示有效數(shù)字位數(shù)的最大數(shù)目。注意,小數(shù)位要四舍五入。

【例3.3】 實(shí)數(shù)轉(zhuǎn)為字節(jié)數(shù)組

(1)啟動(dòng)Qt Creator 4.8.2,新建一個(gè)控制臺(tái)項(xiàng)目,項(xiàng)目名為test。

(2)在main.cpp中輸入如下代碼:

我們分別使用了5種格式將實(shí)數(shù)12345.6轉(zhuǎn)換為字節(jié)數(shù)組,最后輸出結(jié)果。

(3)按Ctrl+R快捷鍵運(yùn)行項(xiàng)目,結(jié)果如圖3-3所示。

圖3-3

3.2.6 字母大小寫(xiě)的轉(zhuǎn)換

QByteArray類對(duì)象若為帶大小寫(xiě)字母的字符串,可調(diào)用函數(shù)toUpper()和toLower()實(shí)現(xiàn)字母大小寫(xiě)的轉(zhuǎn)換。函數(shù)toUpper()的原型聲明如下:

    QByteArray toUpper()

函數(shù)很簡(jiǎn)單,沒(méi)有參數(shù),直接返回轉(zhuǎn)換成大寫(xiě)字母后的字節(jié)數(shù)組。在轉(zhuǎn)換過(guò)程中,碰到已經(jīng)是大寫(xiě)的字母就忽略。用法舉例如下:

    QByteArray x("Qt by THE QT COMPANY");
      QByteArray y = x.toUpper();
      // y == "QT BY THE QT COMPANY"

函數(shù)toLower()也很簡(jiǎn)單,它的原型聲明如下:

    QByteArray toLower()

返回轉(zhuǎn)換成小寫(xiě)字母后的字節(jié)數(shù)組。在轉(zhuǎn)換過(guò)程中,碰到已經(jīng)是小寫(xiě)的字母就忽略。用法舉例如下:

      QByteArray x("Qt by THE QT COMPANY");
      QByteArray y = x.toLower();
      // y == "qt by the qt company"

除了字母大小寫(xiě)的轉(zhuǎn)換,QByteArray類還提供了判斷是大寫(xiě)字母還是小寫(xiě)字母的成員函數(shù)isUpper和isLower。其中,isLower()函數(shù)的原型聲明如下:

    bool isLower()

如果字節(jié)數(shù)組中只包含小寫(xiě)字母則返回true,否則返回false。

3.2.7 字符串?dāng)?shù)值轉(zhuǎn)為各類數(shù)值

QByteArray類對(duì)象的字符若都為數(shù)值,則可通過(guò)to**函數(shù)(也稱為方法)轉(zhuǎn)為各種類型的數(shù)據(jù),示例如下:

3.2.8 QByteArray與char*互轉(zhuǎn)

成員函數(shù)data可以返回指向字節(jié)數(shù)組中存儲(chǔ)數(shù)據(jù)的指針。該函數(shù)的原型聲明如下:

    char  *data();

該指針可用于訪問(wèn)和修改組成數(shù)組的元素。可以指定具體訪問(wèn)字節(jié)數(shù)組中的某一個(gè),比如ba.data()[0]表示訪問(wèn)第0個(gè)。

如果要把char*轉(zhuǎn)為QString,可以直接作為參數(shù)傳入QByteArray類的構(gòu)造函數(shù)中:

    char* pt;
    QByteArray byte(str);

我們來(lái)看一個(gè)小例子。

【例3.4】 返回char*并打印內(nèi)容。

(1)啟動(dòng)Qt Creator 4.8.2,新建一個(gè)控制臺(tái)項(xiàng)目,項(xiàng)目名為test。

(2)在test.cpp中輸入如下代碼:

(3)按Ctrl+R快捷鍵運(yùn)行項(xiàng)目,結(jié)果如圖3-4所示。

圖3-4

3.2.9 QByteArray與std::string互轉(zhuǎn)

string是C++標(biāo)準(zhǔn)庫(kù)中的字符串類型。QByteArray類提供的成員函數(shù)toStdString()可以將字節(jié)數(shù)組轉(zhuǎn)為string。該函數(shù)的原型聲明如下:

    std::string toStdString();

與該函數(shù)相反的函數(shù)是靜態(tài)成員函數(shù)fromStdString(),它將string數(shù)據(jù)轉(zhuǎn)為字節(jié)數(shù)組,該函數(shù)的原型聲明如下:

    [static] QByteArray QByteArray::fromStdString(const std::string &str);

其中,參數(shù)str是要轉(zhuǎn)換的string字符串。函數(shù)返回轉(zhuǎn)換后的字節(jié)數(shù)組。注意,轉(zhuǎn)換的是str的一份備份,轉(zhuǎn)換過(guò)程并不會(huì)影響str本身的內(nèi)容。

3.2.10 與字符串QString互轉(zhuǎn)

QString是Qt的字符串類,QByteArray是byte的數(shù)組。它們之間也可以互轉(zhuǎn)。

QByteArray與QString互轉(zhuǎn)極為簡(jiǎn)單,二者在本質(zhì)上是類似的,都是連續(xù)存儲(chǔ)的,區(qū)別是前者可以存儲(chǔ)無(wú)法顯示的字符,后者只存儲(chǔ)可顯示的字符。如QByteArray類對(duì)象可以存儲(chǔ)0x00-0x19,而QString類對(duì)象只能存儲(chǔ)如0x30等可顯示字符(0x20-0x7E)。有關(guān)可顯示字符,可參見(jiàn)ASCII表,相信大家在學(xué)習(xí)C語(yǔ)言時(shí)都了解過(guò)了。

String轉(zhuǎn)QByteArray的代碼如下:

        QString str=QString("hello world!");
        QByteArray arr = str.toLatin1();

QByteArray轉(zhuǎn)QString的代碼如下:

        QByteArray arr("hello world!");
        QString str = arr;

下面再看一下QByteArray轉(zhuǎn)為QString示例:

        QByteArray ba("abc123");
        QString str = ba;
        //或str.prepend(ba);
        qDebug()<<str ;
        //輸出:"abc123"

QString轉(zhuǎn)為QByteArray示例:

        QString str("abc123");
        QByteArray ba = str.toLatin1();
        qDebug()<<ba;
        //輸出:"abc123"

3.2.11 QByteArray與自定義結(jié)構(gòu)體之間的轉(zhuǎn)化

在Socket網(wǎng)絡(luò)編程中,網(wǎng)絡(luò)數(shù)據(jù)一般是uchar類型(最好是用uchar來(lái)傳輸,避免莫名其妙的錯(cuò)誤,另外用char類型也可以),在Qt中則可以使用QByteArray類。QByteArray類在QSocket共享庫(kù)中,根據(jù)C++中char*數(shù)據(jù)與結(jié)構(gòu)體之間的映射可以實(shí)現(xiàn)結(jié)構(gòu)體與QByteArray的轉(zhuǎn)化。下面來(lái)看一段代碼:

上面這段程序的運(yùn)行結(jié)果如下:

3.2.12 判斷是否為空

可以使用函數(shù)isEmpty()來(lái)判斷字節(jié)數(shù)組是否為空,即size是否為0。函數(shù)isEmpty()的原型聲明如下:

    bool isEmpty();

如果字節(jié)數(shù)組的size為0,則返回true,否則返回false。

下列代碼演示isEmpty()函數(shù)的使用:

    QByteArray().isEmpty();             // returns true
    QByteArray("").isEmpty();           // returns true
    QByteArray("abc").isEmpty();        // returns false

3.2.13 向前搜索和向后搜索

函數(shù)indexOf()返回該字節(jié)數(shù)組中第一次出現(xiàn)字節(jié)數(shù)組ba的索引位置,從索引位置向前搜索。該函數(shù)的原型聲明如下:

    int indexOf(const QByteArray &ba, int from = 0);

其中,參數(shù)ba為要查找的目標(biāo)字節(jié)數(shù)組ba,找到ba就返回索引值;from表示開(kāi)始搜索位置對(duì)應(yīng)的索引值,默認(rèn)從索引值為0的位置開(kāi)始搜索。如果找到ba,則返回第一次出現(xiàn)ba所在位置對(duì)應(yīng)的索引值,如果沒(méi)有找到,則返回-1。注意,所謂向前搜索,就是朝著索引值增大的方向搜索,即在數(shù)組中從左到右搜索。

下列代碼演示了這個(gè)函數(shù)的使用方法:

indexOf()還可以搜索char*和QString類型的數(shù)據(jù),函數(shù)的原型聲明如下:

    int  indexOf(const char *str, int from = 0);
    int  indexOf(const QString &str, int from = 0);

此外,還有以某個(gè)字符為搜索對(duì)象的函數(shù)聲明形式:

    int  indexOf(char ch, int from = 0);

使用示例如下:

indexOf()函數(shù)是向前搜索,另外還有一個(gè)函數(shù)lastIndexOf()是向后搜索,該函數(shù)的原型聲明如下:

    int lastIndexOf(const QByteArray &ba, int from = -1);

3.2.14 插入

函數(shù)insert()可以在某個(gè)索引位置上插入字節(jié)數(shù)組,該函數(shù)的原型聲明如下:

    QByteArray & insert(int i, const QByteArray &ba);

其中,i為要插入的索引位置;ba為要插進(jìn)去的字節(jié)數(shù)組對(duì)象。使用示例如下:

      QByteArray ba("Meal");
      ba.insert(1, QByteArray("ontr"));
      // ba == "Montreal"

此外,也可以在某個(gè)位置插入一個(gè)或多個(gè)字符,有兩個(gè)函數(shù),這兩個(gè)函數(shù)的原型聲明如下:

    QByteArray & QByteArray::insert(int i, char ch);
    QByteArray & insert(int i, int count, char ch);

其中,i為要插入的索引位置;count是要插入的字符個(gè)數(shù),其實(shí)就是count個(gè)ch;ch為要插入的字符。

另外,還有一種重載形式,就是插入char*類型的數(shù)據(jù),有兩種函數(shù)的原型聲明形式:

    QByteArray & insert(int i, const char *str);
    QByteArray & QByteArray::insert(int i, const char *str, int len);

第一種形式不帶長(zhǎng)度,插入全部str;第二種形式帶長(zhǎng)度len,len表示str中的len個(gè)字節(jié)。

此外,Qt還提供了prepend()函數(shù),該函數(shù)在原字符串開(kāi)頭插入另一個(gè)字符串。

主站蜘蛛池模板: 渝北区| 屏南县| 高邑县| 泽库县| 监利县| 务川| 定陶县| 武山县| 宜城市| 灵武市| 斗六市| 邢台县| 通州市| 绍兴市| 石楼县| 吉木萨尔县| 克什克腾旗| 九江市| 兰西县| 天祝| 会东县| 南木林县| 慈利县| 安阳市| 黑河市| 沧州市| 白河县| 和平区| 当雄县| 临清市| 孟连| 汉阴县| 方山县| 彭州市| 杭锦旗| 商城县| 东丽区| 东乌珠穆沁旗| 察雅县| 东丰县| 嘉禾县|