C言語のきほん|for文とwhile文を使った多重ループを比較する

同じ多重ループでも、書き方で事故率が変わる。forとwhileの“得意な役割分担”を身につけよう。

多重ループはforでもwhileでも書けるけど、向き不向きがある

多重ループは、外側が「行」、内側が「列」を担当する…という考え方でした。
この構造は for でも while でも作れます。動作の本質は同じです。

ただ、書き方の違いがそのまま「読みやすさ」や「ミスの起きやすさ」に直結します。

  • for:回数が明確な繰り返しを、短く・見通しよく書ける
  • while:条件や終了タイミングが変動する繰り返しを、柔軟に書ける(でも更新忘れで無限ループになりやすい)

さらに、外側と内側で for と while を混ぜて使うと「一番自然な形」にできます。ここが今回のポイントです。

for文の多重ループの特徴

forの二重ループは、初期化・条件・更新が括弧の中にまとまるので、ループの形が一目で分かります。

観点forの強み
見通しループの形が1行で分かる
向いている場面回数や範囲が決まっている(行数、列数が固定)
多重ループでの定番外側も内側もforで行×列を作る

while文の多重ループの特徴

whileは初期化と更新を自分で書く必要があるぶん、自由度が高い反面、ミスもしやすいです。

観点whileの特徴
柔軟性条件が変動するループに強い
注意点更新を書き忘れると無限ループになりやすい
多重ループでの使いどころ入力が終わるまでなど、回数が不確定な外側ループ

図で整理:forとwhileを混ぜると自然になる

この “外側while+内側for” は、実務でもよく出てきます。

サンプルプログラム

例:入力された回数だけ「#」を表示(0以下で終了)

  • 外側:入力が続く限り繰り返す(while)
  • 内側:指定回数だけ表示(for)

ファイル名:9_9_1.c

// 指定された個数の「#」を繰り返し表示するプログラム
#include <stdio.h>

int main(void)
{
    int num;

    printf("表示回数を入力してください(0以下で終了)> ");
    scanf("%d", &num);

    while (num > 0) {                 // 入力が正の間だけ繰り返す(while)
        for (int i = 1; i <= num; i++) {  // num回だけ繰り返す(for)
            printf("#");
        }
        printf("\n");

        printf("表示回数を入力してください(0以下で終了)> ");
        scanf("%d", &num);
    }

    printf("終了します。\n");
    return 0;
}

ここが使い分けの気持ちいいところ

  • 外側は「いつ終わるか分からない」のでwhile
  • 内側は「回数が決まっている」のでfor
    この役割分担が自然で、読みやすくなります。

for多重ループとwhile多重ループを同じ処理で書き比べる

ここでは「3行×5列の数表」を両方で書いて、違いを体感します。

for版(回数が明確でスッキリ)

ファイル名:9_9_2.c

// forの二重ループで 3行×5列 を表示するプログラム
#include <stdio.h>

int main(void)
{
    for (int row = 1; row <= 3; row++) {
        for (int col = 1; col <= 5; col++) {
            printf("%d ", col);
        }
        printf("\n");
    }
    return 0;
}

while版(初期化と更新の位置に注意)

ファイル名:9_9_3.c

// whileの二重ループで 3行×5列 を表示するプログラム
#include <stdio.h>

int main(void)
{
    int row = 1;                 // 外側の初期化

    while (row <= 3) {           // 外側の条件
        int col = 1;             // 内側は毎行ごとに初期化が必要

        while (col <= 5) {       // 内側の条件
            printf("%d ", col);
            col++;               // 内側の更新(忘れると無限ループ)
        }

        printf("\n");
        row++;                   // 外側の更新(忘れると無限ループ)
    }

    return 0;
}

while版でよくある事故(ここ注意)

  • colの初期化を外に置いてしまう
    → 2行目以降、内側ループが回らない(colがすでに6になっているなど)
  • col++やrow++を書き忘れる
    → 無限ループ

多重ループだと更新が2か所あるので、whileは特に事故りやすいんです。

実践問題:行数ぶんの段を表示

行数を入力し、次のように段を表示してください。

実行例

行数を入力してください > 4
1
1 2
1 2 3
1 2 3 4

解答例

ファイル名:9_9_4.c

// 行数に応じて段を表示するプログラム
#include <stdio.h>

int main(void)
{
    int n;

    printf("行数を入力してください > ");
    scanf("%d", &n);

    for (int row = 1; row <= n; row++) {
        for (int col = 1; col <= row; col++) {  // 行番号と同じ回数だけ表示
            printf("%d ", col);
        }
        printf("\n");
    }

    return 0;
}

解説

内側の継続条件は col <= row。
その行で表示したい個数が row 個だからです。

実践問題:九九の表を表示

解答例

ファイル名:9_9_5.c

// 九九の表を表示するプログラム
#include <stdio.h>

int main(void)
{
    printf("* * * 九九の表示 * * *\n");
    printf("    |");

    for (int col = 1; col <= 9; col++) {
        printf("%3d", col);
    }
    printf("\n");

    printf("--------------------------------\n");

    for (int row = 1; row <= 9; row++) {
        printf("%2d |", row);                 // 行見出しと区切り線
        for (int col = 1; col <= 9; col++) {  // 掛け算本体
            printf("%3d", row * col);
        }
        printf("\n");
    }

    return 0;
}

解説(どこで何を表示するか)

  • 最初にタイトル行
  • 次に上段の列見出し(1〜9)
  • その次に横線
  • そのあと、外側ループで行(1〜9)
    ・行頭で row と | を表示
    ・内側ループで row * col を並べる

「| をどこで出すか」を先に決めると、迷いにくいです。

実践問題:0~9の3つの数の和が指定値になる組

0~9の3つの整数 (a, b, c) の和が入力した合計値になる組み合わせをすべて表示し、通り数も表示してください。

解答例

ファイル名:9_9_6.c

// 0~9の3つの数の和が指定値になる組を全探索するプログラム
#include <stdio.h>

int main(void)
{
    int target;
    int count = 0;

    printf("合計値を入力してください。> ");
    scanf("%d", &target);

    for (int a = 0; a <= 9; a++) {
        for (int b = 0; b <= 9; b++) {
            for (int c = 0; c <= 9; c++) {
                if (a + b + c == target) {
                    printf("(%d, %d, %d)\n", a, b, c);
                    count++;
                }
            }
        }
    }

    printf("合計値が%dになる組み合わせは%d通りです。\n", target, count);

    return 0;
}

解説

三重ループは「全パターンを試す」ための道具です。
0〜9の10通りが3つなので、10×10×10=1000通りを全部チェックしています。
ifで一致したものだけ表示して数えます。

実践問題:forとwhileを組み合わせる二重ループ

セット回数を入力し、その回数だけ次を繰り返してください。

  • 0以下が入力されるまで、正の整数を何回でも入力できる
  • 入力された正の整数の合計を表示する
  • これをセット回数ぶん繰り返す

解答例

ファイル名:9_9_7.c

// forとwhileを組み合わせて、セットごとに合計を求めるプログラム
#include <stdio.h>

int main(void)
{
    int times;

    printf("セット回数を入力してください > ");
    scanf("%d", ×);

    for (int t = 1; t <= times; t++) {
        int n;
        int sum = 0;

        printf("---- %dセット目 ----\n", t);

        printf("整数値を入力してください(0以下で終了)> ");
        scanf("%d", &n);

        while (n > 0) {
            sum += n;

            printf("整数値を入力してください(0以下で終了)> ");
            scanf("%d", &n);
        }

        printf("合計値 = %d\n\n", sum);
    }

    return 0;
}

解説(役割分担がキレイ)

  • 外側for:セット回数が決まっている(回数主役)
  • 内側while:0以下が出るまで入力(条件主役)
    この分担は、まさに「forとwhileの使い分け」の実戦例です。

実践問題:菱形を表示

ファイル名:9_9_8.c

// 入力nに応じて菱形を表示するプログラム(奇数・偶数対応)
#include <stdio.h>

int main(void)
{
    int n;
    printf("*の数を入力してください > ");
    scanf("%d", &n);

    if (n <= 0) {
        printf("エラー:1以上を入力してください。\n");
        return 0;
    }

    // 偶数なら最大は n-1、奇数なら最大は n
    int maxStars = (n % 2 == 0) ? (n - 1) : n;

    // 上り(1,3,5,...,maxStars)
    for (int stars = 1; stars <= maxStars; stars += 2) {
        int spaces = (n - stars) / 2;   // n幅で中央寄せ
        for (int s = 0; s < spaces; s++) printf(" ");
        for (int k = 0; k < stars; k++) printf("*");
        printf("\n");
    }

    // 下り(maxStars-2,...,3,1)
    for (int stars = maxStars - 2; stars >= 1; stars -= 2) {
        int spaces = (n - stars) / 2;
        for (int s = 0; s < spaces; s++) printf(" ");
        for (int k = 0; k < stars; k++) printf("*");
        printf("\n");
    }

    return 0;
}

解説(菱形は3つの部品でできてる)

1行ごとにやっていることは毎回同じです。

  1. 先頭にスペースを出す(中央寄せ)
  2. 星を stars 個出す
  3. 改行

外側ループは stars の値を 1→3→5… と増やし、次に減らしていくだけです。
内側ループは「スペースをspaces回」「星をstars回」出す担当です。

実行結果例1(奇数のnを入力した場合:n=7)

*の数を入力してください > 7
   *
  ***
 *****
*******
 *****
  ***
   *

実行結果例2(偶数のnを入力した場合:n=6)

*の数を入力してください > 6
  *
 ***
*****
 ***
  *