L - 1.11.for文・break・continue Editorial /

Time Limit: 0 msec / Memory Limit: 0 KB

前のページ | 次のページ

補足

この説明を読む前に付録4.ループの裏技repマクロを読んだほうが理解しやすいです。ただし、必須の知識では無いので読まなくても問題ありません。

キーポイント

  • for文は繰り返し処理でよくあるパターンをwhile文より短く書くための構文
  • 「初期化」→「条件式」→「処理」→「更新」→「条件式」→「処理」→...という順で実行され、条件式が真のとき繰り返し続ける
for (初期化; 条件式; 更新) {
  処理
}
  • N回の繰り返し処理は次のfor文で書くのが一般的
for (int i = 0; i < N; i++) {
  処理
}
  • breakを使うとループを途中で抜けられる
  • continueを使うと後の処理を飛ばして次のループへ行ける

for文

for文は「N回処理する」というような繰り返し処理でよくあるパターンをwhile文より短く書くための構文です。

3回繰り返すプログラムをwhile文とfor文で書くと次のようになります。

#include <bits/stdc++.h>
using namespace std;

int main() {

  int j = 0;
  while (j < 3) {
    cout << "Hello while: " << j << endl;
    j++;
  }

  for (int i = 0; i < 3; i++) {
    cout << "Hello for: " << i << endl;
  }

}
実行結果
Hello while: 0
Hello while: 1
Hello while: 2
Hello for: 0
Hello for: 1
Hello for: 2

for文は次のように書き、条件式が真のとき処理を繰り返し続けます。

for (初期化; 条件式; 更新) {
  処理
}

実行される順序は次のとおりです。

for文のイラスト

はじめのプログラムのfor文が実行される様子を表したのが次のスライドです。

for文 from APG4b

forとwhileの対応関係

for文とwhile文の対応関係を見てみましょう。

int i = 0; // 初期化
while (i < 3 /* 条件式 */ ) {

  cout << "Hello while: " << j << endl; // 処理

  i++; //更新
}
for (int i = 0 /* 初期化 */ ; i < 3 /* 条件式 */ ; i++ /* 更新 */) {

  cout << "Hello for: " << i << endl; // 処理

}

処理される順序はwhile文で書いたときと全く同じで、「初期化」→「条件式」→「処理」→「更新」→「条件式」→「処理」→...という順で実行されます。

while文とfor文は機能面ではほとんど差がありませんが、次の「N回の繰り返し処理」等、for文で簡潔に書ける処理はfor文で書くのが一般的です。

N回の繰り返し処理

for文を使うとき、ほとんどは「N回の繰り返し処理」のパターンです。
動作の細かい部分がわからない人は、とりあえずこのパターンを覚えるところから始めましょう。

for (int i = 0; i < N; i++) {
  処理
}

for文を使うときのコツ

N回の繰り返し処理」のfor文を使うときは、「初期化」「条件式」「更新」の細かい動作を考えないようにしましょう。
よりおおざっぱに、for文はiが1ずつ増えながらN回処理を繰り返す機能と考えた方が、for文を使うプログラムを書きやすくなります。

また、ループでどう書けばよいかわからなくなったときは、まずループを使わずにプログラムを書いてみて、その後ループで書き直すという方法が有効です。
以下の2つのプログラムはその例です。これに関しては2.01.ループの書き方でより詳しく説明します。

ループを使わないプログラム
cout << "hello for :" << 0 << endl;
cout << "hello for :" << 1 << endl;
cout << "hello for :" << 2 << endl;
ループで書き直したプログラム
for (int i = 0; i < 3; i++) {
  cout << "hello for :" << i << endl;
}

breakとcontinue

while文とfor文を制御する命令として、breakcontinueがあります。

break

breakはループを途中で抜けるための命令です。

breakのいらすと

breakを使ったプログラムの例です。

#include <bits/stdc++.h>
using namespace std;

int main() {

  // breakがなければこのループは i == 4 まで繰り返す
  for (int i = 0; i < 5; i++) {

    if (i == 3) {
      cout << "ぬける" << endl;
      break; // i == 3 の時点でループから抜ける
    }

    cout << i << endl;
  }

  cout << "終了" << endl;
}
実行結果
0
1
2
ぬける
終了

if文で i == 3 が真になったとき、break;の命令を実行することでforループを抜け、終了と出力しています。

continue

continueは後の処理をとばして次のループへ行くための命令です。

continueのいらすと

continueを使ったプログラムの例です。

#include <bits/stdc++.h>
using namespace std;

int main() {

  for (int i = 0; i < 5; i++) {

    if (i == 3) {
      cout << "とばす" << endl;
      continue; // i == 3 のとき これより後の処理をとばす
    }

    cout << i << endl;
  }

  cout << "終了" << endl;
}
実行結果
0
1
2
とばす
4
終了

上のプログラムでは、if文で i == 3 が真になったとき、continue;の命令を実行することでcontinueより下の部分を飛ばし、次のループに入ります。


細かい話

細かい話なので、飛ばして問題を解いても良いです。

for文とwhile文の違い

for文とwhile文の違いは主に2点あります。「カウンタ変数のスコープ」と「continueをしたときの動作」です。

カウンタ変数のスコープ

for文のカウンタ変数はwhile文よりスコープが狭くなります。
次の例では、for文のカウンタ変数であるiがスコープの範囲外で使われているため、コンパイルエラーが発生しています。

#include <bits/stdc++.h>
using namespace std;

int main() {

  int j = 0; // jのスコープはmain関数の終わりまで
  while (j < 3) {
    cout << "Hello while" << endl;
    j++;
  }

  for (int i = 0; i < 3; i++) { // iのスコープはforの終わりまで
    cout << "Hello for" << endl;
  }

  cout << j << endl;

  cout << i << endl;
}
コンパイルエラー
In function ‘int main()’:
18:13: error: ‘i’ was not declared in this scope
   cout << i << endl;
           ^

「変数のスコープ」で見たエラーと同じく、‘i’ was not declared in this scope('i'はこのスコープで宣言されていません)というエラーが出ています。

while文で使っている変数jのスコープは6行目からmain関数の終わりまでですが、 for文の「初期化」の場所で宣言している変数iのスコープは、for文の{ }中(12行目から14行目)だけになります。

continueをしたときの動作

while文でcontinueをすると更新処理を飛ばしてしまう事があるので、注意が必要です。
例を見てみましょう。

#include <bits/stdc++.h>
using namespace std;

int main() {

  for (int i = 0; i < 5; i++) {

    if (i == 3) {
      cout << "forとばす" << endl;
      continue;
    }

    cout << "for" << i << endl;
  }

  cout << "for終了" << endl;

  int j = 0;
  while(j < 5) {

    if (j == 3) {
      cout << "whileとばす" << endl;
      continue;
    }

    cout << "while" << j << endl;
    j++;
  }

  cout << "while終了" << endl;
}
実行結果
for0
for1
for2
forとばす
for4
for終了
while0
while1
while2
whileとばす
whileとばす
whileとばす
(無限に続く)

for文のcontinueは先に説明したとおりですが、while文では無限ループになってしまっています。
j == 3のとき、12行目のcontinue;より後を飛ばして次のループに行っていますが、よく見てみるとj++の処理も飛ばされてしまっています。
そのため、変数jの値は永遠に3のままとなり、無限ループになってしまいます。

省略したfor文

for文の「初期化」「条件式」「更新」の部分は、必要が無い場合省略できます。

次のように書いた場合、for文の動作はwhile文と完全に同じものになります。

int i = 0;
for (; i < n;) {
  i++;
}

「条件式」の部分を省略した場合、trueと書いたときと同じ動作になります。
次のプログラムは無限ループになります。

for (int i = 0; ; i++) {
  cout << i << endl;
}

{ } の省略

if文と同様に、for文やwhile文の処理が一文のみの場合も{ }を省略できます。

#include <bits/stdc++.h>
using namespace std;

int main() {

  for (int i = 0; i < 3; i++)
    cout << "Hello!" << endl;

}

for文のネスト

if文と同様、for文とwhile文もネストさせることができます。そのような書き方は多重ループと呼ばれます。
詳しくは2.02.多重ループで説明します。

#include <bits/stdc++.h>
using namespace std;

int main() {

  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      cout << "i: " << i << ", j:" << j << endl;
    }
  }

}
実行結果
i:0, j:0
i:0, j:1
i:1, j:0
i:1, j:1

問題

リンク先の問題を解いてください。

ABCの問題

ここまでの知識だけで解ける問題をAtCoder Beginner Contestから再び紹介します。練習問題だけでは物足りない人は解いてみてください。
「易しめ」と書いてあるものも今までのABCの問題よりも難易度が高いことに注意してください。
解けない場合、2.01.ループの書き方2.02.多重ループを読んでから再挑戦してみてください。

易しめ

難しめ

前のページ | 次のページ