多重ループ

繰り返しを繰り返す


もちろん、ループ内でもループを書ける。

for ( /* ~ */ ) {
  for ( /* ~ */ ) {

  }
}

これを 二重ループ とか、更に何個も連ねるのを 多重ループ とかいう。

外側で 10 回、内側で 10 回繰り返すと、10 × 10 = 100 回繰り返す。

外側で N 回、内側で M 回繰り返すと、N × M 回繰り返す。

以下、よくやる使い方を紹介しておく。

二つの値の組み合わせをすべて網羅する場合

ここでは、与えられた半径 radius に対して、その半径の円の中に、中心から敷き詰めた正方形のタイルの数を数えてみる。

タイルと円

double radius = 1.42; // 約 √2、標準入力でもいいけど今回は決め打ち
int count = 0;
int limit = radius + 0.5;
// まず X と Y が + の方向の点だけ数える
for (int x = 1; x <= limit; ++x) {
  for (int y = 1; y <= limit; ++y) {
    if (x * x + y * y < radius * radius) { // 円の方程式 x^2 + y^2 < r^2 をしている
      ++count;
    }
  }
}
// 4 倍にする
count = count * 4 ;

一応この例では、x のループの中に y のループを書いてもいいし、y のループの中に x のループを書いてもいい。

複数行に渡って、パターンを画面に出力する場合

一行ずつに着目して考えると良い。

今回は、"#" を黒点、" " を白点として、画面に半径 radius の円を描いてみる。

今の行の y 座標がわかっていると仮定しよう。これはあとで追加する 外側の for ループ の制御変数だよ。

x 座標を増やしていくループを書く。

for (int x = -radius; x <= radius; ++x) {
  // x^2 + y^2 <= r^2
  if (x * x + y * y <= radius * radius) {
    std::cout << "#";
  } else {
    std::cout << " ";
  }
}

こんな感じの一行を考えたら、それを繰り返す場合を考える。

for (int y = -radius; y <= radius; ++y) {
  // ここは一行の処理が始まる前
  for (int x = -radius; x <= radius; ++x) {
    // x^2 + y^2 <= r^2
    if (x * x + y * y <= radius * radius) {
      std::cout << "#";
    } else {
      std::cout << " ";
    }
  }
  // ここは一行の処理が終わった後
  // この改行を忘れないように
  std::cout << "\n";
}

行を繰り返すので、外側の for はこれだけ。

これで完成。実行してみると、きれいな円 が見られるはず。他にもいろいろやってみてね。

この場合は、ループの内側と外側を逆にしたりはできない。

横方向 (行) の出力を縦に繰り返しているからね。

順序を逆にするわかるけど、表示が崩れちゃう。

多重ループのときの break

多重ループしたときの break は、その直近、つまり内側のループしか抜けられないので注意。

while (true) {
  while (true) {
    break;
  }
  // break したらここに来る
}
// このままだと無限ループだぁ

外側のループとかを抜ける方法は次の章でやるよ。

そういう処理はただのループでは向いてないはずだからね。