如何将十六进制字符串转换为unsigned char数组?

Gbp*_*bps 12 c arrays hex

例如,我有一个cstring "E8 48 D8 FF FF 8B 0D"(包括空格)需要转换为等效的unsigned char数组{0xE8,0x48,0xD8,0xFF,0xFF,0x8B,0x0D}.有效的方法是什么?谢谢!

编辑:我不能使用标准库...所以考虑这个C问题.对不起!

Jam*_*lis 30

这回答了原始问题,该问题要求C++解决方案.

您可以使用istringstreamhex机械手:

std::string hex_chars("E8 48 D8 FF FF 8B 0D");

std::istringstream hex_chars_stream(hex_chars);
std::vector<unsigned char> bytes;

unsigned int c;
while (hex_chars_stream >> std::hex >> c)
{
    bytes.push_back(c);
}
Run Code Online (Sandbox Code Playgroud)

注意,c必须是int(或long,或其他整数类型),而不是char; 如果它是char(或unsigned char),>>将调用错误的重载并从字符串中提取单个字符,而不是十六进制整数字符串.

额外的错误检查以确保提取的值符合a char是一个好主意.

  • 因为我不能给出两个正确的答案,所以我继续进行投票,因为对于C ++用户而言,这绝对是一个不错的解决方案! (2认同)

Nor*_*sey 11

你永远不会让我相信这个操作是一个性能瓶颈.有效的方法是使用标准C库充分利用您的时间:

static unsigned char gethex(const char *s, char **endptr) {
  assert(s);
  while (isspace(*s)) s++;
  assert(*s);
  return strtoul(s, endptr, 16);
}

unsigned char *convert(const char *s, int *length) {
  unsigned char *answer = malloc((strlen(s) + 1) / 3);
  unsigned char *p;
  for (p = answer; *s; p++)
    *p = gethex(s, (char **)&s);
  *length = p - answer;
  return answer;
}
Run Code Online (Sandbox Code Playgroud)

编译和测试.适用于您的示例.

  • 更简单:`for(i = 0; i <max && isxdigit(*s); i ++)a [i] = strtol(s,&s,16);`重点是,你的`gethex`函数完全是多余的.`strtol`跳过领先的空白本身.如果您想更严格地不接受与模式不匹配的字符串,可以使用sscanf来控制字段宽度并测量匹配长度. (5认同)
  • OTOH,缓冲区溢出"ABCDEF 1 2 3 4 5 6 7 8 9". (3认同)

Ben*_*igt 6

  • 遍历所有角色.
    • 如果您有十六进制数字,则数字为(ch >= 'A')? (ch - 'A' + 10): (ch - '0').
      • 向左移动累加器四位,并在新数字中添加(或OR).
    • 如果有空格,并且前一个字符不是空格,则将当前累加器值附加到数组并将累加器重置为零.


Die*_*lia 5

如果您事先知道要解析的字符串的长度(例如,您正在从 /proc 读取某些内容),则可以使用 sscanf 和 'hh' 类型修饰符,它指定下一个转换是 diouxX 和存储它的指针之一将是有符号字符或无符号字符。

// example: ipv6 address as seen in /proc/net/if_inet6:
char myString[] = "fe80000000000000020c29fffe01bafb";
unsigned char addressBytes[16];
sscanf(myString, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx
%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", &addressBytes[0],
&addressBytes[1], &addressBytes[2], &addressBytes[3], &addressBytes[4], 
&addressBytes[5], &addressBytes[6], &addressBytes[7], &addressBytes[8], 
&addressBytes[9], &addressBytes[10], addressBytes[11],&addressBytes[12],
&addressBytes[13], &addressBytes[14], &addressBytes[15]);

int i;
for (i = 0; i < 16; i++){
    printf("addressBytes[%d] = %02x\n", i, addressBytes[i]);
}
Run Code Online (Sandbox Code Playgroud)

输出:

addressBytes[0] = fe
addressBytes[1] = 80
addressBytes[2] = 00
addressBytes[3] = 00
addressBytes[4] = 00
addressBytes[5] = 00
addressBytes[6] = 00
addressBytes[7] = 00
addressBytes[8] = 02
addressBytes[9] = 0c
addressBytes[10] = 29
addressBytes[11] = ff
addressBytes[12] = fe
addressBytes[13] = 01
addressBytes[14] = ba
addressBytes[15] = fb
Run Code Online (Sandbox Code Playgroud)


小智 5

使用“旧”sscanf() 函数:

string s_hex = "E8 48 D8 FF FF 8B 0D"; // source string
char *a_Char = new char( s_hex.length()/3 +1 ); // output char array

for( unsigned i = 0, uchr ; i < s_hex.length() ; i += 3 ) {
    sscanf( s_hex.c_str()+ i, "%2x", &uchr ); // conversion
    a_Char[i/3] = uchr; // save as char
  }
delete a_Char;
Run Code Online (Sandbox Code Playgroud)