在 C 中将 Base 16(十六进制)转换为 Base 36 字符串
Convert Base 16 (Hexadecimal) to Base 36 String in C
在 C 中,将 64 个字符的十六进制数(作为字符串)转换为 base 36 字符串的有效方法是什么?
我的意思是,它是否像组合几个 GLIB2 函数(在 Linux 上)或标准库函数一样简单?或者,我必须全部定制吗?
64 个字符的十六进制要求是一个杀手,这是一个 256 位整数,比任何本机 C 整数类型可以处理的都大。
由于转换为 base-36 涉及计算数字和 36 的模,我认为您将需要一个 bignum 库(例如 GNU MP)来执行此操作。
一旦你有了它,实现发出 base-36 的算法(来自 Wikipedia)应该是微不足道的。
使用像 GMP 这样的库很容易:
mpz_t nr;
mpz_init(nr);
mpz_set_str(nr, hexstr, 16);
printf("%s\n", mpz_get_str(NULL, 36, nr));
在 debian-based 系统上,您可以安装 GMP-library:
apt-get install libgmp-dev
完整示例:
#include <stdio.h>
#include <gmp.h>
int main(int argc, char **argv) {
mpz_t nr;
mpz_init(nr);
mpz_set_str(nr, argv[1], 16);
printf("%s\n", mpz_get_str(NULL, 36, nr));
return 0;
}
编译:
gcc -O2 conv.c -o conv -lgmp
表现不错:
$ time ./conv 2eb1a3e346933962bdfbb7b118404b68b967d44006986d4b1e88ec23e433de12
15wa17qx942cddy4n5q5px1fw6yi9llw0lzxjg2ahh2q0w9amq
real 0m0.001s
user 0m0.000s
sys 0m0.000s
Convert Base 16 (Hexadecimal) to Base 36 String
使用一些标准 C 函数很容易做到。
形成一个“字符串倍数”函数。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static char *str_times(char *s, int base, int times, int carry) {
size_t len = strlen(s);
for (size_t i = len; i > 0;) {
i--;
// Convert character digit into into value
// |-------------------------------------|
int acc = strtol((char[2] ) { s[i], 0 }, 0, base) * times + carry;
s[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[acc % base];
carry = acc / base;
}
while (carry) {
memmove(&s[1], &s[0], ++len);
s[0] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[carry % base];
carry /= base;
}
return s;
}
char *str_base_convert(char *dest, int base_dest, const char *src, int base_src) {
strcpy(dest, "0");
while (*src) {
str_times(dest, base_dest, base_src, strtol((char [2]) {*src,0}, 0, base_src));
src++;
}
return dest;
}
char *str16_to_str36(char *dest, const char *src) {
return str_base_convert(dest, 36, src, 16);
}
示例用法
int main(void) {
char dest[51]; // Size for 64-digit hexadecimal number in base 36
puts(str16_to_str36(dest, "1"));
puts(str16_to_str36(dest, "24"));
puts(str16_to_str36(dest, "FF"));
puts(str16_to_str36(dest, "FFFFffff"));
puts(str16_to_str36(dest,
"FFFFffffFFFFffffFFFFffffFFFFffffFFFFffffFFFFffffFFFFffffFFFFffff"));
return 0;
}
输出
1
10
73
1Z141Z3
6DP5QCB22IM238NR3WVP0IC7Q99W035JMY2IW7I6N43D37JTOF
在 C 中,将 64 个字符的十六进制数(作为字符串)转换为 base 36 字符串的有效方法是什么?
我的意思是,它是否像组合几个 GLIB2 函数(在 Linux 上)或标准库函数一样简单?或者,我必须全部定制吗?
64 个字符的十六进制要求是一个杀手,这是一个 256 位整数,比任何本机 C 整数类型可以处理的都大。
由于转换为 base-36 涉及计算数字和 36 的模,我认为您将需要一个 bignum 库(例如 GNU MP)来执行此操作。
一旦你有了它,实现发出 base-36 的算法(来自 Wikipedia)应该是微不足道的。
使用像 GMP 这样的库很容易:
mpz_t nr;
mpz_init(nr);
mpz_set_str(nr, hexstr, 16);
printf("%s\n", mpz_get_str(NULL, 36, nr));
在 debian-based 系统上,您可以安装 GMP-library:
apt-get install libgmp-dev
完整示例:
#include <stdio.h>
#include <gmp.h>
int main(int argc, char **argv) {
mpz_t nr;
mpz_init(nr);
mpz_set_str(nr, argv[1], 16);
printf("%s\n", mpz_get_str(NULL, 36, nr));
return 0;
}
编译:
gcc -O2 conv.c -o conv -lgmp
表现不错:
$ time ./conv 2eb1a3e346933962bdfbb7b118404b68b967d44006986d4b1e88ec23e433de12
15wa17qx942cddy4n5q5px1fw6yi9llw0lzxjg2ahh2q0w9amq
real 0m0.001s
user 0m0.000s
sys 0m0.000s
Convert Base 16 (Hexadecimal) to Base 36 String
使用一些标准 C 函数很容易做到。
形成一个“字符串倍数”函数。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static char *str_times(char *s, int base, int times, int carry) {
size_t len = strlen(s);
for (size_t i = len; i > 0;) {
i--;
// Convert character digit into into value
// |-------------------------------------|
int acc = strtol((char[2] ) { s[i], 0 }, 0, base) * times + carry;
s[i] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[acc % base];
carry = acc / base;
}
while (carry) {
memmove(&s[1], &s[0], ++len);
s[0] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[carry % base];
carry /= base;
}
return s;
}
char *str_base_convert(char *dest, int base_dest, const char *src, int base_src) {
strcpy(dest, "0");
while (*src) {
str_times(dest, base_dest, base_src, strtol((char [2]) {*src,0}, 0, base_src));
src++;
}
return dest;
}
char *str16_to_str36(char *dest, const char *src) {
return str_base_convert(dest, 36, src, 16);
}
示例用法
int main(void) {
char dest[51]; // Size for 64-digit hexadecimal number in base 36
puts(str16_to_str36(dest, "1"));
puts(str16_to_str36(dest, "24"));
puts(str16_to_str36(dest, "FF"));
puts(str16_to_str36(dest, "FFFFffff"));
puts(str16_to_str36(dest,
"FFFFffffFFFFffffFFFFffffFFFFffffFFFFffffFFFFffffFFFFffffFFFFffff"));
return 0;
}
输出
1
10
73
1Z141Z3
6DP5QCB22IM238NR3WVP0IC7Q99W035JMY2IW7I6N43D37JTOF