HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

「プログラマ脳を鍛える数学パズル」補完計画:進数変換(1)

本業が開店休業状態でリハビリしなきゃなぁということで6年前の本だけど掘り返してみた。

この本の1問目で「C言語には2進表記や8進表記に一発で変換する方法はない」とあったので、リハビリがてら書いてみた。といっても大したものではないけど。

#include <stdio.h>
#include <string.h>

/*
 * 与えられた文字列を逆順にする。
 *
 * str 文字列が格納された配列
 */
void reverse(char* str) {
    for (int i = 0, j = strlen(str) - 1; i < j; ++i, --j) {
        char ch = str[i];
        str[i] = str[j];
        str[j] = ch;
    }
}

/*
 * 与えられた文字セットを使って、整数値の進数変換をして文字列にする。
 *
 * digits 使用する文字セット
 * src 変換元の整数値
 * dest 変換結果を格納する文字配列
 */
void dec(char* digits, int src, char* dest) {
    int base = strlen(digits);

    int i = 0;

    // 下位の桁から順にdestに格納する
    do {
        int r = src % base;
        dest[i++] = digits[r];
        src /= base;
    } while (src > 0);
    dest[i] = '\0';

    // 上位が先頭になるように文字列を逆順にする
    reverse(dest);
}

/*
 * 10進⇒2進変換
 */
void toBin(int src, char* dest) {
    dec("01", src, dest);
}

/*
 * 10進⇒8進変換
 */
void toOct(int src, char* dest) {
    dec("01234567", src, dest);
}

/*
 * 10進⇒16進変換
 */
void toHex(int src, char* dest) {
    dec("0123456789ABCDEF", src, dest);
}

int main(int argc, char** argv) {
    char dBin[128];
    char dOct[128];
    char dHex[128];
    int sample[] = { 0, 1, 2, 5, 8, 123456789, 0x7fffffff };

    for (int i = 0; i < sizeof(sample) / sizeof(int); ++i) {
        toBin(sample[i], dBin);
        toOct(sample[i], dOct);
        toHex(sample[i], dHex);
        fprintf(stdout, "%d\n", sample[i]);
        fprintf(stdout, "  => %s(2)\n", dBin);
        fprintf(stdout, "  => %s(8)\n", dOct);
        fprintf(stdout, "  => %s(16)\n", dHex);
    }
    return 0;
}

実行結果。

0
  => 0(2)
  => 0(8)
  => 0(16)
1
  => 1(2)
  => 1(8)
  => 1(16)
2
  => 10(2)
  => 2(8)
  => 2(16)
5
  => 101(2)
  => 5(8)
  => 5(16)
8
  => 1000(2)
  => 10(8)
  => 8(16)
123456789
  => 111010110111100110100010101(2)
  => 726746425(8)
  => 75BCD15(16)
2147483647
  => 1111111111111111111111111111111(2)
  => 17777777777(8)
  => 7FFFFFFF(16)

ひと仕事おしまい。