ループ構造
ループは陸上トラックの周回走のようなものです——ゴールラインに達するまで走り続けます。条件が満たされたら止まる。ループがあれば、プログラムは一度きりの実行にとどまらず、繰り返し処理ができるようになります。
whileループ
whileは最も基本的なループです。まず条件を確認し、真ならループ本体を実行し、再び条件を確認する、という繰り返しで条件が偽になるまで続けます。
#include <stdio.h>
int main(void) {
int count = 1;
while (count <= 5) {
printf("Lap %d\n", count);
count++;
}
printf("Done!\n");
return 0;
}
Lap 1
Lap 2
Lap 3
Lap 4
Lap 5
Done!
count++など)が必ず必要です。さもないと無限ループになり、プログラムが永遠に止まらなくなります。
whileを使う場面
繰り返し回数が不定で実行時の条件に依存する場合、whileが最も自然な選択です。例えば、特定の値が入力されるまで読み込みを続ける場合などです。
#include <stdio.h>
int main(void) {
int sum = 0;
int num = 0;
printf("Enter positive integers to sum, 0 to finish: ");
scanf("%d", &num);
while (num != 0) {
sum += num;
scanf("%d", &num);
}
printf("Sum: %d\n", sum);
return 0;
}
Enter positive integers to sum, 0 to finish: 10 20 30 0
Sum: 60
do-whileループ
do-whileはまずループ本体を実行してから条件を確認します。ループ本体が必ず少なくとも1回は実行されることが、whileとの決定的な違いです。
#include <stdio.h>
int main(void) {
int num;
do {
printf("Enter a number 1-10: ");
scanf("%d", &num);
} while (num < 1 || num > 10);
printf("You entered: %d\n", num);
return 0;
}
Enter a number 1-10: 15
Enter a number 1-10: 0
Enter a number 1-10: 7
You entered: 7
do-whileの末尾のセミコロンは省略できません。} while (condition); セミコロンを忘れるとコンパイルエラーになります。
whileとdo-whileの使い分け
- 少なくとも1回は実行が必要 →
do-while(例:入力の検証) - 0回の可能性もある →
while(例:見つからないかもしれない探索)
forループ
forは初期化、条件確認、更新をヘッダーにまとめる、最もよく使われるループ形式です。
for (initialization; condition; update) {
loop body;
}
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 5; i++) {
printf("%d ", i);
}
printf("\n");
return 0;
}
1 2 3 4 5
forループの実行フロー
- 初期化を実行(1回だけ)
- 条件を確認——偽ならループを抜ける
- ループ本体を実行
- 更新を実行
- 手順2に戻る
forの柔軟性
forの3つの部分はすべて省略可能ですが、セミコロンは残す必要があります。
#include <stdio.h>
int main(void) {
int i = 1;
for (; i <= 5; ) {
printf("%d ", i);
i++;
}
printf("\n");
return 0;
}
条件を省略すると無限ループになります。for (;;) {}はwhile (1) {}と等価です。
forループを優先しましょう。ループ変数、境界条件、更新方法が一目でわかるため、うっかり無限ループを書く危険が少なくなります。
スコープの考慮
C99ではforの初期化部で変数を宣言できます。その変数はforループ内でのみ有効です。
#include <stdio.h>
int main(void) {
for (int i = 0; i < 3; i++) {
printf("i = %d\n", i);
}
return 0;
}
ループ終了後、iにはアクセスできません。ループ外でiを使う必要がある場合は、forの前に宣言してください。
ネストされたループ
ループの中に別のループを入れたものがネストされたループです。外側のループの各反復で、内側のループが1回完全に実行されます。
星形の長方形を出力
#include <stdio.h>
int main(void) {
int rows = 3;
int cols = 5;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("* ");
}
printf("\n");
}
return 0;
}
* * * * *
* * * * *
* * * * *
九九の表
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
printf("%d*%d=%-4d", j, i, i * j);
}
printf("\n");
}
return 0;
}
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
break文
breakは現在のループをただちに抜けます(1レベルだけ)。残りの反復はスキップされます。
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break;
}
printf("%d ", i);
}
printf("\nStopped at 5\n");
return 0;
}
1 2 3 4
Stopped at 5
条件を満たす最初の要素を見つける
#include <stdio.h>
int main(void) {
int nums[] = {3, 7, 2, 9, 5, 1};
int target = 9;
int found = 0;
for (int i = 0; i < 6; i++) {
if (nums[i] == target) {
printf("Found %d at index %d\n", target, i);
found = 1;
break;
}
}
if (!found) {
printf("%d not found\n", target);
}
return 0;
}
Found 9 at index 3
continue文
continueは現在の反復の残りの文をスキップし、次の反復にジャンプします(条件確認または更新手順に戻ります)。
#include <stdio.h>
int main(void) {
for (int i = 1; i <= 10; i++) {
if (i % 3 == 0) {
continue;
}
printf("%d ", i);
}
printf("\nMultiples of 3 skipped\n");
return 0;
}
1 2 4 5 7 8 10
Multiples of 3 skipped
whileやdo-whileループでcontinueを使う場合、更新文がcontinueよりも前にあることを確認してください。さもないと無限ループになる可能性があります。
よくあるループパターン
カウントパターン
条件を満たす要素の数を数えます。
#include <stdio.h>
int main(void) {
int nums[] = {12, 45, 3, 67, 89, 23, 56};
int count = 0;
for (int i = 0; i < 7; i++) {
if (nums[i] > 50) {
count++;
}
}
printf("Numbers greater than 50: %d\n", count);
return 0;
}
Numbers greater than 50: 3
累積パターン
一連の値を合計します。
#include <stdio.h>
int main(void) {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
printf("Sum from 1 to 100: %d\n", sum);
return 0;
}
Sum from 1 to 100: 5050
探索パターン
条件を満たす最初の要素を見つけ、breakで抜けます。前出のbreakの例を参照してください。
走査パターン
配列の各要素を順番に処理します。
#include <stdio.h>
int main(void) {
int scores[] = {85, 92, 78, 96, 61};
int len = 5;
for (int i = 0; i < len; i++) {
printf("Student%d: %d %s\n", i + 1, scores[i], scores[i] >= 60 ? "Pass" : "Fail");
}
return 0;
}
Student1: 85 Pass
Student2: 92 Pass
Student3: 78 Pass
Student4: 96 Pass
Student5: 61 Pass
無限ループとその回避方法
無限ループとは、条件が常に真であるループです。意図的な無限ループはfor(;;)やwhile(1)を使い、内部でbreakで抜けます。
#include <stdio.h>
int main(void) {
int num;
while (1) {
printf("Enter a number (0 to quit): ");
scanf("%d", &num);
if (num == 0) {
break;
}
printf("You entered: %d\n", num);
}
printf("Goodbye!\n");
return 0;
}
意図しない無限ループは、ループ変数が更新されない、または間違った方向に更新されることが原因で発生します。
int i = 0;
while (i < 10) {
printf("%d", i);
}
例
ネストされたループで直角三角形を出力します。
#include <stdio.h>
int main(void) {
int n = 5;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
printf("* ");
}
printf("\n");
}
return 0;
}
*
* *
* * *
* * * *
* * * * *
例
ユークリッドの互除法で2つの正の整数の最大公約数を求めます。反復回数が不定なwhileループの実例です。
#include <stdio.h>
int main(void) {
int a = 48, b = 18;
int orig_a = a, orig_b = b;
while (b != 0) {
int temp = a % b;
a = b;
b = temp;
}
printf("GCD of %d and %d is %d\n", orig_a, orig_b, a);
return 0;
}
GCD of 48 and 18 is 6
3種のループの使い分け
| 状況 | 推奨 |
|---|---|
| 反復回数が固定 | for |
| 少なくとも1回は実行が必要 | do-while |
| 反復回数が不定 | while |
| 対話型メニュー | do-while + switch |
❓ よくある質問
forとwhileはどちらを使うべきですか?for、そうでない場合はwhileを使うのが最も広く受け入れられているガイドラインです。breakで複数レベルのループを抜けられますか?breakは最内側のループしか抜けません。複数レベルを抜けるには、フラグ変数と外側ループの確認を組み合わせるか、gotoを使います(推奨されませんが実用的な場合があります)。for(;;)とwhile(1)はどちらが良いですか?while(1)のほうが読みやすく、for(;;)は伝統的なCスタイルです。チームの規約に従ってください。i、j、kを使ってもよいですか?row、col、student_index)は、説明的な名前が良いです。📖 まとめ
whileは実行前に確認、do-whileは実行後に確認、forは3つの要素をヘッダーに集約しますforは反復回数が決まっているループで最もよく使われる構造です- ネストされたループの総反復回数は各レベルの回数の積になります。パフォーマンスに注意してください
breakは現在のループを抜け、continueは現在の反復をスキップします。どちらも最内側のループにのみ作用します- 意図しない無限ループを避けるため、ループ変数が正しく、正しい方向に更新されることを確認しましょう
📝 練習問題
forループを使って階乗の和 1! + 2! + 3! + ... + 10! を計算するプログラムを書いてください。- ネストされたループを使って、逆直角三角形(5行で、1行目に星5個、5行目に星1個)を出力するプログラムを書いてください。
- 正の整数を読み込み、その桁を逆順に出力するプログラムを書いてください(例:1234の入力で4 3 2 1と出力)。



