3

C で、64 文字の 16 進数を (文字列として) 基数 36 の文字列に変換する効率的な方法は何ですか?

つまり、いくつかの GLIB2 関数 (Linux の場合) または標準ライブラリ関数を組み合わせるのと同じくらい簡単ですか? または、すべてのカスタムを行う必要がありますか?

4

3 に答える 3

4

Base 16 (16 進数) を Base 36 文字列に変換する

いくつかの標準 C 関数を使用して簡単に実行できます。
「string times」関数を形成します。

#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 based, const char *src, int bases) {
  strcpy(dest, "0");
  while (*src) {
    str_times(dest, based, bases, strtol((char [2]) {*src,0}, 0, bases));
    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
于 2016-01-15T17:17:01.463 に答える
3

その 64 文字の 16 進要件はキラーです。これは、ネイティブ C 整数型が処理できるよりも大きい 256 ビット整数です。

base-36 への変換には数値と 36 のモジュロの計算が含まれるため、これを行うには bignum ライブラリ ( GNU MPなど) が必要になると思います。

それができたら、base-36 を発行するアルゴリズムを実装することは (たとえばWikipediaから) 簡単なはずです。

于 2016-01-15T10:33:43.610 に答える
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
于 2016-01-15T10:43:29.990 に答える