C言語学習ポータル(無料版) 学習コンテンツ 制御構造 ループのネストと九九表

🔀 制御構造

ループのネストと九九表

無料公開版に収録・読む目安 12分

🎯 二重ループの動きを説明でき、九九表のような表形式の出力を自分で組み立てられる

アナログ時計を見てください。長針が1周する間に、短針は1目盛りだけ進みます。外側が1回進む間に、内側は最初から最後まで回りきる。これがループのネスト(入れ子)です。

外側3回、内側3回なら、本体が実行されるのは 3×3 = 9回。掛け算になるのがポイントです。

定番中の定番、九九表を作りましょう。

#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 9; i++) {          // 段
        for (int j = 1; j <= 9; j++) {      // 掛ける数
            printf("%3d", i * j);
        }
        printf("\n");                        // 1段ぶん終わったので改行
    }
    return 0;
}

9行9列の表が出ます。%3d は「3桁ぶんの幅で右寄せ」というprintfの書式指定で、これがあるおかげで桁が揃います。

このコードで本当に大事なのは、改行の位置です。printf("\n") は内側のループの外、外側のループの中にあります。ここを間違えると形が崩れます。

改行を内側のループの中に入れると、数字が1つ出るたびに改行されて縦1列になります。改行を外側のループの外に出すと、81個の数字が全部1行に並びます。「内側が回りきったら、1行ぶん終わり」——この対応を意識すると、表の出力で迷わなくなります。

ビット外側1回ぶんが「1段」。内側が回りきったら改行、って唱えると九九表は一発だよ

内側の条件に外側の変数を使うと、段ごとに長さを変えられます。

#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 5; i++) {
        for (int j = 1; j <= i; j++) {   // 上限が外側の i
            printf("*");
        }
        printf("\n");
    }
    return 0;
}

* が1個、2個、3個…と増えて三角形になります。ネストの本当の威力はここで、内側と外側を連動させると一気に表現力が上がります。

前のトピックで触れた「breakは内側しか抜けない」問題も片付けておきましょう。外側まで抜けたいときはboolのフラグを使います。

#include <stdio.h>

int main(void) {
    bool found = false;

    for (int i = 1; i <= 3 && !found; i++) {   // フラグを外側の条件にも入れる
        for (int j = 1; j <= 3; j++) {
            if (i * j == 4) {
                printf("見つけた: %d x %d\n", i, j);
                found = true;
                break;                          // 内側を抜ける
            }
        }
    }
    return 0;
}

内側で found = true にしてから break すると、外側の継続条件 !found が偽になって外側も終わります。少し回りくどく見えますが、流れが1本道なので後から読む人に優しい書き方です。

罠を2つ。

その1、カウンタ名の使い回し。 外側も内側も i にすると、内側が外側のカウンタを壊して動きがめちゃくちゃになります。i, j, k と分けてください。

その2、実行回数は掛け算。 外側 n 回・内側 n 回なら本体は n×n 回です。n が 1000 なら100万回。ネストは静かに重くなります。三重にすれば n×n×n。「入れ子を1つ増やすと桁が変わる」という感覚は、今のうちに持っておいて損はありません。

まとめます。外側1周につき内側は回りきる。表の形を決めるのは改行の位置。カウンタ名は分ける。実行回数は掛け算で効いてくる。

要点まとめ

アプリで演習問題まで解く(無料・登録不要)

この項目に出てくる用語

入れ子(ネスト)いれこ

if文やループの中に、さらにif文やループを書くことのこと。九九表のような2次元的な処理を扱うときによく使われる書き方。深くなりすぎると読みにくくなるため、関数分割で整理することもある。

for文ふぉーぶん

「初期化・条件・更新」の3つを1行にまとめて書ける繰り返し構文のこと。回数があらかじめ決まっている繰り返しにとくに向いている。繰り返す回数があらかじめはっきりしている場面で、とくに書きやすい構文。

break文ぶれいくぶん

ループやswitch文の実行をその場で強制的に抜け出す命令のこと。「これ以上繰り返す必要がない」と判断したときに使う。多重ループの中で使うと、いちばん内側のループだけを抜ける点に注意が必要。

bool型ぶーるがた

true(真)かfalse(偽)のどちらかしか入らない型のこと。C23では標準の書き方としてbool・true・falseがそのまま使えるようになった。従来は0と1で真偽を表していたが、C23の書き方の方が意図が伝わりやすい。

同じトラックのほかの項目

流れを変える——制御構造の全体像プログラムの流れが「順次・分岐・繰り返し」の3つでできていることを理解し、場面に応じてどれを使うか見当をつけられ… if文——もしも、の分かれ道if文の書き方と条件式の考え方を理解し、条件によって処理を分けられるようになる else if / else の分かれ道設計else / else if で複数の分かれ道を作れるようになり、範囲判定の順序を正しく設計できる 条件式の罠——= と == の悲劇代入 = と比較 == の違いを説明でき、条件式で取り違えたときに何が起きるかを見抜ける 論理演算子と短絡評価&& || ! で複数の条件を組み立てられるようになり、短絡評価の性質を安全のために利用できる switch文とfallthroughswitch文で値による多分岐を書けるようになり、break忘れによるフォールスルーを理解する for文——回数が決まった繰り返しfor文の3つの部品と実行順序を理解し、回数の決まった繰り返しを正しく書ける while文——条件が決める繰り返しwhile文で終わりの読めない繰り返しを書けるようになり、for との使い分けを判断できる do-while文と入力チェックdo-while の「まず1回は実行する」性質を理解し、入力のやり直しループを書ける breakとcontinueの使いどころbreak でループを打ち切り、continue で残りをスキップできるようになり、それぞれの副作用を避けられる 無限ループとの付き合い方無限ループの原因を3つの型で診断でき、意図的な無限ループを出口つきで安全に書ける
‹ breakとcontinueの使いどころ 無限ループとの付き合い方 ›

もっと先へ:ポインタ・メモリ・ファイル入出力・セキュアコーディングを含む全26トラックと、段位検定・模試のフルセットは完全版に収録しています。

完全版(BOOTH)を見る

📚 姉妹教材:手を動かして覚える Linux 教材 — Linuxとインフラの仕組みを地図で学ぶ

Web版 / BOOTH