有没有标准的C函数可以将十六进制字符串转换为字节数组?
我不想自己编写函数。
char *hexstring = "deadbeef10203040b00b1e50", *pos = hexstring;
unsigned char val[12];
while( *pos )
{
if( !((pos-hexstring)&1) )
sscanf(pos,"%02x",&val[(pos-hexstring)>>1]);
++pos;
}
sizeof(val)/sizeof(val[0])是多余的!
unsigned char val[12];...sscanf(pos,"%02x",&val[...]);
是错误的,因为它试图将一个 unsigned
存储到一个 unsigned char
中。 - chux - Reinstate Monica这是从一个类似的问题修改的函数,根据https://dev59.com/M3XYa4cB1Zd3GeqP98AA#18267932的建议进行了修改。
此函数将把具有偶数个字符的十六进制字符串(不带前缀“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;
}
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;
}
使用strchr()解析字节或字的两个简短例程。
// HexConverter.h
#ifndef HEXCONVERTER_H
#define HEXCONVERTER_H
unsigned int hexToByte (const char *hexString);
unsigned int hexToWord (const char *hexString);
#endif
// HexConverter.c
#include <string.h> // for strchr()
#include <ctype.h> // for toupper()
unsigned int hexToByte (const char *hexString)
{
unsigned int value;
const char *hexDigits = "0123456789ABCDEF";
value = 0;
if (hexString != NULL)
{
char *ptr;
ptr = strchr (hexDigits, toupper(hexString[0]));
if (ptr != NULL)
{
value = (ptr - hexDigits) << 4;
ptr = strchr (hexDigits, toupper(hexString[1]));
if (ptr != NULL)
{
value = value | (ptr - hexDigits);
}
}
}
return value;
}
unsigned int hexToWord (const char *hexString)
{
unsigned int value;
value = 0;
if (hexString != NULL)
{
value = (hexToByte (&hexString[0]) << 8) |
(hexToByte (&hexString[2]));
}
return value;
}
// HexConverterTest.c
#include <stdio.h>
#include "HexConverter.h"
int main (int argc, char **argv)
{
(void)argc; // not used
(void)argv; // not used
unsigned int value;
char *hexString;
hexString = "2a";
value = hexToByte (hexString);
printf ("%s == %x (%u)\n", hexString, value, value);
hexString = "1234";
value = hexToWord (hexString);
printf ("%s == %x (%u)\n", hexString, value, value);
hexString = "0102030405060708090a10ff";
printf ("Hex String: %s\n", hexString);
for (unsigned int idx = 0; idx < strlen(hexString); idx += 2)
{
value = hexToByte (&hexString[idx]);
printf ("%c%c == %x (%u)\n", hexString[idx], hexString[idx+1],
value, value);
}
return EXIT_SUCCESS;
}
它可能更简单吗?!
uint8_t hex(char ch) {
uint8_t r = (ch > 57) ? (ch - 55) : (ch - 48);
return r & 0x0F;
}
int to_byte_array(const char *in, size_t in_size, uint8_t *out) {
int count = 0;
if (in_size % 2) {
while (*in && out) {
*out = hex(*in++);
if (!*in)
return count;
*out = (*out << 4) | hex(*in++);
*out++;
count++;
}
return count;
} else {
while (*in && out) {
*out++ = (hex(*in++) << 4) | hex(*in++);
count++;
}
return count;
}
}
int main() {
char hex_in[] = "deadbeef10203040b00b1e50";
uint8_t out[32];
int res = to_byte_array(hex_in, sizeof(hex_in) - 1, out);
for (size_t i = 0; i < res; i++)
printf("%02x ", out[i]);
printf("\n");
system("pause");
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][a-f] 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;
}
*(decodedPtr+1) = '\0'
中出现了一个美丽的“越界一个”的错误(因为在上次写入后decodedPtr
已经被增加了)。 - rlubastatic unsigned char ascii2byte(char *val)
{
unsigned char temp = *val;
if(temp > 0x60) temp -= 39; // convert chars a-f
temp -= 48; // convert chars 0-9
temp *= 16;
temp += *(val+1);
if(*(val+1) > 0x60) temp -= 39; // convert chars a-f
temp -= 48; // convert chars 0-9
return temp;
}
对于新手和为了改进@Michael的答案,这里提供完整版本:
// out needs to be at least len/2+1 bytes long
// length will be returned
int hexStrToBin(char* out, const char *str)
{
int i, len = strlen(str);
for (i = 0; i < len; i++)
{
// Reads str & stores in op
sscanf(str, "%2hhx", &op[i]);
str += 2;
}
return len/2;
}
op
)的引用,可能导致未定义的行为。 - Thom Wiggersop
在栈上分配,当 hexStrToBin
返回后就会停止存在。虽然这个答案是关于 C++ 的,但在这里同样适用 https://dev59.com/Rm445IYBdhLWcg3w6eNo#30864512。 - Thom Wiggers&op[i]
改为&out[i]
。根据我现在的阅读,op
未定义。 - Andrew Falanga/**
* @brief Convert a hex string to a byte array
* @param hex pointer to the hex string to convert
* @param output Array to place the results, should be half the size of the input array
* @param array_length Number of bytes to output
*/
void hex_to_bytes(char *hex, uint8_t *output, uint8_t array_length)
{
for (int i = 0, j = 0; i < array_length; i++, j += 2)
{
hex[j] = toupper(hex[j]);
hex[j+1] = toupper(hex[j+1]);
uint8_t bottom = hex[j + 1] - (hex[j + 1] > '9' ? 'A' - 10 : '0');
uint8_t top = hex[j] - (hex[j] > '9' ? 'A' - 10 : '0');
output[i] = (top * 16) + bottom;
}
}
不是。但是使用循环中的sscanf
相对容易实现。