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. 71c开发者_JAVA百科092a79cf30c4c7e7baf46a4af3c78cedec9ae3867d1e2600ffc39d58beaf2
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)
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 free
ing 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;
}
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 malloc
ed 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.
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
.
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.
精彩评论