
C言語基礎|多重ループの応用
はじめに:多重ループは「組み合わせる」と一気に強くなるよ
ここまで学んだ多重ループは、for の中に for が入る形が中心でしたよね。
でも実は、繰り返し文は do / while / for の3種類があるので、好きに組み合わせて入れ子にできます。
- 外側は「もう一回やる?」を do で回す。
- 入力チェックは while で粘る。
- 図形や表の出力は for の二重ループで描く。
みたいに役割分担すると、プログラムが読みやすくなって、応用もしやすくなります。

サンプルプログラム:図形を選んで何度でも表示する(多重ループの組み合わせ)
このプログラムは、次の流れです。
- 図形の種類を選ぶ(入力チェックつき)
- サイズを入力する(入力チェックつき)
- 二重ループで図形を描画する
- もう一度やるか聞く(do で繰り返す)
プロジェクト名:chap4-19-1 ソースファイル名:chap4-19-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int main(void)
{
int again;
puts("図形を表示するミニデモを始めます。");
do {
int type = 0;
int size = 0;
/* 図形メニューの入力チェック(while) */
while (type < 1 || type > 2) {
puts("どの図形を表示しますか?");
puts(" 1: 九九表(1〜9)");
puts(" 2: 正方形(# で描画)");
printf("番号を入力: ");
scanf("%d", &type);
if (type < 1 || type > 2) {
puts("その番号は選べません。もう一度入力してください。");
}
}
/* サイズ入力チェック(while) */
while (size < 1) {
printf("サイズを入力(1以上): ");
scanf("%d", &size);
if (size < 1) {
puts("サイズは1以上でお願いします。");
}
}
/* 図形の描画(多重ループ:for の二重ループ) */
if (type == 1) {
puts("九九表を表示します(固定で1〜9)。");
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= 9; j++) {
printf("%3d", i * j);
}
putchar('\n');
}
} else {
puts("正方形を表示します。");
for (int i = 1; i <= size; i++) {
for (int j = 1; j <= size; j++) {
putchar('#');
}
putchar('\n');
}
}
/* もう一度?(do-while で全体を繰り返す) */
printf("続けますか?(続ける:1 / 終了:0): ");
scanf("%d", &again);
} while (again == 1);
puts("おつかれさまでした。");
return 0;
}実行例(イメージ)
- 図形選択を間違えると、while で聞き直し
- size が 1 未満なら、while で聞き直し
- 描画は for の二重ループで一気に出力
多重ループの階層(擬似フローチャート)
do (again)
while (type が 1〜2 になるまで)
入力してチェック
while (size が 1以上になるまで)
入力してチェック
if (type == 1)
for i = 1..9
for j = 1..9
掛け算を表示
else
for i = 1..size
for j = 1..size
# を表示
again を入力
while (again == 1)この擬似フローチャートのポイント
- do-while がいちばん外側で、全体を「もう一回」できるようにしている。
- 入力チェックは while で粘る(条件を満たすまで抜けない)
- 出力処理は for の二重ループが担当(行と列を回して並べる)
多重ループで「行」と「列」を作る感覚
九九表も正方形も、考え方は同じです。
- 外側のループ:行(縦)
- 内側のループ:列(横)
変数 i / j の役割
| 変数 | 役割 | 例 |
|---|---|---|
| i | 行を進める | 1行目→2行目→… |
| j | 1行の中で横に進める | 左から右へ並べる |
登場する命令(関数・文)の書式と役割
「命令が何をするか」「どう書くか」を、ここで整理しておきます。
よく使う命令(関数)と繰り返し文
| 種類 | 名前 | 書式 | 何をする? |
|---|---|---|---|
| 繰り返し文 | for | for (初期化; 条件; 更新) 文 | 回数やカウンタがはっきりした繰り返しに強い |
| 繰り返し文 | while | while (条件) 文 | 条件を満たす間くり返す(入力チェックに便利) |
| 繰り返し文 | do-while | do 文 while (条件); | とにかく1回は実行してから判定する |
| 出力 | puts | puts(文字列); | 文字列を表示して改行する |
| 出力 | printf | printf(書式, 値, ...); | 整形して表示する(数値の桁合わせも得意) |
| 入力 | scanf | scanf(書式, 変数のアドレス); | キーボードから読み込む |
| 出力 | putchar | putchar(文字); | 文字を1つ出力する |
応用のコツ:役割ごとにループを分けると読みやすい
多重ループがごちゃっと見えるときは、次のように「担当」を分けるとスッキリします。
- 外側:全体の繰り返し(もう一回やる?)
- 中:入力の安全確認(入力チェック)
- 内側:出力の本体(表・図形・一覧)
こうすると、あとから機能を追加するのもラクになります。
たとえば、図形を3種類に増やすなら、if を増やすだけで済みます。
名前と識別子:同じ名前があると困るから、区別できる名前が必要
プログラムでは、変数名や関数名など「名前」を使っていろいろ管理します。
ただ、現実の名前は同姓同名があり得ますよね。プログラムで同姓同名が起きると混乱します。
そこで、プログラムの世界では「識別子」という言葉を使います。
識別子は、他と区別できるように付ける名前のことです。
表:名前の付け方のちょいコツ
| 対象 | 良い例 | 理由 |
|---|---|---|
| 図形の種類 | type | 意味が分かる。 |
| サイズ | size | 何の値か即分かる。 |
| 繰り返すか | again | 0/1 の意味が想像しやすい。 |
| ループ用 | i, j | 行と列の定番(短くて見やすい) |
演習問題
演習4-17:見出し付き九九表(横と縦の見出し+区切り線)
横に 1〜9、縦に 1〜9 の見出しを付けた九九表を表示せよ。区切り線も入れること。
解答例
プロジェクト名:chap4-19-2 ソースファイル名:chap4-19-2.c
#include <stdio.h>
int main(void)
{
printf(" ");
for (int j = 1; j <= 9; j++) printf("%3d", j);
putchar('\n');
printf(" ");
for (int k = 0; k < 9 * 3 + 1; k++) putchar('-');
putchar('\n');
for (int i = 1; i <= 9; i++) {
printf("%2d |", i);
for (int j = 1; j <= 9; j++) {
printf("%3d", i * j);
}
putchar('\n');
}
return 0;
}演習4-18:指定サイズの正方形(中が空洞の枠だけ)
一辺 n の正方形を、外枠だけ * で描け。中は空白にすること。
入力例:n=5
出力例:
*****
* *
* *
* *
*****解答例
プロジェクト名:chap4-19-3 ソースファイル名:chap4-19-3.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int main(void)
{
int n;
puts("枠だけの正方形を作ります。");
printf("一辺: ");
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (i == 1 || i == n || j == 1 || j == n) putchar('*');
else putchar(' ');
}
putchar('\n');
}
return 0;
}演習4-19:横長の長方形(小さい方を高さ、大きい方を幅にする)
2つの整数 a, b を読み込み、小さい方を高さ、大きい方を幅として # の長方形を描け。
解答例
プロジェクト名:chap4-19-4 ソースファイル名:chap4-19-4.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int main(void)
{
int a, b;
int h, w;
puts("横長の長方形を作ります。");
printf("辺その1: ");
scanf("%d", &a);
printf("辺その2: ");
scanf("%d", &b);
if (a < b) { h = a; w = b; }
else { h = b; w = a; }
for (int i = 1; i <= h; i++) {
for (int j = 1; j <= w; j++) putchar('#');
putchar('\n');
}
return 0;
}演習4-20:右上が直角の直角三角形(左寄せで上が広い形)
段数 n を読み込み、右上が直角になる三角形を表示せよ。
n=5 の例:
*****
****
***
**
*解答例
プロジェクト名:chap4-19-5 ソースファイル名:chap4-19-5.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int main(void)
{
int n;
puts("右上が直角の三角形を作ります。");
printf("段数: ");
scanf("%d", &n);
for (int i = n; i >= 1; i--) {
for (int j = 1; j <= i; j++) putchar('*');
putchar('\n');
}
return 0;
}演習4-21:ピラミッド(段数 n、中央寄せ)
段数 n を読み込み、ピラミッドを * で表示せよ。
第 i 行目の * の数は (i - 1) * 2 + 1。
解答例
プロジェクト名:chap4-19-6 ソースファイル名:chap4-19-6.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int main(void)
{
int n;
puts("ピラミッドを作ります。");
printf("段数: ");
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int spaces = n - i;
int stars = (i - 1) * 2 + 1;
for (int s = 0; s < spaces; s++) putchar(' ');
for (int k = 0; k < stars; k++) putchar('*');
putchar('\n');
}
return 0;
}演習4-22:下向き数字ピラミッド(各行は同じ数字を並べる)
段数 n を読み込み、上から下へ短くなる数字ピラミッドを表示せよ。
上から i 行目は数字 i を並べる。並べる個数は (n - i + 1) * 2。
n=3 の例:
11 11 (空白なしで 1111 でもOK)
222
33解答例(空白なし版)
プロジェクト名:chap4-19-7 ソースファイル名:chap4-19-7.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
int main(void)
{
int n;
puts("下向き数字ピラミッドを作ります。");
printf("段数: ");
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int count = (n - i + 1) * 2;
for (int j = 0; j < count; j++) {
putchar('0' + (i % 10));
}
putchar('\n');
}
return 0;
}