Если строка правильная и нет необходимости сохранять ее содержимое, я бы сделал это следующим образом:
#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;
}
РЕДАКТИРОВАТЬ 1: извините, я забыл рассчитать с буквами A-F (a-f)
РЕДАКТИРОВАТЬ 2: я пытался написать более педантичный код:
#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;
}
Тестирование:
#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 );
}
Результат:
-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" )