前回の練習問題の解答例

今回は2つの解答例を示す。 1つ目は繰り返し条件が「sum<=1000000」、2つ目は無限ループである。

繰り返し条件を「sum<=1000000」とする例:
#include <stdio.h>

int main(void)
{
	int month, deposit, sum;
	
	//初月の値
	month=1;
	deposit=1;
  
	sum=0;
	while (sum<=1000000) {
		//今月の値
		sum=sum+deposit;
		printf("%2dヶ月目は%7d円を入金、残高%7d円",month,deposit,sum);
		
		if (sum<=1000000) {	//残高が100万円以下の月は改行する
			printf("\n");	//つまり、最後の月だけは改行しない
		}
		
		//翌月の値
		month++;
		deposit=deposit*2;
	}
	printf("で100万円を超えました。\n");
	return 0;
}
少し長くなるが、順番に考えていく。
月数、毎月の入金額、残高の3つの変数名を、それぞれ month、deposit、sum とする。
まず、残高が100万円を超えるまで毎月「○ヶ月目は○円を入金、残高○円」と表示することから

	while (sum<=1000000) {
		printf("%2dヶ月目は%7d円を入金、残高%7d円\n",month,deposit,sum);
	}

と書くことができる。
「%2d」「%7d」の%とdの間の数値は表示する文字数を表す。 符合も1文字と数える。 数値の桁が少なくて指定した文字数に満たない場合は、不足分だけ数値の左に空白が追加される。 例えば、「%2d」で1を表示すると空白1個と「1」になり、「%7d」で1を表示すると空白6個と「1」になる。 プログラムが完成してから実行結果を見れば理解できるだろう。

続いて、変数に値を代入していく。 月数の変数month は、最初の値は1で、以降は1ずつ増えていく。 したがって

	month=1;
	while (sum<=1000000) {
		printf("%2dヶ月目は%7d円を入金、残高%7d円\n",month,deposit,sum);
		month++;
	}

となる。 入金額の変数deposit は、最初の値は1で、以降は毎月2倍になっていく。 したがって

	month=1;
	deposit=1;
	while (sum<=1000000) {
		printf("%2dヶ月目は%7d円を入金、残高%7d円\n",month,deposit,sum);
		month++;
		deposit=deposit*2;
	}

となる。 deposit の合計が残高sum なので、繰り返し処理に入る前に sum の値を0にしておいて、繰り返し処理で deposit を加えていけばよい。 したがって

	month=1;
	deposit=1;
	sum=0;
	while (sum<=1000000) {
		sum=sum+deposit;
		printf("%2dヶ月目は%7d円を入金、残高%7d円\n",month,deposit,sum);
		month++;
		deposit=deposit*2;
	}

となる。 printf で残高を表示しているので、それより前に sum を計算しなければならない。 そのため、「sum=sum+deposit」の位置は printf よりも前になる。
最後の月だけは表示する文章が少し違っていて「で100万円を超えました。」が付くので、while文が終わった後に printf を加える。

	month=1;
	deposit=1;
	sum=0;
	while (sum<=1000000) {
		sum=sum+deposit;
		printf("%2dヶ月目は%7d円を入金、残高%7d円\n",month,deposit,sum);
		month++;
		deposit=deposit*2;
	}
	printf("で100万円を超えました。\n");

ところが、これだと最後の月の文章「○ヶ月目は○円を入金、残高○円で100万円を超えました。」が途中で改行してしまう。 これを防ぐために、最後の月だけ「○ヶ月目は○円を入金、残高○円」の後ろで改行しない(sumが100万以下の月だけ改行する)よう書き換える。

	month=1;
	deposit=1;
	sum=0;
	while (sum<=1000000) {
		sum=sum+deposit;
		printf("%2dヶ月目は%7d円を入金、残高%7d円",month,deposit,sum);
		if (sum<=1000000) {
			printf("\n");
		}
		month++;
		deposit=deposit*2;
	}
	printf("で100万円を超えました。\n");

最初の printf から「\n」を削除し、代わりに if文を書き足して sumが100万以下の時だけ「printf("\n")」を実行するようにした。 これで、最後の月(sumが100万を超えた月)は改行しなくなる。
宣言文やコメントなどを付ければ、上の解答例となる。

無限ループの例:
#include <stdio.h>

int main(void)
{
	int month, deposit, sum;
	
	//初月の値
	month=1;
	deposit=1;
	sum=0;
	
	while (1) {
		//今月の値
		sum=sum+deposit;
		printf("%2dヶ月目は%7d円を入金、残高%7d円",month,deposit,sum);
		
		if (sum>1000000) {	//残高が100万円を超えたら終了
			break;
		}
		printf("\n");	//以下は、残高が100万円を超えたら実行されない
		
		//翌月の値
		month++;
		deposit=deposit*2;
	}
	printf("で100万円を超えました。\n");
	return 0;
}
最初の例の

	while (sum<=1000000) {
		if (sum<=1000000) {
			printf("\n");
		}
	}

の部分を

	while (1) {
		if (sum>1000000) {
			break;
		}
		printf("\n");
	}

と書き換えたものである。 両者を見比べれば、同じ動作をすることが解るだろう。


二重ループ

繰り返し処理の中に繰り返し処理を含んでいるもののことを二重ループという。 for文でもwhile文でも二重ループを書くことができる。

二重ループの例1

アスタリスク「*」を縦横に並べるプログラム:
#include <stdio.h>

int main(void)
{
	int x, y;
		
	for (y=1; y<=5; y++) {
		for (x=1; x<=3; x++) {
			printf("*");
		}
		printf("\n");
	}
	return 0;
}
内側のfor文は3回繰り返すループであるが、それ自体が外側のfor文によって5回繰り返される。 内側のfor文の次に改行のprintf文があるので、内側のfor文が3回繰り返した後で毎回改行される。

二重ループの例2

アスタリスク「*」を三角に並べるプログラム:
#include <stdio.h>

int main(void)
{
	int x, y;
		
	for (y=1; y<=5; y++) {
		for (x=1; x<=y; x++) {
			printf("*");
		}
		printf("\n");
	}
	return 0;
}
先程のプログラムの「x<=3」を「x<=y」に変えただけである。 外側のfor文の回によって、内側のfor文の繰り返し回数が変わる。

二重ループの例3

アスタリスク「*」を先程とは逆向きの三角に並べるプログラム:
#include <stdio.h>

int main(void)
{
	int x, y;
		
	for (y=1; y<=5; y++) {
		for (x=1; x<=5; x++) {
			if (x<=5-y) {
				printf(" ");
			} else {
				printf("*");
			}
		}
		printf("\n");
	}
	return 0;
}
実際には記号を長方形に並べており、x,yの値によって空白とアスタリスクを切り替えている。 空白は見えないので、アスタリスクだけが三角に並んでいるように見える。

二重ループの例4

アスタリスク「*」を11個x11個並べた中に空白でバツ印を描くプログラム:
#include <stdio.h>

int main(void)
{
	int x, y;
		
	for (y=1; y<=11; y++) {
		for (x=1; x<=11; x++) {
			if (x==y || x==12-y) {
				printf(" ");
			} else {
				printf("*");
			}
		}
		printf("\n");
	}
	return 0;
}
x,yの値によって空白とアスタリスクを切り替えている。

二重ループの例5

年利率が0.1%、0.2%、…、2.0%のそれぞれについて、2年、3年、…、10年預けた時の金利を計算するプログラム:
#include <stdio.h>

int main(void)
{
	int x, y;
	double interest, rate;
				
	for (y=1; y<=20; y++) {
		rate=(double)y/1000.0;
		interest=rate;
		printf("|%.1f%%|",rate*100.0);
		for (x=2; x<=10; x++) {
			interest=interest+(1.0+interest)*rate;
			printf("%6.3f%%|",interest*100.0);
		}
		printf("\n");
	}
	return 0;
}
printfで「%」を表示したい時は「%%」と書く
「%6.3f」は、実数を6文字かつ小数第3位までで表示するという意味である。 %とfの間の、ドット「.」の左の数値が表示する文字数を、右の数値が小数点以下の表示桁数を表す。 符合と小数点も1文字として数える。

二重ループの例6

先程のプログラムを書き換えて、表の形で出力するようにする。
#include <stdio.h>

int main(void)
{
	int x, y;
	double interest, rate;
		
	//1行目
	printf("+----------------------------------------------------------------------------+\n");
		
	//2行目
	printf("|年利|");
	for (x=2; x<=10; x++) {
		printf("%2d年後 |",x);
	}
	printf("\n");
		
	//3行目
	printf("|----");
	for (x=2; x<=10; x++) {
		printf("+-------");
	}
	printf("|\n");
	
	//本体
	for (y=1; y<=20; y++) {
		rate=(double)y/1000.0;
		interest=rate;
		printf("|%.1f%%|",rate*100.0);
		for (x=2; x<=10; x++) {
			interest=interest+(1.0+interest)*rate;
			printf("%6.3f%%|",interest*100.0);
		}
		printf("\n");
	}
		
	//最終行
	printf("+----------------------------------------------------------------------------+\n");
	return 0;
}


練習問題

先程の金利の表のプログラムを書き換えて、年数をキーボードで入力できるようにしなさい。