ページ 11

2・4・8・16・32進数での表示

Posted: 2012年6月19日(火) 23:57
by tutomu
はじめまして、C言語初心者です。
学校の課題なのですが、タイトルの通り2・4・8・16・32進数での表示の問題でつまってしまっています。
どうか力を貸してください。
問題は以下の通りです。

Q10符号なし進数nを各進数に変換して配列sに格納する関数を書け。
  ・ void shinsuu(unsigned n, char s[],int base, int len); を使う
  ・ printf関数%sを使う
  ・ 未使用の桁は’_’で埋める
  ・ printf("%1d",372);のように桁数を超えた時でも値を表示できるようにする

この問いに対して僕が書いたのが以下の通りです。

コード:

 
#include<stdio.h>

void shinsuu(unsigned n, char s[], int base, int len);

main()
{
	unsigned n=0;
	char s[]="_____";
	int base;
	int len;
	int i;
	
	for(base=1,n=0; n<32; ++n,base=1)
	{
		printf("%2d",n);
		while(base<32)
		{
			base=base*2;
			shinsuu(n, s, base, len);
			printf(":(%d)%s",base,s);
			--len;
		}
		
		printf("\n");
	}
}

void shinsuu(unsigned n, char s[], int base, int len)
{
	int i=1;
	
	if(base==2)
	{
		len=5;
		s[len-1]='0';
		while(0!=n)
		{
			if(0==n%base)
			{
				s[len-i]='0';
			}
			else
			{
				s[len-i]='1';
			}
			n=n/base;
			++i;
		}
	}
	else if(base==4)
	{
		len=4;
		s[len-1]='0';
		while(0!=n)
		{
			if(0==n%base)
			{
				s[len-i]='0';
			}
			else if(1==n%base)
			{
				s[len-i]='1';
			}
			else if(2==n%base)
			{
				s[len-i]='2';
			}
			else
			{
				s[len-i]='3';
			}
			n=n/base;
			++i;
		}
	}
	else if(base==8)
	{
		len=3;
		s[len-1]='0';
		while(0!=n)
		{
			if(0==n%base)
			{
				s[len-i]='0';
			}
			else if(1==n%base)
			{
				s[len-i]='1';
			}
			else if(2==n%base)
			{
				s[len-i]='2';
			}
			else if(3==n%base)
			{
				s[len-i]='3';
			}
			else if(4==n%base)
			{
				s[len-i]='4';
			}
			else if(5==n%base)
			{
				s[len-i]='5';
			}
			else if(6==n%base)
			{
				s[len-i]='6';
			}
			else
			{
				s[len-i]='7';
			}
			n=n/base;
			++i;
		}
	}
	else if(base==16)
	{
		len=2;
		s[len-1]='0';
		while(0!=n)
		{
			if(0==n%base)
			{
				s[len-i]='0';
			}
			else if(1==n%base)
			{
				s[len-i]='1';
			}
			else if(2==n%base)
			{
				s[len-i]='2';
			}
			else if(3==n%base)
			{
				s[len-i]='3';
			}
			else if(4==n%base)
			{
				s[len-i]='4';
			}
			else if(5==n%base)
			{
				s[len-i]='5';
			}
			else if(6==n%base)
			{
				s[len-i]='6';
			}
			else if(7==n%base)
			{
				s[len-i]='7';
			}
			else if(8==n%base)
			{
				s[len-i]='8';
			}
			else if(9==n%base)
			{
				s[len-i]='9';
			}
			else if(10==n%base)
			{
				s[len-i]='a';
			}
			else if(11==n%base)
			{
				s[len-i]='b';
			}
			else if(12==n%base)
			{
				s[len-i]='c';
			}
			else if(13==n%base)
			{
				s[len-i]='d';
			}
			else if(14==n%base)
			{
				s[len-i]='e';
			}
			else
			{
				s[len-i]='f';
			}
			n=n/base;
			++i;
		}
	}
	else
	{
		len=1;
		s[len-1]='0';
		while(0!=n)
		{
			if(0==n%base)
			{
				s[len-i]='0';
			}
			else if(1==n%base)
			{
				s[len-i]='1';
			}
			else if(2==n%base)
			{
				s[len-i]='2';
			}
			else if(3==n%base)
			{
				s[len-i]='3';
			}
			else if(4==n%base)
			{
				s[len-i]='4';
			}
			else if(5==n%base)
			{
				s[len-i]='5';
			}
			else if(6==n%base)
			{
				s[len-i]='6';
			}
			else if(7==n%base)
			{
				s[len-i]='7';
			}
			else if(8==n%base)
			{
				s[len-i]='8';
			}
			else if(9==n%base)
			{
				s[len-i]='9';
			}
			else if(10==n%base)
			{
				s[len-i]='a';
			}
			else if(11==n%base)
			{
				s[len-i]='b';
			}
			else if(12==n%base)
			{
				s[len-i]='c';
			}
			else if(13==n%base)
			{
				s[len-i]='d';
			}
			else if(14==n%base)
			{
				s[len-i]='e';
			}
			else if(15==n%base)
			{
				s[len-i]='f';
			}
			else if(16==n%base)
			{
				s[len-i]='g';
			}
			else if(17==n%base)
			{
				s[len-i]='h';
			}
			else if(18==n%base)
			{
				s[len-i]='i';
			}
			else if(19==n%base)
			{
				s[len-i]='j';
			}
			else if(20==n%base)
			{
				s[len-i]='k';
			}
			else if(21==n%base)
			{
				s[len-i]='l';
			}
			else if(22==n%base)
			{
				s[len-i]='m';
			}
			else if(23==n%base)
			{
				s[len-i]='n';
			}
			else if(24==n%base)
			{
				s[len-i]='o';
			}
			else if(25==n%base)
			{
				s[len-i]='p';
			}
			else if(26==n%base)
			{
				s[len-i]='q';
			}
			else if(27==n%base)
			{
				s[len-i]='r';
			}
			else if(28==n%base)
			{
				s[len-i]='s';
			}
			else if(29==n%base)
			{
				s[len-i]='t';
			}
			else if(30==n%base)
			{
				s[len-i]='u';
			}
			else
			{
				s[len-i]='v';
			}
			n=n/base;
			++i;
		}
	}
	while(0!=s[len-i])
	{
		s[len-i]='_';
		++i;
	}
	s[len]='\0';
}
しかしこれで実行すると、
0:(2)_____:(4)____:(8)___:(16)__:(32)_
1:(2)_:(4)_:(8)_:(16)_1:(32)1
2:(2)1:(4)1:(8)1:(16)_2:(32)2
3:(2)2:(4)2:(8)2:(16)_3:(32)3
4:(2)3:(4)3:(8)3:(16)_4:(32)4
5:(2)4:(4)4:(8)4:(16)_5:(32)5
6:(2)5:(4)5:(8)5:(16)_6:(32)6
7:(2)6:(4)6:(8)6:(16)_7:(32)7
8:(2)_1000:(4)__20:(8)_10:(16)_8:(32)8
9:(2)_1001:(4)__21:(8)_11:(16)_9:(32)9
10:(2)_1010:(4)__22:(8)_12:(16)_a:(32)a
11:(2)_1011:(4)__23:(8)_13:(16)_b:(32)b
12:(2)_1100:(4)__30:(8)_14:(16)_c:(32)c
13:(2)_1101:(4)__31:(8)_15:(16)_d:(32)d
14:(2)_1110:(4)__32:(8)_16:(16)_e:(32)e
15:(2)_1111:(4)__33:(8)_17:(16)_f:(32)f
16:(2)10000:(4)_100:(8)_20:(16)10:(32)g
17:(2)10001:(4)_101:(8)_21:(16)11:(32)h
18:(2)10010:(4)_102:(8)_22:(16)12:(32)i
19:(2)10011:(4)_103:(8)_23:(16)13:(32)j
20:(2)10100:(4)_110:(8)_24:(16)14:(32)k
21:(2)10101:(4)_111:(8)_25:(16)15:(32)l
22:(2)10110:(4)_112:(8)_26:(16)16:(32)m
23:(2)10111:(4)_113:(8)_27:(16)17:(32)n
24:(2)11000:(4)_120:(8)_30:(16)18:(32)o
25:(2)11001:(4)_121:(8)_31:(16)19:(32)p
26:(2)11010:(4)_122:(8)_32:(16)1a:(32)q
27:(2)11011:(4)_123:(8)_33:(16)1b:(32)r
28:(2)11100:(4)_130:(8)_34:(16)1c:(32)s
29:(2)11101:(4)_131:(8)_35:(16)1d:(32)t
30:(2)11110:(4)_132:(8)_36:(16)1e:(32)u
31:(2)11111:(4)_133:(8)_37:(16)1f:(32)v

となってしまいます。
本当なら
0:(2)____0:(4)___0:(8)__0:(16)_0:(32)0
1:(2)____1:(4)___1:(8)__1:(16)_1:(32)1
2:(2)___10:(4)___2:(8)__2:(16)_2:(32)2
3:(2)___11:(4)___3:(8)__3:(16)_3:(32)3
4:(2)__100:(4)__10:(8)__4:(16)_4:(32)4
5:(2)__101:(4)__11:(8)__5:(16)_5:(32)5
6:(2)__110:(4)__12:(8)__6:(16)_6:(32)6
7:(2)__111:(4)__13:(8)__7:(16)_7:(32)7
8:(2)_1000:(4)__20:(8)_10:(16)_8:(32)8
9:(2)_1001:(4)__21:(8)_11:(16)_9:(32)9
10:(2)_1010:(4)__22:(8)_12:(16)_a:(32)a
11:(2)_1011:(4)__23:(8)_13:(16)_b:(32)b
12:(2)_1100:(4)__30:(8)_14:(16)_c:(32)c
13:(2)_1101:(4)__31:(8)_15:(16)_d:(32)d
14:(2)_1110:(4)__32:(8)_16:(16)_e:(32)e
15:(2)_1111:(4)__33:(8)_17:(16)_f:(32)f
16:(2)10000:(4)_100:(8)_20:(16)10:(32)g
17:(2)10001:(4)_101:(8)_21:(16)11:(32)h
18:(2)10010:(4)_102:(8)_22:(16)12:(32)i
19:(2)10011:(4)_103:(8)_23:(16)13:(32)j
20:(2)10100:(4)_110:(8)_24:(16)14:(32)k
21:(2)10101:(4)_111:(8)_25:(16)15:(32)l
22:(2)10110:(4)_112:(8)_26:(16)16:(32)m
23:(2)10111:(4)_113:(8)_27:(16)17:(32)n
24:(2)11000:(4)_120:(8)_30:(16)18:(32)o
25:(2)11001:(4)_121:(8)_31:(16)19:(32)p
26:(2)11010:(4)_122:(8)_32:(16)1a:(32)q
27:(2)11011:(4)_123:(8)_33:(16)1b:(32)r
28:(2)11100:(4)_130:(8)_34:(16)1c:(32)s
29:(2)11101:(4)_131:(8)_35:(16)1d:(32)t
30:(2)11110:(4)_132:(8)_36:(16)1e:(32)u
31:(2)11111:(4)_133:(8)_37:(16)1f:(32)v
32:(2)100000:(4)_200(8)_40:(16)20:(32)10
となるはずです。

教えていただきたいことは3つあります
1.もっとスマートにコード書くことができないか。
2.n=1からn=7まではどうしてずれてしまうのか。
3.n=32に対応するにはどうすればいいか。
です。

やけに長くなってしまい申し訳ございません・・・
初めての投稿ということもあり至らぬ点も多々あると思いますがよろしくお願いします。

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 00:11
by h2so5
例えば、このコードは

コード:

            if(0==n%base)
            {
                s[len-i]='0';
            }
            else if(1==n%base)
            {
                s[len-i]='1';
            }
            else if(2==n%base)
            {
                s[len-i]='2';
            }
            else if(3==n%base)
            {
                s[len-i]='3';
            }
            else if(4==n%base)
            {
                s[len-i]='4';
            }
            else if(5==n%base)
            {
                s[len-i]='5';
            }
            else if(6==n%base)
            {
                s[len-i]='6';
            }
            else
            {
                s[len-i]='7';
            }
こう書き換えられます。

コード:

char table[] = {'0', '1', '2', '3', '4', '5', '6', '7'};
s[len-i] = table[n%base];

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 02:42
by かずま
スマートかどうか分かりませんが、

コード:

#include <stdio.h>
 
void shinsuu(unsigned n, char s[], int base, int len)
{
    char b[255];  int i = 0, j = 0;

    do b[i++] = "0123456789abcdefghijklmnopqrstuv"[n % base]; while (n /= base);
    while (i < len) b[i++] = '_';
    do s[j++] = b[--i]; while (i);    
    s[j] = 0;
}

int main(void)
{
    unsigned int n;  char s[256];  int base, len;
    
    for (n = 0; n <= 32; n++) {
        printf("%2d", n);
        for (base = 2, len = 5; base <= 32; base <<= 1, len--) {
            shinsuu(n, s, base, len);
            printf(":(%d)%s", base, s);
        }
        printf("\n");
    }
    return 0;
}

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 09:56
by non
>2.n=1からn=7まではどうしてずれてしまうのか。

lenの初期値が入っていないこと、s[]に代入した'\0'が2回目以降のループに悪影響を及ぼしていること。

とりあえず、うまく動かすために次のように訂正してみてください。
16行目の後に
len=5;
strcpy(s,"_____");
の2行を挿入。#include<string.h>はもちろん必要です。
331行から335行を削除。

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 10:13
by tutomu
みなさん素早い回答ありがとうございます!!
さっそく書き直して無事動かすことができました。

しかし、かずまさんの以下の部分がわかりません・・・

コード:

do b[i++] = "0123456789abcdefghijklmnopqrstuv"[n % base]; while (n /= base);
ここはどういったものなのかを教えてください・・・よろしくおねがいします。

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 13:16
by softya(ソフト屋)
tutomu さんが書きました:みなさん素早い回答ありがとうございます!!
さっそく書き直して無事動かすことができました。

しかし、かずまさんの以下の部分がわかりません・・・

コード:

do b[i++] = "0123456789abcdefghijklmnopqrstuv"[n % base]; while (n /= base);
ここはどういったものなのかを教えてください・・・よろしくおねがいします。
全部分からないと言うことはないでしょう。何処の部分がわかりませんか?
まぁ、 "0123456789abcdefghijklmnopqrstuv"[]は余り見ない書き方だと思いますけど。

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 15:21
by tutomu
すみません

コード:

do b[i++] = "0123456789abcdefghijklmnopqrstuv"[n % base];  
の部分が分かりませんです・・・。

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 15:25
by softya(ソフト屋)
分解して考えましょう。
1)do
2)b[i++] =
3)"0123456789abcdefghijklmnopqrstuv"[]
4)n % base
の中でわからない部分は何処ですか?

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 15:30
by tutomu
"0123456789abcdefghijklmnopqrstuv"[]
の部分です・・・

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 15:35
by softya(ソフト屋)
文字列は文字の配列ですから、

コード:

(1) "ABC"
(2) char str[]="ABC";のstr
(3) char str[]={'A','B','C','\0'}; のstr
は全て同等だと説明すれば分かりますでしょうか?

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 15:48
by tutomu
つまりb[i++]="0123456789abcdefghijklmnopqrstuv"[n%base];は
"01234…stuv"の n%base番目の文字をb[i++]に代入・・・という意味で大丈夫でしょうか?

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 15:50
by softya(ソフト屋)
そういう事です。
文字列の中のn%base番目の一文字だけを取り出します。

Re: 2・4・8・16・32進数での表示

Posted: 2012年6月20日(水) 15:54
by tutomu
ありがとうございます!!
おかげさまで疑問がすっきり解決しました!!

またどうしてもわからないことがあったらよろしくお願いします。