0

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

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

如何修改此函数以使其返回字符串?IE

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

(目标是稍后比较这两个值)

4

4 回答 4

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;
}
于 2011-10-09T17:29:22.913 回答
4

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

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

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

只需比较原始形式的两个散列变量,您不需要字符串。

于 2011-10-09T17:31:16.237 回答
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.

于 2011-10-09T17:31:19.100 回答
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()函数的调用。

于 2011-10-09T17:47:00.840 回答