C言語のきほん「基数変換」

スポンサーリンク
プログラミング C言語

以前、本ブログで、「基数変換」を取り上げた。↓

割り算を使って、10進数2進数、8進数、16進数変換する方法をご紹介している。

今回は、実際にCのプログラムで基数変換してみよう。

読み込んだ10進数を2進数から36進数に基数変換

//読み込んだ10進数を2進数から36進数に基数変換

#include <stdio.h>

/* type型のxとyの値を交換 */
#define swap(type,x,y) do { type t = x; x = y; y = t;} while (0)

/* 整数値xをn進数に変換した数字文字の並びを配列dに格納 */
int card_conv(unsigned x, int n, char d[])
{
    char dchar[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int digits = 0;

    if (x == 0)                     // 0であれば
        d[digits++] = dchar[0];      //変換後も0
    else
        while(x) {
            d[digits++] = dchar[x % n];   //nで割った剰余を格納 注(1)
            x /= n;                      // 注(2)
        }
    for (int i = 0; i < digits /2; i++)   //配列dの並びを反転 注(3)
        swap(char,d[i],d[digits -i -1]);
    
    return digits;
    
}

int main(void)
{
    puts("10進数を基数変換します");
    int retry;

   do
   {
       unsigned no;         //変換する整数
       int cd;              //基数
       char cno[512];

       printf("変換する非負の整数:");
       scanf("%u",&no);

       do {
           printf("何進数に変換しますか(2-36) :");
           scanf("%d",&cd);

       } while (cd < 2 || cd > 36);   

       int dno = card_conv(no,cd,cno);

       printf("%d進数では",cd);
       for (int i = 0; i < dno; i++)
            printf("%c",cno[i]);
        printf("です\n");

        printf("もう一度しますか(1-yes,0-no) :");
        scanf("%d",&retry);
       
   } while (retry == 1);

   return 0;
   
}

実行結果

$ ./a.out 
10進数を基数変換します
変換する非負の整数:57
何進数に変換しますか(2-36) :2
2進数では111001です
もう一度しますか(1-yes,0-no) :1
変換する非負の整数:57
何進数に変換しますか(2-36) :8
8進数では71です
もう一度しますか(1-yes,0-no) :1
変換する非負の整数:57
何進数に変換しますか(2-36) :16
16進数では39です
もう一度しますか(1-yes,0-no) :0
$

プログラム内 注(1) xをnで割った剰余を添字とする配列dchar内の文字dchar[ x % n ]を配列dの要素d[digits]に代入し、それからdigitsの値をインクリメントする。(後置増分演算子)

注(2) xをnで割る。

剰余で求めた順に格納していくため、配列dの先頭側が下位桁となる。すなわち、変換後の桁の並びは、求めたい数の並びと逆になる。

そこで、注(3) 配列d内のd[0]~d[digits – 1]の部分の反転を行う。

main関数では、基数変換を対話型で行う。

(参考文献)新・明解C言語で学ぶアルゴリズムとデータ構造第2版 柴田望洋著(SBクリエイティブ)

新・明解C言語で学ぶアルゴリズムとデータ構造第2版

コメント

タイトルとURLをコピーしました