将十六进制值转换为C中的char数组

时间:2011-10-09 17:24:07

标签: c hash hex format-specifiers

我正在尝试实现一个返回十六进制值字符串的函数。我使用此函数打印出十六进制值:

void print_hex(unsigned char *hash, const hashid type) {

    int i;
    for (i = 0; i < mhash_get_block_size(type); i++) {
        printf("%.2x", hex[i]);
    }
    printf("\n");
}

这会输出一些十六进制值,例如71c092a79cf30c4c7e7baf46a4af3c78cedec9ae3867d1e2600ffc39d58beaf2

如何修改此函数以便返回字符串?即。

unsigned char *get_hash_str(unsigned char *hash, const hashid type) { /* ?? */ }

(目标是稍后比较2个值)

4 个答案:

答案 0 :(得分:6)

char * print_hex(const unsigned char *hash, const hashid type)
{
    const char lookupTable[]="0123456789abcdef";
    const size_t hashLength=mhash_get_block_size(type);
    size_t i;
    char * out=malloc(hashLength*2+1);
    if(out==NULL)
        return NULL;
    for (i = 0; i < hashLength; i++)
    {
        out[i*2]=lookupTable[hash[i]>>4];
        out[i*2+1]=lookupTable[hash[i]&0xf];
    }
    out[hashLength*2]=0;
    return out;
}

显然调用者负责free返回的字符串。

然而,正如@ K-Ballo在他的回答中正确地说的那样,你不需要将两个哈希值转换成字符串来比较它们,在这种情况下你需要的只是一个memcmp

int compare_hashes(const unsigned char * hash1, const hashid hash1type, const unsigned char * hash2, const hashid hash2type)
{
    if(hash1type!=hash2type)
        return 0;
    return memcmp(hash1, hash2, mhash_get_block_size(hash1type))==0;
}

答案 1 :(得分:4)

  

如何修改此函数以便返回字符串?

您可以使用sprintf打印到字符串变量。我假设散列大小是固定的,因此您知道字符串的大小为number-of-chars-in-hash * 2 + 1。如何返回该信息是C中的典型问题,您可以将用户必须记住的malloc ed字符串返回到free,或者返回一个静态字符串,该字符串将被下一次调用替换到函数(并使函数不可重新执行)。就个人而言,我倾向于避免返回字符串,而是让函数采用char*目的地和大小。

  

(目标是我可以稍后比较2个值)

只需比较原始形式的两个哈希变量,就不需要字符串了。

答案 2 :(得分:2)

sprintf()函数与printf()的作用相同,只是它“打印”到char缓冲区。这样你的功能可能如下所示:

void sprint_hex(char *outbuf, unsigned char *hash, const hashid type) {
    int i;
    for (i = 0; i < mhash_get_block_size(type); i++) {
        sprintf(outbuf, "%.2x", hex[i]);
        outbuf += 2;
    }
}

请注意,这假设适当大小的缓冲区作为outbuf传递。

答案 3 :(得分:0)

让用户传入要写入的缓冲区以及大小。显然,该功能必须重命名。即使这有点通用;由于format_hash_to_hex_string()参数,它应该是hashid

int format_hex_string(unsigned char const *hash, hashid type, char *buffer, size_t buflen)
{
    size_t n = mhash_get_block_size(type);
    if (buflen < 2 * n + 1)
        return -1;
    for (size_t i = 0; i < n; i++)
        sprintf(&buffer[2*i], "%.2X", hash[i]);
    return 0;
}

或者,如果您信任您的用户提供足够大的缓冲区:

format_hex_string(unsigned char const *hash, hashid type, char *buffer)
{
    size_t n = mhash_get_block_size(type);
    for (size_t i = 0; i < n; i++)
        sprintf(&buffer[2*i], "%.2X", hash[i]);
}

或者如果你喜欢比特笨拙(这可能比调用sprintf()更快):

int format_hex_string(unsigned char const *hash, hashid type, char *buffer, size_t buflen)
{
    static char const hexdigits[] = "0123456789ABCDEF";
    size_t n = mhash_get_block_size(type);
    if (buflen < 2 * n + 1)
        return -1;
    for (size_t i = 0; i < n; i++)
    {
        *buffer++ = hexdigits[hash[i] >>  4];
        *buffer++ = hexdigits[hash[i] & 0xF];
    }
    *buffer = '\0';
    return 0;
}

为了证明通用名称的合理性,最好用简单的长度替换hashid type参数(然后你可以合理地假设程序员知道缓冲区长度必须至少是哈希长度的2倍) ):

int format_hex_string(unsigned char const *binbuffer, size_t binlen, char *hexbuffer)
{
    static char const hexdigits[] = "0123456789ABCDEF";
    for (size_t i = 0; i < binlen; i++)
    {
        *hexbuffer++ = hexdigits[binbuffer[i] >>  4];
        *hexbuffer++ = hexdigits[binbuffer[i] & 0xF];
    }
    *hexbuffer = '\0';
}

现在这是一个通用功能。如果你愿意的话,你可以把它包装成专门用于你的哈希格式化;包装器可能会节省您向mhash_get_block_size()函数写几个调用。