当前位置:  开发笔记 > 编程语言 > 正文

将二进制数据转换为可打印的十六进制

如何解决《将二进制数据转换为可打印的十六进制》经验,为你挑选了2个好方法。

在这个帖子中,有人评论说下面的代码只能在'玩具'项目中使用.不幸的是,他还没有回来说明为什么它不符合生产质量,所以我希望社区中的某个人能够向我保证代码没问题(因为我非常喜欢)或者找出错误.

template< class T1, class T2>
void hexascii( T1& out, const T2& in )
{
    out.resize( in.size() * 2 );
    const char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7','8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    T1::iterator outit = out.begin();
    for( T2::const_iterator it = in.begin(); it != in.end(); ++it )
    {
        *outit++ = hexDigits[*it >> 4];
        *outit++ = hexDigits[*it & 0xF];
    }
}

template
void asciihex( T1& out, const T2& in )
{
    size_t size = in.size;
    assert( !(size % 2) );

    out.resize( size / 2 );
    T1::iterator outit = out.begin();
    for( T2::const_iterator it = in.begin(); it != in.end(); it += 2, ++outit )
    {
    *outit = ((( (*it > '9' ? *it - 0x07 : *it)  - 0x30) << 4) & 0x00f0) + 
                (((*(it+1) > '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f);
    }
}

编辑:感谢您的帮助,您已经做了一些重大改进.我从你的答案中写出了两种建议风格的函数.一些粗略的测试表明第二种方法比第一种方法稍微快一些,但IMO比第一种方法的可读性提高了.

template
void asciihex2( T1& out, const std::string& in )
{
    dassert( sizeof(T1::value_type)==1 );
    size_t size = in.size();
assert( !(size % 2) );
    out.resize( size / 2 );
    T1::iterator outit = out.begin();
    for( size_t i = 0; i < in.size(); i += 2 )
    {
        int tmp;
        sscanf( in.c_str() + i, "%02X", &tmp );
        *outit++ = tmp;
    }
}

template
void asciihex3( T1& out, const std::string& in )
{
    dassert( sizeof(T1::value_type)==1 );
    size_t size = in.size();
assert( !(size % 2) );
    out.resize( size / 2 );
    T1::iterator outit = out.begin();
const char hexDigits[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                  0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
for( std::string::const_iterator it = in.begin(); it != in.end(); it += 2, ++outit )
    {
    *outit = (hexDigits[(*it - 0x30) & 0x1f] << 4) + 
              hexDigits[((*(it+1) - 0x30) & 0x1f)];
    }
}

这段代码中的一些假设:1:它们不是通用的,而是在匿名名称空间中用于转换特定类的数据.2:模板是必需的,因为正在使用两个单独的容器类型(一个是std :: vector,另一个是来自第三方库的类似字节数组类型容器.3:目的是能够转换不确定的二进制数据长度为字符串然后再返回(0x1234abcd < - >"1234abcd")4:在调试和释放模式下断言陷阱错误5:当调用这些函数时,字符串的大小已经被检查,断言用于如果出现严重问题则终止处理6:需要一些评论

任何其他想法赞赏.



1> SmacL..:

考虑到在标准C scanfprintf函数中有直接的十六进制转换,似乎很多模板化代码实现得很少.何必?



2> unknownuser..:

我对它的主要评论是,它很难阅读.

特别:

*outit = ((( (*it > '9' ? *it - 0x07 : *it)  - 0x30) << 4) & 0x00f0) + 
            (((*(it+1) > '9' ? *(it+1) - 0x07 : *(it+1)) - 0x30) & 0x000f)

如果我继承了代码,那么我的大脑会花一点时间来解决这个问题,并让我烦恼.

推荐阅读
低调pasta_730
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有