我需要像这样转换大位字符串:
unsigned char* key = "0111010111010101010101010100101011010";
像这样的十六进制字符串:
unsigned char* string = EBAAAA95A;
问题是我的密钥通常长于 50 或 60 位,当我尝试用
strtoll(key, NULL, 2)
转换它们时,返回的数字远远大于 long long int
甚至可以容纳的数字。有没有一种有效的方法可以直接将其转换为十六进制?
非常感谢您的帮助!
我认为你需要推出自己的实现。这是一个从@mediocrevegetable 获得灵感的实现
#include <stdlib.h>
#include <string.h>
static inline int bitstr_to_int(const char *str, int len)
{
int h = 0;
for (int i = 0; i < len; i++) {
switch (str[i]) {
case '0': h *= 2; continue;
case '1': h *= 2; h++; continue;
default: return -1;
}
}
return h;
}
char * bitstr_to_hexstr(const char *str, int len)
{
static const char hex_digit[] = {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'A', 'B',
'C', 'D', 'E', 'F'
};
int i = 0; //traces the input chars in bitstr
int j = 0; //traces the output chars in hexstr
int h = 0;
int r = len % 4;
int q = len / 4;
char *hexstr = malloc(q + !!r + 1);
if (hexstr == NULL) return NULL;
if (r != 0) {
h = bitstr_to_int(str, r);
if (h == -1) goto err;
hexstr[j++] = hex_digit[h];
}
for (i = r; i < len; i += 4) {
h = bitstr_to_int(str+i, 4);
if (h == -1) goto err;
hexstr[j++] = hex_digit[h];
}
hexstr[j] = '\0';
return hexstr;
err:
free(hexstr);
return NULL;
}
int main(void)
{
const char *key = "0111010111010101010101010100101011010";
char *res = bitstr_to_hexstr(key, strlen(key));
printf("%s\n", res);
}
如果您需要处理大数字,一个好的库(也许是首选库)是 GMP。这是一个简单的示例,演示了您询问的转换:
#include <stdio.h>
#include <gmp.h>
int main()
{
char *instr = "0111010111010101010101010100101011010";
char outstr[100];
mpz_t x;
mpz_init(x);
mpz_set_str(x, instr, 2); /* convert from base 2 */
printf("%s\n", mpz_get_str(outstr, 16, x)); /* convert to base 16 */
}
如果字符串超过 64 位,您可以一次转换一个十六进制数字,确保只有第一个数字使用少于 4 位。
这是一个带有测试用例的实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* convert len bits to a number */
static unsigned bin2hex_val(const char *str, size_t len) {
unsigned v = 0;
while (len --> 0) {
v = v * 2 + (*str++ - '0');
}
return v;
}
char *bin2hex_str(const char *str) {
static const char hex_digits[16] = "0123456789ABCDEF";
size_t len = strspn(str, "01"); /* number of binary digits */
size_t hexlen = (len + 3) / 4; /* number of hex digits */
char *p = malloc(hexlen + 1); /* allocate the hex string */
size_t i = 0;
if (p) {
/* special case the first hex digit if fewer than 4 bits */
if (len % 4) {
p[i++] = hex_digits[bin2hex_val(str, len % 4)];
str += len % 4;
len -= len % 4;
}
/* convert remaining groups of 4 bits as hex digits */
while (len > 0) {
p[i++] = hex_digits[bin2hex_val(str, 4)];
str += 4;
len -= 4;
}
p[i] = '\0';
}
return p;
}
void test(const char *str) {
char *p = bin2hex_str(str);
printf("%s -> %s\n", str, p);
free(p);
}
int main() {
test("");
test("0");
test("1");
test("01");
test("011");
test("0111");
test("01110");
test("011101");
test("0111010");
test("01110101");
test("01110101110101010101010101001010");
test("0111010111010101010101010100101011010011101011101010101010101010");
test("01110101110101010101010101001010110100111010111010101010101010100101011010");
test("ABC");
test("0.0");
test("123");
return 0;
}
输出:
->
0 -> 0
1 -> 1
01 -> 1
011 -> 3
0111 -> 7
01110 -> 0E
011101 -> 1D
0111010 -> 3A
01110101 -> 75
01110101110101010101010101001010 -> 75D5554A
0111010111010101010101010100101011010011101011101010101010101010 -> 75D5554AD3AEAAAA
01110101110101010101010101001010110100111010111010101010101010100101011010 -> 1D755552B4EBAAAA95A
ABC ->
0.0 -> 0
123 -> 1