'Convert Base 16 (Hexadecimal) to Base 36 String in C
In C, what's an efficient way to convert a 64 character hexadecimal number (as a string) into a base 36 string?
I mean, is it as easy as combining a few GLIB2 functions (on Linux), or Standard Library functions? Or, do I have to do it all custom?
Solution 1:[1]
This is easy with a library like GMP:
mpz_t nr;
mpz_init(nr);
mpz_set_str(nr, hexstr, 16);
printf("%s\n", mpz_get_str(NULL, 36, nr));
On debian-based systems you can install the GMP-library with:
apt-get install libgmp-dev
Full example:
#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;
}
Compiled with:
gcc -O2 conv.c -o conv -lgmp
Performs quite well:
$ time ./conv 2eb1a3e346933962bdfbb7b118404b68b967d44006986d4b1e88ec23e433de12
15wa17qx942cddy4n5q5px1fw6yi9llw0lzxjg2ahh2q0w9amq
real    0m0.001s
user    0m0.000s
sys     0m0.000s
    					Solution 2:[2]
Convert Base 16 (Hexadecimal) to Base 36 String
Easy to do using a few standard C functions.
Form a "string times" function.
#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);
}
Sample usage
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;
}
Output
1
10
73
1Z141Z3
6DP5QCB22IM238NR3WVP0IC7Q99W035JMY2IW7I6N43D37JTOF
    					Solution 3:[3]
That 64-character hex requirement is a killer, that's a 256-bit integer which is larger than any native C integer type can handle.
Since converting to base-36 involves computing the modulo of the number and 36, I think you're going to need a bignum library (such as GNU MP) to do this.
Once you have that, implementing the algorithm to emit base-36 (from e.g. Wikipedia) should be trivial.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source | 
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | 
