C言語基礎|多重ループで図形を描く

はじめに:多重ループで「画面に図形」を描けるようになるよ

多重ループ(入れ子ループ)は、行(縦)と列(横)を同時に扱えるので、九九表みたいな「表」だけじゃなく、長方形・三角形などの図形も作れます。
しかも、break や continue を組み合わせると「途中でやめる」「条件のときだけ飛ばす」みたいな制御もできて、一気に表現力が上がります。

ここでは、内容をわかりやすくするために、プログラム例を 図形(長方形+右下三角形)にしつつ、表示メッセージも別の日本語に置き換えて解説していきますね。

多重ループの基本:外側が行、内側が列

図形描画はだいたいこの考え方でいけます。

  • 外側のループ:何行描くか(縦方向)
  • 内側のループ:1行に何文字並べるか(横方向)

多重ループと図形の対応

ループ担当具体例
外側(i)行を進める上から下へ 1行ずつ描く
内側(j)1行の中で文字を並べる* や空白を横に並べる

サンプルプログラム例:指定サイズの長方形を描く(基本の図形)

プロジェクト名:chap4-18-1 ソースファイル名:chap4-18-1.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int h, w;

    puts("サイズを指定して、記号で長方形を描きます。");
    printf("たて(行数): ");
    scanf("%d", &h);
    printf("よこ(文字数): ");
    scanf("%d", &w);

    for (int i = 1; i <= h; i++) {          // 行をh回
        for (int j = 1; j <= w; j++) {      // 各行にw個
            putchar('#');                   // 記号は # に変更
        }
        putchar('\n');                      // 行末で改行
    }

    return 0;
}

実行例

サイズを指定して、記号で長方形を描きます。
たて(行数): 3
よこ(文字数): 6
######
######
######

長方形ができる仕組み

長方形の処理は、頭の中ではこうなっています。

外側ループ i = 1..h
  内側ループ j = 1..w
    文字を1個出す
  改行する
  • 内側が横に並べる
  • 外側がそれを縦に積む

これだけで「四角」が描けます。

break と continue を多重ループで使うときの注意点

重要:break が抜けるのは「その break を囲んでいるループだけ」

多重ループで break すると、いきなり外側まで全部終わるわけじゃなくて、基本的に内側だけを抜けます。

break と continue の影響範囲

何をする?多重ループでの影響
breakループを強制終了するその break を直接囲むループを抜ける。
continueその周回の残りをスキップその continue を直接囲むループの残りだけ飛ばす。

break の例:1行の途中で打ち切る(内側だけ抜ける)

長方形の描画中に「この列まででやめる」みたいな例です。

for (int i = 1; i <= h; i++) {
    for (int j = 1; j <= w; j++) {
        if (j > 4) break;      // 5文字目以降は描かない
        putchar('#');
    }
    putchar('\n');
}

この break は 内側の j ループだけを止めます。
外側の i ループは続くので、次の行も描かれます。

continue の例:for文では C部(更新)が必ず走るのが大事

continue すると「残りの処理」を飛ばしますが、for の更新(C部)はちゃんと実行されます

for (int j = 1; j <= w; j++) {
    if (j % 2 == 0) continue;  // 偶数列は飛ばす
    putchar('#');
}
  • j が偶数のときは出力しない。
  • でも j++ は必ず進む。
    だから無限ループにはなりません(ここが安心ポイント)。

もう1つの図形例:右下が直角の三角形(空白+記号の2段構え)

図形が「右寄せ」になる理由は、先に空白を並べるからです。
これも多重ループの典型パターン。

プロジェクト名:chap4-18-2 ソースファイル名:chap4-18-2.c

Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。

#include <stdio.h>

int main(void)
{
    int len;

    puts("右寄せの三角形を描きます。");
    printf("高さ: ");
    scanf("%d", &len);

    for (int i = 1; i <= len; i++) {
        for (int j = 1; j <= len - i; j++)
            putchar(' ');      // 先に空白
        for (int j = 1; j <= i; j++)
            putchar('@');      // 記号は @ に変更
        putchar('\n');
    }

    return 0;
}

実行例

右寄せの三角形を描きます。
高さ: 5
    @
   @@
  @@@
 @@@@
@@@@@

登場する命令(関数)の書式と役割

この章でよく使う命令(関数)

命令(関数)書式何をする?
putsputs(文字列);文字列を表示して改行する。
printfprintf(書式, 値, ...);整形して表示する(入力促しにも便利)
scanfscanf(書式, 変数のアドレス);キーボードから値を読み込む。
putcharputchar(文字);文字を1つ出力する。
breakbreak;そのループを強制終了する。
continuecontinue;その周回の残りを飛ばして次へ進む。

まとめ:多重ループは「描画」「表」「条件制御」に強い

  • 外側=行、内側=列で考えると図形はスッと作れる。
  • break は内側だけを抜ける(外側までは抜けない)
  • continue は残りを飛ばすけど、for の更新(C部)は必ず実行される。

この3点を押さえると、図形描画系の問題はかなり解けるようになります。