Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何将十六进制字符串转换为无符号字符数组?_C_Arrays_Hex - Fatal编程技术网

C 如何将十六进制字符串转换为无符号字符数组?

C 如何将十六进制字符串转换为无符号字符数组?,c,arrays,hex,C,Arrays,Hex,例如,我有一个cstring“E8 48 D8 FF 8B 0D”(包括空格),它需要转换为等效的无符号字符数组{0xE8,0x48,0xD8,0xFF,0xFF,0x8B,0x0D}。做这件事的有效方法是什么?谢谢 编辑:我不能使用std库。。。所以考虑这个问题。对不起 < P> 这回答了原来的问题,它要求C++解决方案。 < /P> 您可以将istringstream与hex操纵器一起使用: std::string hex_chars("E8 48 D8 FF FF 8B 0D"); st

例如,我有一个cstring
“E8 48 D8 FF 8B 0D”
(包括空格),它需要转换为等效的无符号字符数组
{0xE8,0x48,0xD8,0xFF,0xFF,0x8B,0x0D}
。做这件事的有效方法是什么?谢谢

编辑:我不能使用std库。。。所以考虑这个问题。对不起

< P> <强>这回答了原来的问题,它要求C++解决方案。<强> < /P> 您可以将
istringstream
hex
操纵器一起使用:

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);
}
std::字符串十六进制字符(“E8 48 D8 FF 8B 0D”);
std::istringstream十六进制字符流(十六进制字符);
std::向量字节;
无符号整数c;
while(十六进制字符流>>标准::十六进制>>c)
{
字节。推回(c);
}
请注意,
c
必须是
int
(或
long
,或其他一些整数类型),而不是
char
;如果是
字符
(或
无符号字符
),将调用错误的
>
重载,并从字符串中提取单个字符,而不是十六进制整数字符串

额外的错误检查以确保提取的值符合
字符
将是一个好主意。

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

旧的C方式,手工操作;-)(有很多较短的方法,但我不是打高尔夫球,我是跑步)

enum{NBBYTES=7};
char res[NBBYTES+1];
const char*c=“E8 48 D8 FF 8B 0D”;
常数char*p=c;
int i=0;
对于(i=0;i
现在,另一个允许数字之间任意数量的数字,任意数量的空格分隔它们,包括前导空格或尾随空格(Ben的规范):

#包括
#包括
int main(){
枚举{NBBYTES=7};
char res[NBBYTES];
const char*c=“E8 48 D8 FF 8B 0D”;
常数char*p=c;
int i=-1;
res[i]=0;
char ch=“”;
while(ch&&i

不,它不是很模糊。。。但是,看起来确实如此。

对于纯C实现,我认为您可以说服sscanf(3)
做您想做的事情。我认为只要输入字符串只包含两个字符的十六进制值,这应该是可移植的(包括稍微狡猾的类型强制以安抚编译器)

#include <stdio.h>
#include <stdlib.h>


char hex[] = "E8 48 D8 FF FF 8B 0D";
char *p;
int cnt = (strlen(hex) + 1) / 3; // Whether or not there's a trailing space
unsigned char *result = (unsigned char *)malloc(cnt), *r;
unsigned char c;

for (p = hex, r = result; *p; p += 3) {
    if (sscanf(p, "%02X", (unsigned int *)&c) != 1) {
        break; // Didn't parse as expected
    }
    *r++ = c;
}
#包括
#包括
字符十六进制[]=“E8 48 D8 FF 8B 0D”;
char*p;
int cnt=(strlen(十六进制)+1)/3;//是否有尾随空格
无符号字符*结果=(无符号字符*)malloc(cnt),*r;
无符号字符c;
对于(p=hex,r=result;*p;p+=3){
如果(sscanf(p、%02X),(无符号整数*)&c)!=1){
break;//未按预期进行分析
}
*r++=c;
}

您永远不会让我相信此操作是性能瓶颈。 有效的方法是通过使用标准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;
}

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

如果您事先知道要分析的字符串的长度(例如,您正在从/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]);
}
使用“old”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;
字符串s_hex=“E8 48 D8 FF 8B 0D”//源字符串 char*a_char=新字符(s_hex.length()/3+1);//输出字符数组 for(无符号i=0,uchr;i
+1:这可能是最直接、最简单的方法。基本上我就是这么做的,除了使用开关而不是三元测试。取决于编译器和处理器架构
// 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]);
}
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
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;