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

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

至此,问题成功解决。

posted on 2014-09-19 12:10  辉常的D调  阅读(4830)  评论(0编辑  收藏  举报

导航