36日目 K&RのExerciseをやってみた

K&Rの1章のエクササイズで、0〜9までの数字をカウントして、その数だけ*を出力せよというやつがあった。
ぱっと思いつかなかったので、「困難は分割せよ」メソッドを発動。
まず、forで*の階段を表示させようと思った。

/*とりあえず何も見ないで*で階段作ってみた*/
#include <stdio.h>

main()
{
    int i,j;

    for (i=0; i<10; i++){        // i回目の試行
        for (j=0; j<i; j++){
            printf("*");
        }
        printf("\n");
    }
    return 0;
}

出力結果
*
**
***
****
*****
******
*******
********
*********
**********

→*が何個あるのかわかりづらい。表示しよう。

/*数字を表示させてみた*/
#include <stdio.h>

main()
{
    int i, j;

    for (i=0; i<10; i++){
        printf("%d\t", i);    // i回目の試行(この行ではiはカウンタ)
        for (j=0; j<i; j++){  // この行ではiは定数、jがカウンタ
            printf("*");
        }
        printf("\n");
    }
    return 0;
}
実行結果
0
1       *
2       **
3       ***
4       ****
5       *****
6       ******
7       *******
8       ********
9       *********

宿題

  • 8行目をの引数をjにしたらうまくいかないのはなぜか簡潔に説明せよ
    • プログラムを読み込んで行数を表示するソースをつくろう
  • いまは関係ないけど変数一個にできないか
  • そもそもforに関係なく変数の値のみに依存して*の数を自由に変えたい
    • for文の中身が不適当
/*配列の中身だけ*を表示*/
#include <stdio.h>

main()
{
	int i,j,wc[10]={0,1,2,3,4,5,6,7,8,9};

	for (i=0; i<10; i++){
		printf("%d\t", i);
		for (j=0; j<wc[i]; j++){
			printf("*");
		}
		printf("\n");
	}
	return 0;
}
出力結果
0
1       *
2       **
3       ***
4       ****
5       *****
6       ******
7       *******
8       ********
9       *********

さっきとおなじになった。よかったよかった。
ちなみにここでwc[i]でなくwc[j]ではうまくいかないのだが、その理由をすぐに説明できないのがくやしい。おちつけ。少し考えればわかるはずだ。

さて問題のexcerciseなわけだが

/*1.6 Arrays*/
#include <stdio.h>

/* count digits, white spaces, others */
main()
{
	int c, i, nwhite, nother;
	int ndigit[10];

	nwhite = nother = 0;
	for (i = 0; i < 10; ++i)
		ndigit[i] = 0;

	while ((c = getchar()) != EOF)
		if (c >= '0' && c <= '9')
			++ndigit[c-'0'];
		else if (c == ' ' || c == '\n' || c == '\t')
			++nwhite;
		else
			++nother;

	printf("digits =");
	for (i = 0; i < 10; ++i)
		printf(" %d",ndigit[i]);
	printf(", white space = %d, other = %d\n", nwhite, nother);
}

OKわかった。最後のforループの中身をいじればよい。
とりあえずもう一個変数がいる。

と、そのまえにこのソースを実行して円周率内の数字の分布を見たい。

実行結果
3.1415926535897932384626433832795028841971693993751058209749445923078164
^Z
digits = 4 6 7 10 8 7 5 6 7 11, white space = 1, other = 1

これを視覚的に表示させる。

#include <stdio.h>

main()
{
	int c, i, j, nwhite, nother;
	int ndigit[10];

	nwhite = nother = 0;
	for (i = 0; i < 10; ++i)
		ndigit[i] = 0;

	while ((c = getchar()) != EOF)
		if (c >= '0' && c <= '9')
			++ndigit[c-'0'];
		else if (c == ' ' || c == '\n' || c == '\t')
			++nwhite;
		else
			++nother;

		printf("digits :\n");
	for (i = 0; i < 10; ++i){
		printf(" %d\t", i);
		for (j=0; j<ndigit[i]; j++){
			printf("*");
		}
		printf("\n");
	}
	printf(" white space = %d, other = %d\n", nwhite, nother);
}
実行結果
3.1415926535897932384626433832795028841971693993751058209749445923078164
^Z
digits :
 0      ****
 1      ******
 2      *******
 3      **********
 4      ********
 5      *******
 6      *****
 7      ******
 8      *******
 9      ***********
 white space = 1, other = 1

できた!
→宿題
「横方向ではなく、縦方向に*を積み上げて表示せよ」
…がんばる。