break と continue

ループ処理を行う場合には、for, while, repeat 文を使うことが分かりました。簡単におさらいしますと、for 文はループ制御変数を用いて、ループ実行回数を指定します。while 文はループ開始前に制御条件を評価し、条件が True であれば一連の文が実行されます。そして、再び制御条件を評価し、その結果が False になるまでループが回ります。repeat 文は while 文と似ています。異なるのは、制御条件を評価するタイミングです。while 文では、文を実行する前に制御条件を評価しますが、 repeat 文では、一連の文を実行してから制御条件を評価し、ループ継続かの判断が下されます。

ここでは、ループを途中で終了させる break, 次のループへ制御フローを進める continue を紹介します。

break について

次のサンプルは、for 文で 100 回ループするようになっていますが、一つのループでは、変数 Sum2 の値が 20 を超えたら break を実行するようになっています。break を実行すると、その時点でループが終了します。

procedure TForm1.Button1Click(Sender: TObject);
var
  Sum1, Sum2, i: Integer;
begin
  Sum1 := 0;
  Sum2 := 0;

  for i := 0 to 99 do
  begin
    Inc(Sum1); // Sum1 := Sum1 + 1; と同じ意味
  end;

  for i := 0 to 99 do
  begin
    Inc(Sum2);

    if Sum2 > 20 then
      break;
  end;

  ShowMessage('Sum1: ' + IntToStr(Sum1) + ' Sum2: ' + IntToStr(Sum2));  
end;

実行すると、「Sum1: 100 Sum2: 21」と表示されます。下の方の for 文では Sum2 の値が 20 より大きい場合に break が実行されるようになっています。break を実行した、まさにそこでループが終了するということに留意してください。例えば:

procedure TForm1.Button1Click(Sender: TObject);
var
  Sum1, Sum2, i: Integer;
begin
  Sum1 := 0;
  Sum2 := 0;
  for i := 0 to 99 do
  begin
    Inc(Sum1);
    if Sum1 > 20 then
      break;
    Inc(Sum2);
  end;

  ShowMessage('Sum1: ' + IntToStr(Sum1) + ' Sum2: ' + IntToStr(Sum2));
end;

実行すると、「Sum1: 21 Sum2: 20」となります。break が実行された、その時点で終了です。ループが一回りして、最初に戻ってから終了ということではありません。

break は、日本語では「切断する、壊す」といった感じになります。ループの途中で、そのループを無理やり壊し(終了し)ているような感じですね。

次の例では、while 文で break を使用しています。フォームにリストボックス(ListBox)を貼り付けて下さい(Button と同じ Standard ページにあります)。

procedure TForm1.Button1Click(Sender: TObject);
var
  Sum: Integer;
  AddedValue: Integer;
  LuckyNumber: Integer;
begin
  LuckyNumber := 7; // ラッキーナンバー

  Sum := 0;
  while Sum < 50 do
  begin
    AddedValue := Random(10);
    if AddedValue = LuckyNumber then
      break;

    Inc(Sum, AddedValue); // Sum := Sum + AddedValue; と同じです
  end;

  if Sum < 50 then
    ListBox1.Items.Add('[Lucky] Sum の値は' + IntToStr(Sum))
  else
    ListBox1.Items.Add(' Sum の値は' + IntToStr(Sum));
end;

while 文のループ終了条件を、「変数 Sum の値が 50 以上であるならループ終了」としています。そして肝心の break の所ですが、次のようになっています。

AddedValue = Random(10);
if AddedValue = LuckyNumber then
  break;

まず、AddedValue には、Random 関数から返される値が代入されています。Random 関数は、与えられた引数(ここでは 10)より小さい値(且つ 0 以上)をランダムで返す関数です。すなわち、0 から 9 までの値が AddedValue に代入されます。もし、AddedValue の値が LuckyNumber と等しければ break が実行されます。LuckyNumber には 7 が代入されていますので、AddedValue の値が 7 であれば break が実行されます。

?

プログラムを実行してみてください。リストボックスに表示されるメッセージで、冒頭に "[Lucky]" と付く場合と、付かない場合があります。もし、break が実行されたなら、Sum の値は 50 未満です。しかし、while の制御条件(ループを続行するかの判断)でループ終了の判定がなされたら、Sum の値は 50 以上です。つまり、break が実行された時には、[Lucky] をつけるようにしていたのでした。

ループが入れ子になっている場合の break の動作

ループの中にさらにまたループがある場合、つまり入れ子になっている場合に break を実行したら、どうなるかを見てみましょう。

procedure TForm1.Button1Click(Sender: TObject);
var
  i, j: Integer;
begin
  for i := 0 to 3 do
  begin
    for j := 0 to 5 do
    begin
      ListBox1.Items.Add('( i, j ) = (' + IntToStr(i) + ', ' +
        IntToStr(j) + ')');

      if j = 2 then
        break;
    end;
  end;
end;

実行すると、下図のようになります。

?

ループが入れ子になっている場合、内側のループで break を実行したなら、その内側のループが終了しているのが分かります。

continue

continue はループを次に進めます。

「ループを次に進める」とは、continue が実行された時点で残りの処理(continue より下にある文)を実行せずに、次のループに進むことを指します。

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to 4 do
  begin
    ListBox1.Items.Add('[begin] i->' + IntToStr(i));

    if i = 2 then
      continue;

    ListBox1.Items.Add('[end  ] i->' + IntToStr(i));
  end;
end;

?

実行しますと、上図のようになります。i の値が 2 の場合、ListBox1.Items.Add(''[end ] i->'' + IntToStr(i));が実行されていません。それは、if 文で i が 2 であるなら continue が実行されて、ループの中身をスキップして次の繰り返しに移るためです。

入れ子になっている場合の continue の動作

break の場合と同様に働きます。つまり、内側のループで continue を実行すれば、内側のループに対して continue が適用されます。

procedure TForm1.Button1Click(Sender: TObject);
var
  i, j: Integer;
begin
  for i := 0 to 3 do
  begin
    for j := 0 to 3 do
    begin
      if j = 1 then
        continue;

      ListBox1.Items.Add('i->' + IntToStr(i) + ' j->' + IntToStr(j));
    end;
  end;
end;

実行すると、下図のようになります。

?

j の値が 1 の時は、ListBox1.Items.Add('i->' + IntToStr(i) + 'j->' + IntToStr(j)); が実行されていないことが分かります。


up next
Last Update 2004/08/06