ループ--文を繰り返し実行すること

何度も何度もやってみる。そして少数の都合のよい可能な場合を見逃さないように、試行を変えることである。(中略)また試行の失敗からより多くのことを学ぶ事ができるのだ。

『数学の問題の発見的解き方』George Polya著、柴垣和三雄、金山靖夫訳より引用

ループとはなんだろうか。ためしに辞書で引いてみると、そのものずばりの説明がある:

具体的なコードを見ていこう:

var
  i: Integer;
begin
  for i := 0 to 2 do
  begin
    Writeln('Gold');
  end;

  Readln;
end.
Gold
Gold
Gold

このコードから、まず読み取ってほしいことは、

Writeln('Gold');

が 3 回実行されるということだ。なぜ(4 回ではなく) 3 回なのだろうか。

次のコード:

for i := 0 to 2 do
begin
  Writeln('Gold');
end;

このコードは Writeln('Gold'); を 3 回実行した。もし、これを 5 回実行したいとすると、どこを修正したらよいか分かるだろうか?2 通りの修正の仕方がある。これからそのコードを示すが、いったんここで本文を読むのを止めて、ぜひあなた自身で見つけてほしい。

1 つは次のようになる:

var
  i: Integer;
begin
  for i := 0 to 4 do
  begin
    Writeln('Gold');
  end;

  Readln;
end.

もう 1 つは次のように:

var
  i: Integer;
begin
  for i := -2 to 2 do
  begin
    Writeln('Gold');
  end;

  Readln;
end.

for 文は次のようにみる:

for <カウンタ> := <初期値> to <終値> do
begin
  <文>
end;

ループする回数は、「<終値> - <初期値> + 1」となる。<カウンタ> には「<初期値> + それまでにループした回数」が格納される。<カウンタ> の値を表示させるプログラムを書いてそれを確かめよう。

var
  i: Integer;
begin
  for i := 0 to 5 do
  begin
    Writeln(i);
  end;

  Writeln('---');

  for i := 4 to 6 do
  begin
    Writeln(i);
  end;
  Readln;
end;
0
1
2
3
4
5
---
4
5
6

あなたへの課題:

  1. 一回だけループする for 文を書いてください
  2. 一回もループしない for 文を書いてください

for 文も if 文同様、実行する文が一つだけの場合に限って、beginend を省略できる:

var
  i: Integer;
begin
  for i := 0 to 2 do
    Writeln('foo');

  Readln;
end.
foo
foo
foo

配列の要素を全て表示するには for 文を使うと簡単になる。for 文を使わないと次のようなコードになるが、

var
  Ary: array[0..3] of Integer;
begin
  Ary[0] :=  0;
  Ary[1] := 10;
  Ary[2] := 20;
  Ary[3] := 30;

  Writeln(Ary[0]);
  Writeln(Ary[1]);
  Writeln(Ary[2]);
  Writeln(Ary[3]);
  
  Readln;
end.
0
10
20
30

for 文を使うと、こうなる:

var
  Ary: array[0..3] of Integer;
  i: Integer;
begin
  for i := 0 to 3 do
    Ary[i] := 10 * i;

  for i := 0 to 3 do
    Writeln(Ary[i]);

  Readln;
end.
0
10
20
30

Low 関数と High 関数を使えば、配列の下限値と上限値が得られるので、for 文を次のように書き直すと、まちがいを起こしにくくなる。

var
  Ary: array[0..3] of Integer;
  i: Integer;
begin
  for i := Low(Ary) to High(Ary) do
    Ary[i] := 10 * i;

  for i := Low(Ary) to High(Ary) do
    Writeln(Ary[i]);

  Readln;
end.
0
10
20
30

たとえば、1 から 100 までの整数の合計を計算するコードは for 文で次のように書ける。

var
  i, Sum: Integer;
begin
  Sum := 0;
  for i := 1 to 100 do
    Sum := Sum + i;

  Writeln(Sum);
  Readln;
end.
5050

1 から 10 までの整数の中で偶数を表示させるコードも for 文を使えば簡単に書ける。

var
  i: Integer;
begin
  for i := 1 to 10 do
    if (i mod 2) = 0 then
      Writeln(i);

  Readln;
end.
2
4
6
8
10

あなたへの課題:1 から 10 までの偶数の合計を表示するプログラムを書いてください

for 文を入れ子にして利用すると、九九の表が作れる。

var
  i, j: Integer;
begin
  for i := 1 to 9 do
  begin
    for j := 1 to 9 do
      Write(Format('%2d ', [i * j]));

    Writeln;
  end;

  Readln;
end.
 1  2  3  4  5  6  7  8  9
 2  4  6  8 10 12 14 16 18
 3  6  9 12 15 18 21 24 27
 4  8 12 16 20 24 28 32 36
 5 10 15 20 25 30 35 40 45
 6 12 18 24 30 36 42 48 54
 7 14 21 28 35 42 49 56 63
 8 16 24 32 40 48 56 64 72
 9 18 27 36 45 54 63 72 81

Format は文字列を返す関数である。使用例については、次のサンプルを参考にしてほしい。

という点に注目してコードをみよう。

begin
  Writeln('>>' + Format('%d', [27])    + '<<');
  Writeln('>>' + Format('%10d', [27])  + '<<');
  Writeln('>>' + Format('%-10d', [27]) + '<<');

  Readln;
end.
>>27<<
>>        27<<
>>27        <<

また、次のような三角形を表示させるプログラムも for 文を使えばできる。

o
oo
ooo
oooo
var
  i, j: Integer;
begin
  for i := 1 to 4 do
  begin
    for j := 1 to i do
      Write('o');
    Writeln;
  end;

  Readln;
end.

あなたへの課題:次の三角形を表示させるプログラムを for 文を使って書いてください

o
oo
ooo
oooo
ooo
oo
o

あなたへの課題:次の三角形を表示させるプログラムを for 文を使って書いてください

   o
  ooo
 ooooo
ooooooo

あなたへの課題:次の三角形を表示させるプログラムを for 文を使って書いてください

   o
  o o
 o   o
ooooooo

while 文

ループには for 文のほかに while 文がある。while 文を使って、1 から 9 までの合計を表示するプログラムは次のように書ける。

var
  x, Sum: Integer;
begin
  x   := 1;
  Sum := 0;

  while x < 10 do
  begin
    Sum := Sum + x;
    x := x + 1;
  end;

  Writeln(Sum);
  Readln;
end.
45

while のコードを図示すると次のようになる:

while x < 10 do
begin
  Sum := Sum + x;
  x := x + 1;
end;

while <条件> do
begin
  <文>
end;

<条件> が False を返すとき、ループが終了する。<条件> が True を返すなら <文> が実行され、再び <条件> の判定に戻り、同じ事を繰り返す。

repeat 文

while 文と似たループに repeat 文がある。repeat 文と while 文との違いは一つしかない。それは、ループするかどうかの判定を最初に行うかそれとも最後に行うかだ。

先ほどの while 文のコードを repeat 文に書き直してみよう。

var
  x, Sum: Integer;
begin
  x   := 1;
  Sum := 0;

  repeat
    Sum := Sum + x;
    x := x + 1;
  until x = 10;

  Writeln(Sum);
  Readln;
end.
45

repeat 文を図にすると次のようになる:

repeat
  Sum := Sum + x;
  x := x + 1;
until x = 10;

while 文のところで示した図とどこが違うだろうか。ひし形の図形の位置する場所が変わったのが分かる。

repeat
  <文>
until <条件>

repeat 文では <文> をまず実行する。そして <条件> が True を返すとき、ループは終了する。<条件> が False を返すなら、再び <コード> が実行される。以降同じことを繰り返す。while 文では <条件> が False ならループは終了した。 repeat 文では <条件> が True であればループが終了する。

考えを広げるために:

repeat 文:

repeat
  <文>
until <条件>

とあるとき、<文> がいくつあろうと begin, end は必要としない。つまり、

repeat
begin
  <文>
end
until <条件>

のようには書かない。なぜだろうか。

逆に考えてみよう。if 文や while, for 文では、なぜ begin と end が必要なのだろうか。なぜ while 文などでは、<条件>が True のとき実行される文がたったの一つであれば、begin と end が省略できるのか。

あなたへの課題:次のプログラムは数当てゲームです。このプログラムをエディタに打ち込んで、遊んでみてください。

var
  x, Ans: Integer;
  s: string;
begin
  Randomize;
  Ans := Random(100)+1;

  repeat
    Write('数値を入力して下さい(0で終了):');
    Readln(s);
    x := StrToIntDef(s, 0);
    if x = Ans then
    begin
      Writeln('正解');
      break;
    end
    else if x > Ans then
      Writeln('もう少し下です')
    else
      Writeln('もう少し上です');
  until x = 0;

  Writeln('エンターキーで終了します');
  Readln;
end.
数値を入力して下さい(0で終了):35
もう少し下です
数値を入力して下さい(0で終了):22
もう少し下です
数値を入力して下さい(0で終了):13
正解
エンターキーで終了します

あなたへの課題の解答例

一回だけループする for 文:

var
  i: Integer;
begin
  for i := 0 to 0 do
  begin
    Writeln('Gold');
  end;

  Readln;
end.

一回もループしない for 文:

var
  i: Integer;
begin
  for i := 0 to -1 do
  begin
    Writeln('Gold');
  end;

  Readln;
end.

※上のコードを実行しようとすると、

[ヒント] 一度も実行されない for/while ループがあります - 削除しました

とヒントが表示されるだろう。

1 から 10 までの偶数の合計を表示するプログラム:

var
  i, Sum: Integer;
begin
  Sum := 0;
  for i := 1 to 10 do
    if (i mod 2) = 0 then
      Sum := Sum + i;

  Writeln(Sum);
  Readln;
end.

次の三角形を表示させるプログラム:

o
oo
ooo
oooo
ooo
oo
o
var
  i, j, n, Top: Integer;
begin
  Top := 4; // 三角形の頂上までの "o" の個数 
  for i := 1 to Top * 2 - 1 do
  begin
    if i > Top then
      n := Top * 2 - i
    else
      n := i;

    for j := 1 to n do
      Write('o');
    Writeln;
  end;

  Readln;
end.

次の三角形を表示させるプログラム:

   o
  ooo
 ooooo
ooooooo
var
  i, j, Top, Len: Integer;
begin
  Len := 1; 
  Top := 4; // 三角形の底辺から頂上までの "o" の個数

  for i := 1 to Top do
  begin
    for j := 1 to Top - i do
      Write(' ');

    for j := 1 to Len do
      Write('o');
    Writeln;
    Len := Len + 2;
  end;

  Readln;
end.

次の三角形を表示させるプログラム

   o
  o o
 o   o
ooooooo
var
  i, j, Top, Len: Integer;
begin
  Len := 1;
  Top := 4;

  for i := 1 to Top do
  begin
    for j := 1 to Top - i do
      Write(' ');

    for j := 1 to Len do
    begin
      if i = Top then
        Write('o')
      else if j = 1 then
        Write('o')
      else if j = Len then
        Write('o')
      else
        Write(' ');
    end;
    Writeln;
    Len := Len + 2;
  end;

  Readln;
end.

上のコードの別解として次のコードがあります。

var
  i, j, Top, Len: Integer;
begin
  Len := 1;
  Top := 4;

  for i := 1 to Top do
  begin
    for j := 1 to Top - i do
      Write(' ');

    for j := 1 to Len do
      if (i = Top) or (j = 1) or (j = Len) then
        Write('o')
      else
        Write(' ');

    Writeln;
    Len := Len + 2;
  end;

  Readln;
end.

up next

更新日:2004-12-08