destructo_gold
destructo_gold

Reputation: 319

Convert hex values to char array in C

I'm trying to implement a function which returns a string of hex values. I print the hex values out using this function:

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");
}

This outputs some hex value, e.g. 71c092a79cf30c4c7e7baf46a4af3c78cedec9ae3867d1e2600ffc39d58beaf2

How can I modify this function so that it returns a string? i.e.

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

(The goal being to compare the 2 values later)

Upvotes: 0

Views: 4414

Answers (4)

Jonathan Leffler
Jonathan Leffler

Reputation: 754480

Have the user pass in the buffer to be written to, along with the size. Obviously, the function has to be renamed. Even this is a bit generic; it should perhaps be format_hash_to_hex_string() because of the hashid parameter.

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;
}

Or, if you trust your users to provide a big enough buffer:

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]);
}

Or if you prefer bit twiddling (which probably is quicker than calling 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;
}

To justify the generic name, it would be better to replace the hashid type parameter with a simple length (and you could then reasonably assume that the programmer knows that the buffer length must be at least 2 times the hash length):

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';
}

This now is a general purpose function. And you could wrap it to specialize it for your hash formatting if you wanted to; the wrapper might save you writing a few calls to your mhash_get_block_size() function.

Upvotes: 0

Matteo Italia
Matteo Italia

Reputation: 126867

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;
}

Obviously the caller is responsible for freeing the returned string.

Still, as @K-Ballo correctly said in his answer, you don't need to convert to string form two hashes to compare them, all you need in that case is just a 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;
}

Upvotes: 6

sth
sth

Reputation: 229754

The sprintf() function does the same thing as printf(), except that it "prints" to a char buffer. With that your function could look like this:

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;
    }
}

Note that this assumes that a buffer of suitable size is passed in as outbuf.

Upvotes: 2

K-ballo
K-ballo

Reputation: 81379

How can I modify this function so that it returns a string?

You can print to a string variable using sprintf. I assume the hash size is fixed, so you know the size of your string would be number-of-chars-in-hash * 2 + 1. How to return that information is a typical problem in C, you can either return a malloced string that the user must then remember to free, or return a static string that will get replaced with the next call to the function (and makes the function non-reentrable). Personally I tend to avoid returning strings, instead having the function take a char* destination and a size.

(The goal being that I can compare the 2 values later)

Just compare the two hash variables in its raw form, you don't need strings for that.

Upvotes: 4

Related Questions