代码之家  ›  专栏  ›  技术社区  ›  Volomike nbk

用C语言将16进制(十六进制)转换为36进制字符串

  •  3
  • Volomike nbk  · 技术社区  · 10 年前

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

    我的意思是,结合几个GLIB2函数(在Linux上)或标准库函数那么简单吗?或者,我必须按惯例做吗?

    3 回复  |  直到 10 年前
        1
  •  5
  •   chux    4 年前

    将16进制(十六进制)转换为36进制字符串

    使用几个标准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
    
        2
  •  3
  •   unwind    10 年前

    64个字符的十六进制要求是一个杀手锏,它是一个256位整数,比任何原生C整数类型都能处理。

    由于转换为36进制涉及到计算数字和36的模,我认为您需要一个bignum库(例如 GNU MP )要做到这一点。

    一旦你有了它,实现算法来发出base-36(例如。 Wikipedia )应该是微不足道的。

        3
  •  2
  •   Ctx    10 年前

    使用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
    
    推荐文章