现在的位置: 首页 > 综合 > 正文

C++编写二进制字符数组转ASCII码的函数

2018年05月17日 ⁄ 综合 ⁄ 共 1339字 ⁄ 字号 评论关闭

原文链接:http://blog.csdn.net/gzliudan/article/details/23478169

    在工控通信中经常用到16进制和ASCII码字符数组互相转换的功能,虽然功能简单,但初学者写出来的代码经常会有各种问题。从16进制转为ASCII吗的功能函数,一个比较简洁的实现版本如下:

void HexToAscii( char * Dest, char * Src, int SrcLen )
{
    for ( int i = 0, j = 0; i < SrcLen; i++ )
    {
         char HiHalf = Src[i] >> 4;
         char LoHalf = Src[i] & 0x0F;
         Dest[j++] = ( HiHalf <= 9 ) ? ( HiHalf + '0' ) : ( HiHalf - 10 + 'A' );
         Dest[j++] = ( LoHalf <= 9 ) ? ( LoHalf + '0' ) : ( LoHalf - 10 + 'A' );
    }
}

    在以上短短几行代码里,基础比较扎实的同学比较容易发现的一个Bug是用signed char来处理二进制数据,这样当被处理的字节Src[i]是负数时就会出现错误的转换结果。同样把HiHalf和LoHalf声明为int,也是有相同Bug的。解决办法是先把Src[i]转为unsigned char,并且把HiHalf和LoHalf定义为unsigned char。

    一个比较隐蔽的严重问题是当Dest和Src字符数组有重叠的地址空间时,转换结果也会不对。例如Dest和Src的地址相等时,Src[0]转换为Dest[0]和Dest[1]后,Src[1]被Dest[1]覆盖,Src[1]还没转换里面的数据已经不是原来的数据了,依次类推。

    除此以外,传进来的指针Dest和Src都要先判断是否等于NULL,这样才能尽量保证写出安全的代码。

   最后一点,最好把Dest和Src声明为void *类型的指针,这样对非char类型的数据调用此函数时,就不需要强制转化。

   修正后的代码如下:

void HexToAscii( void * DestBuf, void * SrcBuf, int SrcLen )
{
    if ( ( DestBuf == NULL ) || ( SrcBuf == NULL ) )
    {
    return;
    }

    unsigned char * Dest = (unsigned char *) DestBuf;
    unsigned char * Src = (unsigned char *) SrcBuf;
    int DestPos = SrcLen << 1;
    int SrcPos = SrcLen;

    while ( --SrcPos >= 0 )
    {
         unsigned char HiHalf = Src[SrcPos] >> 4;
         unsigned char LoHalf = Src[SrcPos] & 0x0F;
         Dest[--DestPos] = ( HiHalf <= 9 ) ? ( HiHalf + '0' ) : ( HiHalf + 55 );
         Dest[--DestPos] = ( LoHalf <= 9 ) ? ( LoHalf + '0' ) : ( LoHalf + 55 );
    }
}

    有兴趣的同学可以写个单元测试验证一下转化结果。或者改用查表法来转化,省去一些计算步骤。

抱歉!评论已关闭.