hexstring到C中的字节数组

是否有任何标准的C函数,从hexstring转换为字节数组
我不想写我自己的function。

据我所知,这样做没有标准的function,但以下列方式很容易实现:

#include <stdio.h> int main(int argc, char **argv) { const char hexstring[] = "deadbeef10203040b00b1e50", *pos = hexstring; unsigned char val[12]; size_t count = 0; /* WARNING: no sanitization or error-checking whatsoever */ for(count = 0; count < sizeof(val)/sizeof(val[0]); count++) { sscanf(pos, "%2hhx", &val[count]); pos += 2; } printf("0x"); for(count = 0; count < sizeof(val)/sizeof(val[0]); count++) printf("%02x", val[count]); printf("\n"); return(0); } 

编辑

正如Al指出的那样,如果string中有奇数个hex数字,则必须确保以0开头。例如,string"f00f5"将被评估为{0xf0, 0x0f, 0x05}错误地由上面的例子,而不是正确的{0x0f, 0x00, 0xf5}

我通过谷歌search发现了同样的问题。 我不喜欢调用sscanf()或strtol()的想法,因为它感觉过度杀伤。 我写了一个快速函数,它不validation文本确实是字节stream的hex表示,但会处理奇数个hex数字:

 uint8_t tallymarker_hextobin(const char * str, uint8_t * bytes, size_t blen) { uint8_t pos; uint8_t idx0; uint8_t idx1; // mapping of ASCII characters to hex values const uint8_t hashmap[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // !"#$%&' 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ()*+,-./ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>? 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // HIJKLMNO 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PQRSTUVW 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // XYZ[\]^_ 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // `abcdefg 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hijklmno 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pqrstuvw 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xyz{|}~. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ........ }; bzero(bytes, blen); for (pos = 0; ((pos < (blen*2)) && (pos < strlen(str))); pos += 2) { idx0 = (uint8_t)str[pos+0]; idx1 = (uint8_t)str[pos+1]; bytes[pos/2] = (uint8_t)(hashmap[idx0] << 4) | hashmap[idx1]; }; return(0); } 

对于短string, strtolstrtollstrtoimax将工作得很好(请注意,第三个参数是在处理string中使用的基础…设置为16)。 如果你的input比number-of-bits-in-the-longest-integer-type/4那么你将需要其他答案所build议的更灵活的方法之一。

迈克尔Foukarakis职位的一个充实的版本(因为我没有“声誉”添加评论到那个职位呢):

 #include <stdio.h> #include <string.h> void print(unsigned char *byte_array, int byte_array_size) { int i = 0; printf("0x"); for(; i < byte_array_size; i++) { printf("%02x", byte_array[i]); } printf("\n"); } int convert(const char *hex_str, unsigned char *byte_array, int byte_array_max) { int hex_str_len = strlen(hex_str); int i = 0, j = 0; // The output array size is half the hex_str length (rounded up) int byte_array_size = (hex_str_len+1)/2; if (byte_array_size > byte_array_max) { // Too big for the output array return -1; } if (hex_str_len % 2 == 1) { // hex_str is an odd length, so assume an implicit "0" prefix if (sscanf(&(hex_str[0]), "%1hhx", &(byte_array[0])) != 1) { return -1; } i = j = 1; } for (; i < hex_str_len; i+=2, j++) { if (sscanf(&(hex_str[i]), "%2hhx", &(byte_array[j])) != 1) { return -1; } } return byte_array_size; } void main() { char *examples[] = { "", "5", "D", "5D", "5Df", "deadbeef10203040b00b1e50", "02invalid55" }; unsigned char byte_array[128]; int i = 0; for (; i < sizeof(examples)/sizeof(char *); i++) { int size = convert(examples[i], byte_array, 128); if (size < 0) { printf("Failed to convert '%s'\n", examples[i]); } else if (size == 0) { printf("Nothing to convert for '%s'\n", examples[i]); } else { print(byte_array, size); } } } 

通过对user411313的代码进行一些修改,下面的代码对我有用:

 #include <stdio.h> #include <stdint.h> #include <string.h> int main () { char *hexstring = "deadbeef10203040b00b1e50"; int i; unsigned int bytearray[12]; uint8_t str_len = strlen(hexstring); for (i = 0; i < (str_len / 2); i++) { sscanf(hexstring + 2*i, "%02x", &bytearray[i]); printf("bytearray %d: %02x\n", i, bytearray[i]); } return 0; } 

但是,在一个循环中使用sscanf是相当简单的。

除了上面的优秀答案之外,我还会写一个C函数,它不使用任何库,并且对坏string有一些防范。

 uint8_t* datahex(char* string) { if(string == NULL) return NULL; size_t slength = strlen(string); if(slength % 2 == 0) // must be even return NULL; size_t dlength = slength / 2; uint8_t* data = malloc(dlength); memset(data, 0, dlength); size_t index = 0; while (index < slength) { char c = string[index]; int value = 0; if(c >= '0' && c <= '9') value = (c - '0'); else if (c >= 'A' && c <= 'F') value = (10 + (c - 'A')); else if (c >= 'a' && c <= 'f') value = (10 + (c - 'a')); else return NULL; data[(index/2)] += value << (((index + 1) % 2) * 4); index++; } return data; } 

说明:

一个。 index / 2 | 整数之间的划分将舍入该值,所以0/2 = 0,1 / 2 = 0,2 / 2 = 1,3 / 2 = 0等等。因此,对于每2个string字符,我们将该值加到1个数据字节。

(index + 1)%2 | 我们希望奇数的结果为1,甚至为0,因为hexstring的第一个数字是最重要的,需要乘以16.所以对于索引0 => 0 + 1%2 = 1,索引1 => 1 + 1%2 = 0等

C。 << 4 | 按4移位乘以16.例如:b00000001 << 4 = b00010000

 char *hexstring = "deadbeef10203040b00b1e50", *pos = hexstring; unsigned char val[12]; while( *pos ) { if( !((pos-hexstring)&1) ) sscanf(pos,"%02x",&val[(pos-hexstring)>>1]); ++pos; } 

(val)/ sizeof(val [0])是多余的!

  In main() { printf("enter string :\n"); fgets(buf, 200, stdin); unsigned char str_len = strlen(buf); k=0; unsigned char bytearray[100]; for(j=0;j<str_len-1;j=j+2) { bytearray[k++]=converttohex(&buffer[j]); printf(" %02X",bytearray[k-1]); } } Use this int converttohex(char * val) { unsigned char temp = toupper(*val); unsigned char fin=0; if(temp>64) temp=10+(temp-65); else temp=temp-48; fin=(temp<<4)&0xf0; temp = toupper(*(val+1)); if(temp>64) temp=10+(temp-65); else temp=temp-48; fin=fin|(temp & 0x0f); return fin; } 

试试下面的代码:

 static unsigned char ascii2byte(char *val) { unsigned char temp = *val; if(temp > 0x60) temp -= 39; // convert chars af temp -= 48; // convert chars 0-9 temp *= 16; temp += *(val+1); if(*(val+1) > 0x60) temp -= 39; // convert chars af temp -= 48; // convert chars 0-9 return temp; } 

这是一个类似问题的修改函数,根据https://stackoverflow.com/a/18267932/700597的build议进行修改。;

这个函数会将一个hex的string(不是前缀为“0x”)转换为偶数个字符到指定的字节数。 如果遇到无效字符,或者hexstring的长度为奇数,则返回-1,成功则返回0。

 //convert hexstring to len bytes of data //returns 0 on success, -1 on error //data is a buffer of at least len bytes //hexstring is upper or lower case hexadecimal, NOT prepended with "0x" int hex2data(unsigned char *data, const unsigned char *hexstring, unsigned int len) { unsigned const char *pos = hexstring; char *endptr; size_t count = 0; if ((hexstring[0] == '\0') || (strlen(hexstring) % 2)) { //hexstring contains no data //or hexstring has an odd length return -1; } for(count = 0; count < len; count++) { char buf[5] = {'0', 'x', pos[0], pos[1], 0}; data[count] = strtol(buf, &endptr, 0); pos += 2 * sizeof(char); if (endptr[0] != '\0') { //non-hexadecimal character encountered return -1; } } return 0; } 

这是我的版本:

 /* Convert a hex char digit to its integer value. */ int hexDigitToInt(char digit) { digit = tolower(digit); if ('0' <= digit && digit <= '9') //if it's decimal return (int)(digit - '0'); else if ('a' <= digit && digit <= 'f') //if it's abcdef return (int)(digit - ('a' - 10)); else return -1; //value not in [0-9][af] range } /* Decode a hex string. */ char *decodeHexString(const char *hexStr) { char* decoded = malloc(strlen(hexStr)/2+1); char* hexStrPtr = (char *)hexStr; char* decodedPtr = decoded; while (*hexStrPtr != '\0') { /* Step through hexStr, two chars at a time. */ *decodedPtr = 16 * hexDigitToInt(*hexStrPtr) + hexDigitToInt(*(hexStrPtr+1)); hexStrPtr += 2; decodedPtr++; } *decodedPtr = '\0'; /* final null char */ return decoded; } 

这里是HexToBin和BinToHex比较干净和可读。 (注意,最初通过错误日志logging系统返回枚举错误代码不是简单的-1或-2。)

 typedef unsigned char ByteData; ByteData HexChar (char c) { if ('0' <= c && c <= '9') return (ByteData)(c - '0'); if ('A' <= c && c <= 'F') return (ByteData)(c - 'A' + 10); if ('a' <= c && c <= 'f') return (ByteData)(c - 'a' + 10); return (ByteData)(-1); } ssize_t HexToBin (const char* s, ByteData * buff, ssize_t length) { ssize_t result = 0; if (!s || !buff || length <= 0) return -2; while (*s) { ByteData nib1 = HexChar(*s++); if ((signed)nib1 < 0) return -3; ByteData nib2 = HexChar(*s++); if ((signed)nib2 < 0) return -4; ByteData bin = (nib1 << 4) + nib2; if (length-- <= 0) return -5; *buff++ = bin; ++result; } return result; } void BinToHex (const ByteData * buff, ssize_t length, char * output, ssize_t outLength) { char binHex[] = "0123456789ABCDEF"; if (!output || outLength < 4) return (void)(-6); *output = '\0'; if (!buff || length <= 0 || outLength <= 2 * length) { memcpy(output, "ERR", 4); return (void)(-7); } for (; length > 0; --length, outLength -= 2) { ByteData byte = *buff++; *output++ = binHex[(byte >> 4) & 0x0F]; *output++ = binHex[byte & 0x0F]; } if (outLength-- <= 0) return (void)(-8); *output++ = '\0'; } 

hextools.h

 #ifndef HEX_TOOLS_H #define HEX_TOOLS_H char *bin2hex(unsigned char*, int); unsigned char *hex2bin(const char*); #endif // HEX_TOOLS_H 

hextools.c

 #include <stdlib.h> char *bin2hex(unsigned char *p, int len) { char *hex = malloc(((2*len) + 1)); char *r = hex; while(len && p) { (*r) = ((*p) & 0xF0) >> 4; (*r) = ((*r) <= 9 ? '0' + (*r) : 'A' - 10 + (*r)); r++; (*r) = ((*p) & 0x0F); (*r) = ((*r) <= 9 ? '0' + (*r) : 'A' - 10 + (*r)); r++; p++; len--; } *r = '\0'; return hex; } unsigned char *hex2bin(const char *str) { int len, h; unsigned char *result, *err, *p, c; err = malloc(1); *err = 0; if (!str) return err; if (!*str) return err; len = 0; p = (unsigned char*) str; while (*p++) len++; result = malloc((len/2)+1); h = !(len%2) * 4; p = result; *p = 0; c = *str; while(c) { if(('0' <= c) && (c <= '9')) *p += (c - '0') << h; else if(('A' <= c) && (c <= 'F')) *p += (c - 'A' + 10) << h; else if(('a' <= c) && (c <= 'f')) *p += (c - 'a' + 10) << h; else return err; str++; c = *str; if (h) h = 0; else { h = 4; p++; *p = 0; } } return result; } 

main.c中

 #include <stdio.h> #include "hextools.h" int main(void) { unsigned char s[] = { 0xa0, 0xf9, 0xc3, 0xde, 0x44 }; char *hex = bin2hex(s, sizeof s); puts(hex); unsigned char *bin; bin = hex2bin(hex); puts(bin2hex(bin, 5)); size_t k; for(k=0; k<5; k++) printf("%02X", bin[k]); putchar('\n'); return 0; }