在C语言中将十六进制转换为三十六进制字符串

3

在C语言中,将一个64位十六进制数(作为字符串)转换成基于36进制的字符串,有什么高效的方法吗?

我的意思是,是否可以通过组合一些GLIB2函数(在Linux上),或者标准库函数来实现呢?还是必须全部自定义实现?

3个回答

5
将十六进制转换为三十六进制字符串
使用一些标准的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

这只是差两点就完美的作品。(哦...同时也要包含string.h :) ) - David C. Rankin
@David C. Rankin 更改为更通用的进制转换。 - chux - Reinstate Monica
1
@Ctx 同意使用经过充分测试的库。在嵌入式世界中,我的家园,通常需要更小的解决方案。 - chux - Reinstate Monica

3
那个要求64个十六进制字符的限制太严格了,这是一个256位的整数,比任何本地的C整数类型都要大。由于转换为36进制需要计算数字和36的模数,所以我认为您需要一个bignum库(例如GNU MP)来完成此操作。一旦您拥有了它,实现发射基础36的算法(例如Wikipedia)应该很容易。

2

如果使用像GMP这样的库,这将变得非常容易:

mpz_t nr;
mpz_init(nr);
mpz_set_str(nr, hexstr, 16);
printf("%s\n", mpz_get_str(NULL, 36, nr));

在基于Debian的系统上,您可以使用以下命令安装GMP库:

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

我仍在学习C语言。我需要在我的Ubuntu 14.04服务器上安装哪个库?我需要什么include语句?我需要在我的Makefile中添加哪个库或include指令? - Volomike
@Volomike 我添加了一个完整的示例。 - Ctx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接