字符串和十六進制數的轉換(總結網上的代碼)


因為用到的轉換功能都需要在Qt中實現,所以先介紹一下QString 、string和char *  的轉換

1、QString 轉換為 string

1 using namespace std;//添加命名空間
2 
3 QString str;
4 string myString = str.toStdString();

2、string 轉換為QString

1 using namespace std;
2 
3 string myString;
4 QString myQString = QString::fromStdString(myString);

3、QString 轉換為char *

1 QString myQString;
2 char *p = (char *)myQString.toStdString().c_str();

4、char *轉換為QString

1     char *p;
2     QString myQString = QString(p);

6、字符串和十六進制數轉換

 1 //十六進制數組轉為字符串
 2 //參數HexData為數組指針
 3 //參數iLen為數組長度
 4 //返回值為對應的十六進制字符串
 5 string HexToStr(const unsigned char* HexData , int iLen);
6 //字符串轉為十六進制數 7 //參數strData為字符串形式的十六進制值 8 //參數HexData為數組指針 9 //參數iLen為數組HexData的長度 10 //返回值為0表示轉換成功,非0則表示轉換失敗 11 //(返回1表示長度不匹配) 12 //(返回2表示字符串中包含非十六進制的字符) 13 int StrToHex(string strData, unsigned char* HexData , int iLen);
 1 static const char Num_Hex[16]={'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F'};
 2 
 3 //十六進制數組轉為字符串
 4 //參數HexData為數組指針
 5 //參數iLen為數組長度
 6 //返回值為對應的十六進制字符串
 7 string HexToStr(const unsigned char* HexData , int iLen)
 8 {
 9     string strRet;
10     unsigned char ucTmp;
11     for(int i=0; i<iLen; i++)
12     {
13         ucTmp = *(HexData + i);
14         strRet += Num_Hex[(ucTmp>>4) & 0x0f];
15         strRet += Num_Hex[ucTmp & 0x0f];
16     }
17     return strRet;
18 }
19 //字符串轉為十六進制數
20 //參數strData為字符串形式的十六進制值
21 //參數HexData為數組指針
22 //參數iLen為數組HexData的長度
23 //返回值為0表示轉換成功,非0則表示轉換失敗
24 //(返回1表示長度不匹配)
25 //(返回2表示字符串中包含非十六進制的字符)
26 int StrToHex(string strData, unsigned char* HexData , int iLen)
27 {
28     int iRet=0;
29     unsigned char ucTmp;
30     transform(strData.begin(), strData.end(), strData.begin(), ::toupper);//字符串轉為大寫
31     int sz = strData.size();
32     if(sz != 2*iLen)
33         return 1;
34     for(int i=0 ; i<sz; i++)
35     {
36         ucTmp = strData.at(i);
37         //0-9的ASCII碼為0x30 - 0x39 , A-F的ASCII碼為0x41-0x46
38         if(!((ucTmp>=0x30 && ucTmp<=0x39) || (ucTmp>=0x41 && ucTmp<=0x46)))
39             return 2;
40     }
41     sz = sz/2;
42     for(int i=0 ; i<sz; i++)
43     {
44         ucTmp = strData.at(2*i);
45         if(ucTmp>=0x30 && ucTmp<=0x39)
46         {
47             ucTmp -= 0x30;
48         }
49         else if(ucTmp>=0x41 && ucTmp<=0x46)
50         {
51             ucTmp -= 0x37;
52         }
53         *(HexData+i) = ucTmp<<4;
54 
55         ucTmp = strData.at(2*i+1);
56         if(ucTmp>=0x30 && ucTmp<=0x39)
57         {
58             ucTmp -= 0x30;
59         }
60         else if(ucTmp>=0x41 && ucTmp<=0x46)
61         {
62             ucTmp -= 0x37;
63         }
64         *(HexData+i) += ucTmp;
65     }
66     return iRet;
67 }

 

1 transform(strData.begin(), strData.end(), strData.begin(), ::toupper);//字符串轉為大寫

 

代碼說明:為什么要加 ::toupper

 

在<cctype>里面聲明了一個C版本的函數tolower,int tolower(int); 而在<local>中間也聲明了一個函數模板:

template <class charT>
charT tolower( charT c , const locale& loc );

如果這兩個頭文件都同時包含到程序中來的話(C++標准頭文件可能會包含另外的標 准頭文件。例如有的編譯器在一些標准頭文件中,如<iostream>,會包含<locale>或<cctype> 頭文件。這樣,包含<iostream>可能會引入<locale>或<cctype>),由於這些 tolower 函數都位於同一 std 名字空間,於是形成了函數重載。這樣的話,transform 函數(也是一個模板函數)的第四個參數是tolower 的時候,此時給定的 tolower 只是作為一個函數指針使用,缺乏類型推導所需要的函數參數信息,所以無法推導出函數的類型,也就無法決定使用哪一個重載函數。

如果想使用非模版的 tolower 函數,有多種方法可以解決:

 

 

 

transform( s.begin(), s.end(), s.begin(), (int(*)(int))tolower);
或者:

int (*pf)( int ) = tolower; // pf 是一個函數指針,其類型已經明確。 transform( s.begin(), s.end(), s.begin(), pf );

或者:
// 使用一個包裝函數,避免直接使用 tolower 函數由於重載帶來的問題。 int my_tolower( int c ) { return tolower( c ); // 根據 c 的類型可以確定使用 tolower 的哪個重載函數。 }
 

// …
// my_tolower 是非模版非重載函數,避免了函數重載帶來的類型解析問題。
transform( s.begin(), s.end(), s.begin(), my_tolower );

另外,非模板函數的 tolower 其實是來自於標准 C 庫函數,因此在 C++ 標准庫中它同時位於全局和 std 名字空間。既然 std 名字空間內 tolower 函數有可能形成函數重載,但是在全局名字空間中的 tolower 函數卻只有一個,所以也可以直接使用全局名字空間中的 tolower:

 

transform( s.begin(), s.end(), s.begin(), ::tolower);

當然,模板函數和非模板函數 tolower 的區別還是很明顯的:前者有兩個參數,后者只有一個參數。而程序中使用的 transform 函數的第四個參數要求,如果是函數的話只能是有一個參數的函數,所以從這方面來說重載函數的選擇問題是可以得到解決的。有的編譯器可能就是根據這一點做了 進一步的判別處理,或者直接選擇了非模版函數,從而解決了這一問題。但是 C++ 標准並沒有要求一定要解決類似的不確定問題,所以無論編譯器是怎樣處理的,解決或者沒有解決,應該都是符合標准的。

至此,問題成功解決。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM