字符串和十六进制数的转换(总结网上的代码)

因为用到的转换功能都需要在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++ 标准并没有要求一定要解决类似的不确定问题,所以无论编译器是怎样处理的,解决或者没有解决,应该都是符合标准的。

至此,问题成功解决。

你可能感兴趣的:(十六进制)