十六进制转换成字符串——CRC

继前天的,完成了计算阶乘,今天计算CRC32。

本来将数字转换成字符串直接使用sprintf就可以了,我在PC上也这样用,没问题。但我对DSP完全不熟悉,在DSP端的代码中使用如sprintf这些函数,结果没有得到预期效果,DSP应该不能使用这些函数吧?(注:可以使用,没得到预期效果是因为对内存操作错误造成的。)

没办法,只好自己写一个,参考网上的十进制转换字符串的做法,代码如下:

void hex_to_string(unsigned int num, char *str)
{
    int i = 0;
    int n = 0;
    char tmp;
    if (num == 0)
    {
        str[0] = '0';
        str[1] = '\0';
        return;
    }
    while (num > 0)
    {
        tmp = num % 16;
        if (tmp >= 0 && tmp <= 9)
            str[n] = tmp + '0';
        else if (tmp >= 10 && tmp <= 15)
            str[n] = tmp + 'A' - 0x0a;
        num /= 16;
        n++;
    }

    for (i = 0; i < n / 2; i++)
    {
        tmp = str[i];
        str[i] = str[n - i - 1];
        str[n - i - 1] = tmp;
    }
    str[n] = '\0';
}


函数的目的是将计算好的CRC32值转换成字符串形式,发送到ARM端。

有几个说明:

1、十进制、十六进制在内存中表现完全一样,只是printf使用不同的输出格式就得到不同的进制。传入的参数是无符号类型,如果是有符号的,结果是不正确的,像“hello world.”的CRC32值是930BDFFC,用printf的%d和%u打印的结果是不同的,如下:

930BDFFC -1827938308 2467028988

只能说,这个数就在内存中,你是有符号,还是无符号,数还是那个数,数就在那里。

2、将十进制转换成十六进制就是将十进制数除以16,取余数。这里是放到数组中,当然是ASCII码了。所以要做一个判断,当余数为0~9范围内时,说明是数字0~9,对应的ASCII码就是将这个数加上48,48、0x30、'0'都是一样的,为了阅读的方便,代码中写成'0'。当余数为10~15时,就是十六进制的'A'~'F',至于为什么要减去10,因为前面10个数是数字,不是字母。

3、上面得到的结果是反的,所以要倒过来放。为什么是反的,试一下就知道了。

4、还是前天说的,没有手动搞个'\0'上去,就不算正常的字符串,打印出来的结果会连着后面的数据。在PC上没有这种情况发生,但在DSP上,它就是发生了。不知道这个疑问到什么时候才能解决。

5、如果要提高所谓的效率,可以将tmp = num % 16;改为tmp = num & 0xf;的形式,将num /= 16;改为num >>= 4;的形式。

 

测试结果:

# ./loopgpp_new loop_new.out "http://www.latelee.org"
the string you input: http://www.latelee.org
string: http://www.latelee.org crc32: 7D696766 7D696766
=============== Sample Application : LOOP ==========
Entered LOOP_Create ()
Leaving LOOP_Create ()
Entered LOOP_Execute ()
crc: 7D696766
37 44 36 39 36 37 36 36 0 77 2e 6c 61 74 65 6c 65 65 2e 6f 72 67 0 64 2e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
end. buffer size: 128 LOOP_NumIterations: 1
Leaving LOOP_Execute ()
Entered LOOP_Delete ()
Leaving LOOP_Delete ()
====================================================

再来一个:

# ./loopgpp_new loop_new.out "hello world."             
the string you input: hello world.
string: hello world. crc32: 930BDFFC 930BDFFC
=============== Sample Application : LOOP ==========
Entered LOOP_Create ()
Leaving LOOP_Create ()
Entered LOOP_Execute ()
crc: 930BDFFC
39 33 30 42 44 46 46 43 0 6c 64 2e 0 74 65 6c 65 65 2e 6f 72 67 0 64 2e 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
end. buffer size: 128 LOOP_NumIterations: 1
Leaving LOOP_Execute ()
Entered LOOP_Delete ()
Leaving LOOP_Delete ()
====================================================

上面将128个字节的缓冲区打印出来是为了更清楚里面到底是些什么东西。

PS:话说小弟接触硬件也有两三年了,CRC是知道的,但一直没有从代码上理解,前不久才在一个偶然的机会学习,代码主要来自zlib,u-boot中的crc校验也是修改自zlib,我的是综合网络资源、zlib、u-boot三者搞出来的。

 

你可能感兴趣的:(十六进制转换成字符串——CRC)