Hex to char array in C
Solution 1:
You can't fit 5 bytes worth of data into a 4 byte array; that leads to buffer overflows.
If you have the hex digits in a string, you can use sscanf()
and a loop:
#include <stdio.h>
#include <ctype.h>
int main()
{
const char *src = "0011223344";
char buffer[5];
char *dst = buffer;
char *end = buffer + sizeof(buffer);
unsigned int u;
while (dst < end && sscanf(src, "%2x", &u) == 1)
{
*dst++ = u;
src += 2;
}
for (dst = buffer; dst < end; dst++)
printf("%d: %c (%d, 0x%02x)\n", dst - buffer,
(isprint(*dst) ? *dst : '.'), *dst, *dst);
return(0);
}
Note that printing the string starting with a zero-byte requires care; most operations terminate on the first null byte. Note that this code did not null-terminate the buffer; it is not clear whether null-termination is desirable, and there isn't enough space in the buffer I declared to add a terminal null (but that is readily fixed). There's a decent chance that if the code was packaged as a subroutine, it would need to return the length of the converted string (though you could also argue it is the length of the source string divided by two).
Solution 2:
I would do something like this;
// Convert from ascii hex representation to binary
// Examples;
// "00" -> 0
// "2a" -> 42
// "ff" -> 255
// Case insensitive, 2 characters of input required, no error checking
int hex2bin( const char *s )
{
int ret=0;
int i;
for( i=0; i<2; i++ )
{
char c = *s++;
int n=0;
if( '0'<=c && c<='9' )
n = c-'0';
else if( 'a'<=c && c<='f' )
n = 10 + c-'a';
else if( 'A'<=c && c<='F' )
n = 10 + c-'A';
ret = n + ret*16;
}
return ret;
}
int main()
{
const char *in = "0011223344";
char out[5];
int i;
// Hex to binary conversion loop. For example;
// If in="0011223344" set out[] to {0x00,0x11,0x22,0x33,0x44}
for( i=0; i<5; i++ )
{
out[i] = hex2bin( in );
in += 2;
}
return 0;
}
Solution 3:
If the string is correct and no need to keep its content then i would do it this way:
#define hex(c) ((*(c)>='a')?*(c)-'a'+10:(*(c)>='A')?*(c)-'A'+10:*(c)-'0')
void hex2char( char *to ){
for(char *from=to; *from; from+=2) *to++=hex(from)*16+hex(from+1);
*to=0;
}
EDIT 1: sorry, i forget to calculate with the letters A-F (a-f)
EDIT 2: i tried to write a more pedantic code:
#include <string.h>
int xdigit( char digit ){
int val;
if( '0' <= digit && digit <= '9' ) val = digit -'0';
else if( 'a' <= digit && digit <= 'f' ) val = digit -'a'+10;
else if( 'A' <= digit && digit <= 'F' ) val = digit -'A'+10;
else val = -1;
return val;
}
int xstr2str( char *buf, unsigned bufsize, const char *in ){
if( !in ) return -1; // missing input string
unsigned inlen=strlen(in);
if( inlen%2 != 0 ) return -2; // hex string must even sized
for( unsigned i=0; i<inlen; i++ )
if( xdigit(in[i])<0 ) return -3; // bad character in hex string
if( !buf || bufsize<inlen/2+1 ) return -4; // no buffer or too small
for( unsigned i=0,j=0; i<inlen; i+=2,j++ )
buf[j] = xdigit(in[i])*16 + xdigit(in[i+1]);
buf[inlen/2] = '\0';
return inlen/2+1;
}
Testing:
#include <stdio.h>
char buf[100] = "test";
void test( char *buf, const char *s ){
printf("%3i=xstr2str( \"%s\", 100, \"%s\" )\n", xstr2str( buf, 100, s ), buf, s );
}
int main(){
test( buf, (char*)0 );
test( buf, "123" );
test( buf, "3x" );
test( (char*)0, "" );
test( buf, "" );
test( buf, "3C3e" );
test( buf, "3c31323e" );
strcpy( buf, "616263" ); test( buf, buf );
}
Result:
-1=xstr2str( "test", 100, "(null)" )
-2=xstr2str( "test", 100, "123" )
-3=xstr2str( "test", 100, "3x" )
-4=xstr2str( "(null)", 100, "" )
1=xstr2str( "", 100, "" )
3=xstr2str( "", 100, "3C3e" )
5=xstr2str( "", 100, "3c31323e" )
4=xstr2str( "abc", 100, "abc" )