目標
繰り返しとは何か理解し、while 文で繰り返しが書けるようにする。
プログラムの構造化定理 (再掲)
プログラムは次の3つの構造の組み合わせで、どんなことでも表現できることが数学的に証明されています。
- 連接 (順次)
- 分岐 (選択)
- 繰り返し
連接は、上から下にへ、書かれた順番でプログラムを実行するという意味です。
これは、今までのプログラムで無意識に利用してきました。
今回は、3番目の繰り返しにあたる構造を勉強します。
繰り返しとは
たとえば、1 から 100 までの整数を足すことを考えてみます。
これをそのまま数学の式で書くと、次のようになります。
1 + 2 + 3 + … + 99 + 100
これはシグマを使って置き換えることができます。
繰り返しとは、このようにある作業 (この場合、足し算) を何回も実行することをいいます。
また、繰り返しのことは、ループとも言います。
繰り返しの例
1 から 100 までの整数を足し、合計を表示するプログラムは次のようになります。
int i, sum;
i = 1;
sum = 0;
while(i <= 100){
sum = sum + i;
++i;
}
printf("%d\n", sum);
上の例では、変数 i が 1 から 100 までインクリメントによって変化します。
そして、その変化する i を sum に加算しています。
i <= 100 というのは、この繰り返しが実行され続ける条件です。
この場合、i が 100 以下な間、括弧 {} の中を繰り返しなさい、という意味になります。
条件として指定できるものは、if 文と同じです。
絶対に成立する条件を指定した場合、プログラムが終了しないので注意してください*1。
while 文
while 文は次のような形式をしています。
while(条件){
条件が成立している間実行する文;
}
たとえば、条件に i < 10 と指定した場合、変数 i が 10 未満な間、括弧の中を実行します。
条件がはじめから成り立っていない場合、一回も実行されません。
以下は、1 から 10 まで表示する例です。
int i;
int a;
i = 1;
a = 10;
while(i <= a){
printf("%d\n", i);
++i;
}
++i (もしくは i++) を忘れないように注意してください。
これを忘れると、i が増えないため、永遠に 1 が表示されます。
break 文
while 文の中で break 文を使うと、条件に関係なく強制的にループを抜けます。
int i;
i = 1;
while(i <= 10){
if(i == 6){
break;
}
printf("%d\n", i);
++i;
}
上の例では、1 から 5 まで表示されます。
i が 6 になったとき (i == 6) に、if 文が成立し、表示される前に強制的にループから抜けるからです。
continue 文
ループを強制的に抜けるには break 文を使うことは既に知っていると思います。
今回は、似たような働きをする continue 文について扱います。
break 文は、以下の図のように強制的にループを終了させる働きをしました。
一方、continue 文は、括弧内の処理の末尾の次にジャンプします。
continue 文では、ループは終了しませんが、continue 文以降の処理が省かれることになります。
break, continue 文は、while, for, do-while 文で利用できます。
無限ループ
while 文の条件に、必ず成立する条件を書いておくループを、無限ループといいます。
以下が無限ループの例です (終了しないので、Ctrl-C で終了してください)。
while(1){
printf("loop\n");
}
C言語では、0 が偽 (不成立)、0 以外が真 (成立) として扱われるため、
上記のコードでは、条件が常に成立しています。
無限ループは、起動したら絶対に終了しないプログラム (組み込み分野、家電製品など) で多く用いられます。
また、先ほどの break 文と組み合わせ、非組み込み分野でも利用されます。
以下が break 文と組み合わせた例です。
int a;
printf("0 以上の整数を入力してください。\n");
while(1){
scanf("%d", &a);
if(a >= 0){
break;
}
printf("入力された値は 0 未満です。正しく入力しなおしてください。\n");
}
上のコードでは、ユーザーが正しく入力するまで、繰り返し入力を求めます。
無限ループを利用せずに同じ事を実現することも可能ですが、
この場合は無限ループを使ったほうが、わかりやすく直感的です。
ちなみに、無限ループを使わない場合は、以下のようにかけます。
int a;
printf("0 以上の整数を入力してください。\n");
scanf("%d", &a);
while(a < 0){
printf("入力された値は 0 未満です。正しく入力しなおしてください。\n");
scanf("%d", &a);
}
課題
課題1
1 から 20 の範囲にある奇数をすべて出力しなさい。
課題2
整数を一つ入力させ、1 からその整数まで出力するプログラムを作りなさい。
実行例
1行目はユーザーの入力です。
./a.out 3 1 2 3
./a.out 5 1 2 3 4 5
課題3
指定された個数の整数を足し、答えを出力するプログラムを作成しなさい。
次のように標準入力から数値を与えます。
3 4 5 1
1行目は、整数の個数です。
2行目は、実際に足す整数です。
この場合、4 + 5 + 1 = 10 なので、10 が答えになります。
実行例
./a.out 1 5 5
./a.out 2 7 4 11
./a.out 3 2 4 3 9
課題4
1 から入力された整数 n まで表示するプログラムを作成しなさい。
その際、指定された整数 a の倍数を表示してはいけない。
ただし、プログラムには continue 文を用いること。
入力形式
整数 n, a をスペース区切りで入力します。
n a
実行例
./a.out 6 2 1 3 5
./a.out 10 3 1 2 4 5 7 8 10
./a.out 100 1
挑戦課題
- AOJ 10005: Print Many Hello World
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=10005
- AOJ 10006: Print Test Cases
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=10006
- AOJ 10007: Swapping Two Numbers
http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=10007