三种方法:stoi,strtol,sscanf
各函数具体用法本文不赘述。
测试一:只含数字的十六进制字符串
string str("123");
int a = stoi(str,0,16);
int b = strtol(str.c_str(),0,16);
int c;
sscanf(str.c_str(),"%X",&c);
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
结果:
a = 291
b = 291
c = 291
测试二:含有数字和字母的十六进制字符串
string str("0x1f42a"); //0x 前缀有没有都可以
int a = stoi(str,0,16);
int b = strtol(str.c_str(),0,16);
int c;
sscanf(str.c_str(),"%X",&c); //X不分大小写
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
结果:
a = 128042
b = 128042
c = 128042
测试三:空串(本文的主要目的)
string str("");
int a;
//a = stoi(str,0,16);
int b;
b = strtol(str.c_str(),0,16);
int c;
sscanf(str.c_str(),"%X",&c);
//cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
结果:
stoi
会抛异常:terminate called after throwing an instance of ‘std::invalid_argument’
what(): stoi
b = 0
c = 120135921
针对空白字符串的结论:stoi
抛异常,程序终止;strtol
返回0(我最喜欢……);sscanf
不执行转换。
测试四:超出范围
string str("12345678123456781");
int a;
// a = stoi(str,0,16); //stoi抛异常,程序结束
int b;
b = strtol(str.c_str(),0,16); //64位系统下,long int为8字节
int c;
sscanf(str.c_str(),"%X",&c);
printf("%d,%s \n",errno,strerror(errno));
// cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
结果:
terminate called after throwing an instance of ‘std::out_of_range’
what(): stoi
error: Numerical result out of range
b = -1
c = -1
strtol和sscanf都返回-1,并将 errno 的值设置为 ERANGE。
测试五:字符串中含有空格
string str("34 12"); // " 34 12" 、" 34*12"结果一样
int a;
a = stoi(str,0,16);
int b;
b = strtol(str.c_str(),0,16);
int c;
sscanf(str.c_str(),"%X",&c);
// printf("%d,%s \n",errno,strerror(errno));
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
结果:
a = 52
b = 52
c = 52
结论:三个函数都是忽略开始的空格,直到再次遇到空格或其它无效字符为止,取中间有效字符转换。
针对普通字节流通讯中十六进制数据包解析的应用:
stoi
最严格,一言不合抛异常,程序终止,不太适合变长数据包的解析,因为被访问的字节可能是空串,但是比较适合定长数据包的解析。strtol
比较适合变长数据包的解析,容错性好,空串返回0,适合逻辑判断。sscanf
,不!喜!欢!,但不拒绝使用……