我正在尝试创建一个ASN.1 BITSTRING
首先,我有一个像"abcd..."
这样的长十六进制字符串,我认为它必须在输出中成为{ 0xab, 0xcd ... }
,但不知道从哪里开始(sscanf()
一次只有2个字符? )。在使用char[]
错误地转换为1010101111001101
后实现了这一点,但这不是二进制输出,它是以字符串形式显示的二进制数字。
How to convert a hexadecimal string to a binary string in C似乎对我不起作用(res数组空出来)。
基于评论(在查看优秀答案之前),我想出了以下内容。在给出答案之前会让其他人发表评论。
char input[] = "abcd";
char output[MAX_LENGTH];
char c[3];
int p = 0;
int b = 0;
while (input[p])
{
strncpy(c, input + p, 2);
c[2] = '\0';
p += 2;
output[ b++ ] = strtol(c, NULL, 16);
}
答案 0 :(得分:1)
如果你需要转换" ab"到0xab你可以简单地写
bool StrToHexDigit (char digit, char *converted)
{
bool retVal = true;
if (digit > '9')
{
if ((digit >= 'a') && (digit < 'g'))
// OR if ((digit > 0x60) && (digit < 'g'))
{
*converted = digit - 'a';
}
if ((digit >= 'A') && (digit < 'G'))
// OR if ((digit > 0x40) && (digit < 'G'))
{
*converted = digit - 'A';
}
*converted += 10;
}
else if (digit > '0')
{
*converted = digit - '0';
}
else
{
retVal = false;
}
return retVal;
}
bool StrToHex8Bit ( char hi, char low, uint8_t *converted)
{
bool retVal=StrToHexDigit(hi, &hi)
if ( retVal == true)
{
retVal=StrToHexDigit(low, &low)
*converted = (hi<<4) | low;
}
return retVal;
}
您可以将StrToHexDigit更快地更改,例如:
if (digit > '9')
{
if ((digit > 0x60) && (digit < 'g'))
{
*converted = digit - 0x57;
}
if ((digit > 0x40) && (digit < 'G'))
{
*converted = digit - 0x37;
}
}
另一种更快的方法,如果你确定你的字符串的数字(以避免检查数字是否可加入),就是使用查找表:
char lookup[255];
void init_lookup ( void )
{
lookup['0'] = 0;
lookup['1'] = 1;
lookup['2'] = 2;
lookup['3'] = 3;
lookup['4'] = 4;
lookup['5'] = 5;
lookup['6'] = 6;
lookup['7'] = 7;
lookup['8'] = 8;
lookup['9'] = 9;
lookup['A'] = 10;
lookup['B'] = 11;
lookup['C'] = 12;
lookup['D'] = 13;
lookup['E'] = 14;
lookup['F'] = 15;
lookup['a'] = 10;
lookup['b'] = 11;
lookup['c'] = 12;
lookup['d'] = 13;
lookup['e'] = 14;
lookup['f'] = 15;
}
uint8_t StrToHex (char hi, char low)
{
return ((lookup[hi]<<4) | lookup[low]);
}
答案 1 :(得分:1)
假设一些任意长度的C字符串,只包含字符0
- 9
和A
- F
(或它们的小写版本),那么这应该是很容易实现:
十六进制中的单个数字是二进制的4位,因此两个数字形成一个字节,因此我们需要length / 2
个字节来存储完整的转换结果:
uint8_t * hexstr_to_bin(char const * str) {
size_t const length = strlen(str);
uint8_t * result = malloc((length + 1) / 2);
// ...
return result;
}
然后,人们可以一次一个地迭代字符,并将其转换为它的二进制表示:
size_t it;
for (it = 0; it < length; ++it) {
char const c = str[it];
uint8_t const bin = (c > '9') ? (tolower(c) - 'a' + 10) : (c - '0');
// ...
}
并将其分配到正确的,可能移位的位置:
if (it % 2 == 0) {
result[it / 2] = bin << 4;
} else {
result[it / 2] |= bin;
}
当然,在结果数组中排序值的可能性很多。以上代码为live here.(虽然未经测试)
答案 2 :(得分:0)
仅供参考,一个简单的实现一次处理一个半字节作为管道过滤器:
#include <stdio.h>
static char nibble[5];
int main()
{
int c, i;
nibble[4] = 0;
while ((c = fgetc(stdin)) != EOF)
{
if (c == '\n') fputc(c, stdout);
if (c < '0' || (c > '9' && c < 'A') || (c > 'F' && c < 'a') || c > 'f')
goto cont;
if (c >= 'a') c -= ('a' - '9' - 1);
else if (c >= 'A') c -= ('A' - '9' - 1);
c -= '0';
for (i = 0; i < 4; ++i)
{
nibble[i] = c & 0x8 ? '1' : '0';
c <<= 1;
}
fputs(nibble, stdout);
cont:;
}
return 0;
}
结果:
> echo "800f024a" | ./hex2bin
10000000000011110000001001001010