while
回数が決まっていない繰り返し
前回の for は「5 回」「40 回」のように回数が先に決まっているときの道具でした。ところが成績管理では、何件入力されるか実行するまで分からない、という場面のほうが多くなります。こういうときに使うのが while です。
while (条件) {
繰り返したい処理
}読み方はそのまま「条件が真であるあいだ、中身を繰り返す」です。for の丸カッコから初期化と更新を取り除き、条件だけを残した形だと考えると分かりやすくなります。
終わらせ方は自分で用意する
for は i++ が自動で条件に近づけてくれましたが、while にはそれがありません。中身のどこかで条件を偽に近づける処理を 自分で書かないと、永久に止まりません。これが無限ループです。
int score;
int total = 0;
scanf("%d", &score);
while (score >= 0) {
total += score;
scanf("%d", &score);
}この形は「番兵」と呼ばれる定番です。負の数が来たら終わり、という合図の値をあらかじめ決めておき、それが来るまで読み続けます。点数は 0 以上しかありえないので、負の数を終了の合図に使えます。
注目してほしいのは scanf が 2 か所 にあることです。ループに入る前に 1 件目を読んでおき、中身の最後で次の 1 件を読みます。こうしないと、条件を確かめる時点で score にまだ何も入っていない、という状態になります。初期化していない変数の中身は決まっていないので、そのまま条件に使うと結果が予測できません。
1回も回らないことがある
while も for と同じく、条件を確かめるのは中身の 前 です。1 件目にいきなり負の数が来たら、中身は 1 回も実行されません。件数が 0 件でも合計が 0 と正しく出るように、total や count はループの前に 0 で初期化しておきます。
無限ループを作ってしまったときは、total += score; は書いたのに 2 つ目の scanf を忘れた、というのが定番の原因です。条件に出てくる変数が、中身のどこで変わるのかを指で追って確かめてください。
for と while は書き換えられる
じつは for で書けるものは while でも書けます。for (i = 1; i <= 5; i++) は、int i = 1; をループの前に出し、while (i <= 5) と書き、中身の最後に i++; を置けば、まったく同じ動きになります。逆に while で書いたものを for に直すこともできます。
どちらを使うかは、動きの違いではなく 何が主役か で決めます。回数が主役なら for、条件が主役なら while です。初期化と更新が丸カッコの中にまとまっている for は、回数を数える意図がひと目で伝わります。一方 while は、終わる条件だけを目立たせたいときに読みやすくなります。同じ動きをする書き方が複数あるとき、意図がいちばん伝わるものを選ぶ、というのはこの先ずっと付いてくる判断です。
では、負の点数が来るまで点数を読み続けて、件数と合計を出してみましょう。
要件
- 点数を読むたびに「1件目 80点」の形で表示する
- 負の数が来たら読み込みをやめ、「入力終了」と表示する
- 最後に「3件の合計は240点です」の形で件数と合計を表示する
- 1件も入力されなかった場合も 0件 0点 と正しく表示する
入出力例
main(80, 90, 70, -1) → "1件目 80点
2件目 90点
3件目 70点
入力終了
3件の合計は240点です"
main(-1) → "入力終了
0件の合計は0点です"