用C++实现ASCII码字符数组转16进制字符数组的功能
来源:互联网 发布:大巴车出租软件 编辑:程序博客网 时间:2024/05/30 04:29
在网络通信中经常用到16进制字符数组和ASCII码字符数组互相转换的功能,虽然功能简单,但初学者写出来的代码经常会有各种问题。从ASCII码字符数组转为16进制字符数组,一个判断比较完整的实现代码如下:
bool AsciiToHex( char * Dest, char * Src, int SrcLen )
{
if ( ( Dest == NULL ) || ( Src == NULL ) )
{
return false;
}
for ( int i = 0, j = 0; i < SrcLen; j++ )
{
unsigned char HiHalf = ( unsigned char ) Src[i++] ;
unsigned char LoHalf = ( unsigned char ) Src[i++] ;
if ( HiHalf >= 'a' && HiHalf <= 'z' )
{
HiHalf -= ( 'a' - 10 );
}
else if ( HiHalf >= 'A' && HiHalf <= 'Z' )
{
HiHalf -= ( 'A' - 10 );
}
else if ( HiHalf >= '0' && HiHalf <= '9' )
{
HiHalf -= '0';
}
else
{
return false;
}
if ( LoHalf >= 'a' && LoHalf <= 'z' )
{
LoHalf -= ( 'a' - 10 );
}
else if ( LoHalf >= 'A' && LoHalf <= 'Z' )
{
LoHalf -= ( 'A' - 10 );
}
else if ( LoHalf >= '0' && LoHalf <= '9' )
{
LoHalf -= '0';
}
else
{
return false;
}
Dest[j] = ( HiHalf << 4 ) | LoHalf;
}
return true;
}
以上代码中,比较了Dest和Src是否为NULL,还判断了字符数组Src里是否有非法字符(即0-9、A-Z、a-z以外的字符),进行计算的时候也使用了更安全的unsigned char类型,看起来很不错。但当SrcLen参数错误,为奇数时Dest会多写一个字节,可能会导致数组越界。 另外以上代码在效率上有严重的问题。一般我们在通信中是把10-15转为大写的A-F,以上代码先和小写字母判断,会导致一些无用功。另外被转换的Src字符为0-15,数字0-9有10个,字母A-F有6个,理论上出现数字的概率大。所以要先判断是否数字,再判断是否大写字母,最后判断是否小写字母,剩下的就是非法字符了。比较代码就应该如下:
if ( HiHalf >= '0' && HiHalf <= '9' )
{
HiHalf -= '0';
}
else if ( HiHalf >= 'A' && HiHalf <= 'F' )
{
HiHalf -= ( 'A' - 10 );
}
else if ( HiHalf >= 'a' && HiHalf <= 'f' )
{
HiHalf -= ( 'a' - 10 );
}
else
{
return false;
}
在修正后的比较代码中,仍然有效率问题。举例如下,当HiHalf等于'A'时,因为 '0' < '9' < 'A' < 'F' < 'a' < 'f',HiHalf分别和'0'、'9'、'A'、‘F’做了4次比较。如果我们将代码改为:
if ( HiHalf <= '9' && HiHalf >= '0' )
{
HiHalf -= '0';
}
else if ( HiHalf <= 'F' && HiHalf >= 'A' )
{
HiHalf -= ( 'A' - 10 );
}
else if ( HiHalf <= 'f' && HiHalf >= 'a' )
{
HiHalf -= ( 'a' - 10 );
}
else
{
return false;
}
那么HiHalf和'9'比较后,就不会再和'0'去比较了,比较次数从4次变成了3次。同理对小写字母来说,比较次数减少了2次。
另外为了调用方便,将Src、Dest的类型从char *改为void *。最终版本的代码如下:
bool AsciiToHex( void * DestBuf, void * SrcBuf, int SrcLen )
{
if ( ( DestBuf == NULL ) || ( SrcBuf == NULL ) )
{
return false;
}
unsigned char * Dest = ( unsigned char * ) DestBuf;
unsigned char * Src = ( unsigned char * ) SrcBuf;
int DestLen = SrcLen >> 1;
for ( int SrcPos = -1, DestPos = 0; DestPos < DestLen; )
{
unsigned char HiHalf = Src[++SrcPos];
unsigned char LoHalf = Src[++SrcPos];
if ( HiHalf <= '9' && HiHalf >= '0' )
{
HiHalf -= '0';
}
else if ( HiHalf <= 'F' && HiHalf >= 'A' )
{
HiHalf -= 55;
}
else if ( HiHalf <= 'f' && HiHalf >= 'a' )
{
HiHalf -= 87;
}
else
{
return false;
}
if ( LoHalf <= '9' && LoHalf >= '0' )
{
LoHalf -= '0';
}
else if ( LoHalf <= 'F' && LoHalf >= 'A' )
{
LoHalf -= 55;
}
else if ( LoHalf <= 'f' && LoHalf >= 'a' )
{
LoHalf -= 87;
}
else
{
return false;
}
Dest[DestPos++] = ( HiHalf << 4 ) | LoHalf;
}
return true;
}
有兴趣的同学可以写个单元测试验证一下转化结果。或者用效率更高的查表法来实现,节省更多计算步骤和时间。
bool AsciiToHex( char * Dest, char * Src, int SrcLen )
{
if ( ( Dest == NULL ) || ( Src == NULL ) )
{
return false;
}
for ( int i = 0, j = 0; i < SrcLen; j++ )
{
unsigned char HiHalf = ( unsigned char ) Src[i++] ;
unsigned char LoHalf = ( unsigned char ) Src[i++] ;
if ( HiHalf >= 'a' && HiHalf <= 'z' )
{
HiHalf -= ( 'a' - 10 );
}
else if ( HiHalf >= 'A' && HiHalf <= 'Z' )
{
HiHalf -= ( 'A' - 10 );
}
else if ( HiHalf >= '0' && HiHalf <= '9' )
{
HiHalf -= '0';
}
else
{
return false;
}
if ( LoHalf >= 'a' && LoHalf <= 'z' )
{
LoHalf -= ( 'a' - 10 );
}
else if ( LoHalf >= 'A' && LoHalf <= 'Z' )
{
LoHalf -= ( 'A' - 10 );
}
else if ( LoHalf >= '0' && LoHalf <= '9' )
{
LoHalf -= '0';
}
else
{
return false;
}
Dest[j] = ( HiHalf << 4 ) | LoHalf;
}
return true;
}
以上代码中,比较了Dest和Src是否为NULL,还判断了字符数组Src里是否有非法字符(即0-9、A-Z、a-z以外的字符),进行计算的时候也使用了更安全的unsigned char类型,看起来很不错。但当SrcLen参数错误,为奇数时Dest会多写一个字节,可能会导致数组越界。 另外以上代码在效率上有严重的问题。一般我们在通信中是把10-15转为大写的A-F,以上代码先和小写字母判断,会导致一些无用功。另外被转换的Src字符为0-15,数字0-9有10个,字母A-F有6个,理论上出现数字的概率大。所以要先判断是否数字,再判断是否大写字母,最后判断是否小写字母,剩下的就是非法字符了。比较代码就应该如下:
if ( HiHalf >= '0' && HiHalf <= '9' )
{
HiHalf -= '0';
}
else if ( HiHalf >= 'A' && HiHalf <= 'F' )
{
HiHalf -= ( 'A' - 10 );
}
else if ( HiHalf >= 'a' && HiHalf <= 'f' )
{
HiHalf -= ( 'a' - 10 );
}
else
{
return false;
}
在修正后的比较代码中,仍然有效率问题。举例如下,当HiHalf等于'A'时,因为 '0' < '9' < 'A' < 'F' < 'a' < 'f',HiHalf分别和'0'、'9'、'A'、‘F’做了4次比较。如果我们将代码改为:
if ( HiHalf <= '9' && HiHalf >= '0' )
{
HiHalf -= '0';
}
else if ( HiHalf <= 'F' && HiHalf >= 'A' )
{
HiHalf -= ( 'A' - 10 );
}
else if ( HiHalf <= 'f' && HiHalf >= 'a' )
{
HiHalf -= ( 'a' - 10 );
}
else
{
return false;
}
那么HiHalf和'9'比较后,就不会再和'0'去比较了,比较次数从4次变成了3次。同理对小写字母来说,比较次数减少了2次。
另外为了调用方便,将Src、Dest的类型从char *改为void *。最终版本的代码如下:
bool AsciiToHex( void * DestBuf, void * SrcBuf, int SrcLen )
{
if ( ( DestBuf == NULL ) || ( SrcBuf == NULL ) )
{
return false;
}
unsigned char * Dest = ( unsigned char * ) DestBuf;
unsigned char * Src = ( unsigned char * ) SrcBuf;
int DestLen = SrcLen >> 1;
for ( int SrcPos = -1, DestPos = 0; DestPos < DestLen; )
{
unsigned char HiHalf = Src[++SrcPos];
unsigned char LoHalf = Src[++SrcPos];
if ( HiHalf <= '9' && HiHalf >= '0' )
{
HiHalf -= '0';
}
else if ( HiHalf <= 'F' && HiHalf >= 'A' )
{
HiHalf -= 55;
}
else if ( HiHalf <= 'f' && HiHalf >= 'a' )
{
HiHalf -= 87;
}
else
{
return false;
}
if ( LoHalf <= '9' && LoHalf >= '0' )
{
LoHalf -= '0';
}
else if ( LoHalf <= 'F' && LoHalf >= 'A' )
{
LoHalf -= 55;
}
else if ( LoHalf <= 'f' && LoHalf >= 'a' )
{
LoHalf -= 87;
}
else
{
return false;
}
Dest[DestPos++] = ( HiHalf << 4 ) | LoHalf;
}
return true;
}
有兴趣的同学可以写个单元测试验证一下转化结果。或者用效率更高的查表法来实现,节省更多计算步骤和时间。
0 0
- 用C++实现ASCII码字符数组转16进制字符数组的功能
- 用C++编写16进制字符数组转ASCII码字符数组的函数
- C#中16进制转化成ASCII码字符
- Unicode字符与ASCII码字符的相互转化
- 宽字符和ASCII码字符的转换
- PHP将含有中英文ASCII码字符串切割为单字数组
- 简单的ASCII码字符串加密
- C++编写二进制字符数组转ASCII码的函数
- ASCII码字符表
- ASCII码字符表
- ASCII 码字符
- ASCII码字符表
- 实现ASCII码字符集到Unicode字符集之间的转换
- 实现数组的功能
- ASCII码字库的显示
- ASCII码字符加密解密
- ASCII码字符对照表
- ASCII码字符对照表
- 74HC/LS/HCT/F系列芯片的区别
- IIS7中的站点、应用程序和虚拟目录详细介绍
- Linux学习之CentOS(二十五)--Linux磁盘管理:LVM逻辑卷基本概念及LVM的工作原理
- 单片机的led跑马灯程序
- 暴力枚举-POJ2965 The Pilots Brothers' refrigerator
- 用C++实现ASCII码字符数组转16进制字符数组的功能
- http://os.51cto.com/art/201005/202380.htm
- C++编写二进制字符数组转ASCII码的函数
- Co-training&主动学习
- IIS中网站匿名访问权限问题解决办法
- uva 1315 - Crazy tea party(数论)
- VirtualBox 共享文件夹设置 及 开机自动挂载
- web开发常识积累
- poj2386Lake Counting(DFS算法)