如何在C中正确地将十六进制字符串转换为字节数组?
我需要将包含十六进制值作为字符的字符串转换为字节数组。虽然这是第一个答案,但我得到以下错误:如何在C中正确地将十六进制字符串转换为字节数组?,c,arrays,type-conversion,C,Arrays,Type Conversion,我需要将包含十六进制值作为字符的字符串转换为字节数组。虽然这是第一个答案,但我得到以下错误: warning: ISO C90 does not support the ‘hh’ gnu_scanf length modifier [-Wformat] 因为我不喜欢警告,省略hh只会产生另一个警告 warning: format ‘%x’ expects argument of type ‘unsigned int *’, but argument 3 has type ‘unsigned c
warning: ISO C90 does not support the ‘hh’ gnu_scanf length modifier [-Wformat]
因为我不喜欢警告,省略hh
只会产生另一个警告
warning: format ‘%x’ expects argument of type ‘unsigned int *’, but argument 3 has type ‘unsigned char *’ [-Wformat]
我的问题是:如何做到这一点?为了完成,我在这里再次发布示例代码:
#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 * sizeof(char);
}
printf("0x");
for(count = 0; count < sizeof(val)/sizeof(val[0]); count++)
printf("%02x", val[count]);
printf("\n");
return(0);
}
#包括
int main(int argc,字符**argv)
{
常量字符hexstring[]=“deadbeef10203040b00b1e50”,*pos=hexstring;
无符号字符val[12];
大小\u t计数=0;
/*警告:无任何消毒或错误检查*/
对于(count=0;count
您可以改用strtol()
只需替换此行:
sscanf(pos, "%2hhx", &val[count]);
与:
更新:您可以避免使用sprintf()
而改用此代码段:
char buf[5] = {"0", "x", pos[0], pos[1], 0};
val[count] = strtol(buf, NULL, 0);
您可以将编译器切换到C99模式(C99中标准化了
hh
长度修饰符),也可以使用unsigned int
临时变量:
unsigned int byteval;
if (sscanf(pos, "%2x", &byteval) != 1)
{
/* format error */
}
val[count] = byteval;
使用mvp建议的更改,我创建了这个函数,其中包括错误检查(无效字符和长度不均匀) 此函数将具有偶数个字符的十六进制字符串(不带“0x”前缀)转换为指定的字节数。如果遇到无效字符或十六进制字符串的长度为奇数,则返回-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;
}
//将hexstring转换为len字节的数据
//成功时返回0,错误时返回1
//数据是至少包含len字节的缓冲区
//hexstring是大写或小写十六进制,前面没有“0x”
int-hex2data(无符号字符*数据,常量无符号字符*hexstring,无符号整数len)
{
无符号常量char*pos=hexstring;
char*endptr;
大小\u t计数=0;
if((hextstring[0]='\0')| |(strlen(hextstring)%2)){
//hexstring不包含任何数据
//或者字符串的长度为奇数
返回-1;
}
用于(计数=0;计数
为什么不使用sscanf、strol等,下面是HexToBin,作为一种自由蜜蜂,BinToHex。(注意,最初通过错误记录系统返回枚举错误代码,而不是简单的-1返回。)
无符号字符HexChar(字符c)
{
如果(0)考虑,这可能不会帮助额外变量不能解决任何问题。为了避免<代码> SCAFTF 更新的答案,您可以将16作为第三代码的<代码> Stotol < /代码>,而不是前缀<代码>“0x”。
。我使用@Vovanium提到的strtol的base16
解决了这个非常类似的问题,现在我能够摆脱@mvp提到的sprintf
。代码片段如下:chart[5]={fd,sd,0};d[c]=strtol(t,NULL,16);
//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;
}
unsigned char HexChar (char c)
{
if ('0' <= c && c <= '9') return (unsigned char)(c - '0');
if ('A' <= c && c <= 'F') return (unsigned char)(c - 'A' + 10);
if ('a' <= c && c <= 'f') return (unsigned char)(c - 'a' + 10);
return 0xFF;
}
int HexToBin (const char* s, unsigned char * buff, int length)
{
int result;
if (!s || !buff || length <= 0) return -1;
for (result = 0; *s; ++result)
{
unsigned char msn = HexChar(*s++);
if (msn == 0xFF) return -1;
unsigned char lsn = HexChar(*s++);
if (lsn == 0xFF) return -1;
unsigned char bin = (msn << 4) + lsn;
if (length-- <= 0) return -1;
*buff++ = bin;
}
return result;
}
void BinToHex (const unsigned char * buff, int length, char * output, int outLength)
{
char binHex[] = "0123456789ABCDEF";
if (!output || outLength < 4) return;
*output = '\0';
if (!buff || length <= 0 || outLength <= 2 * length)
{
memcpy(output, "ERR", 4);
return;
}
for (; length > 0; --length, outLength -= 2)
{
unsigned char byte = *buff++;
*output++ = binHex[(byte >> 4) & 0x0F];
*output++ = binHex[byte & 0x0F];
}
if (outLength-- <= 0) return;
*output++ = '\0';
}