Преобразование шестнадцатеричных значений в массив символов в C - PullRequest
0 голосов
/ 09 октября 2011

Я пытаюсь реализовать функцию, которая возвращает строку шестнадцатеричных значений.Я печатаю шестнадцатеричные значения, используя эту функцию:

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 ]

6 голосов
/ 09 октября 2011
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;
}
4 голосов
/ 09 октября 2011

Как я могу изменить эту функцию, чтобы она возвращала строку?

Вы можете печатать в строковую переменную, используя sprintf. Я предполагаю, что размер хеша фиксирован, поэтому вы знаете, что размер вашей строки будет number-of-chars-in-hash * 2 + 1. Как вернуть эту информацию - типичная проблема в C, вы можете либо вернуть malloc ed строку, которую пользователь затем должен запомнить free, либо вернуть статическую строку, которая будет заменена следующим вызовом функции ( и делает функцию неповторимой). Лично я стараюсь не возвращать строки, вместо этого вместо функции принимаю char* назначение и размер.

(цель в том, чтобы я мог сравнить 2 значения позже)

Просто сравните две хеш-переменные в необработанном виде, для этого вам не нужны строки.

2 голосов
/ 09 октября 2011

Функция sprintf() делает то же самое, что и printf(), за исключением того, что она "печатает" в буфер символов.При этом ваша функция может выглядеть так:

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.

0 голосов
/ 09 октября 2011

Пользователь должен передать в буфер для записи вместе с размером. Очевидно, что функция должна быть переименована. Даже это немного общего; возможно, оно должно быть 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().

...