条件分岐

問題がとけなかったらそのことを余り気にかけないで、もう少しやさしい問題をとくことで満足しなければならない。即ちまずこれと関連した問題をとこうとするのである。そうすれば又もとの問題を解こうという元気がでてくるにちがいない。人間がすぐれているのは、直接にはこえ難い障害物を迂回し、もとの問題がとけそうもない場合には何か補助の問題を考え出すところにあることを忘れてはならない。

『いかにして問題をとくか』G.ポリア著、柿内賢信訳より引用

あなたの家から近くのコンビニへと向かう道は一つではないだろう。コンビニまでの移動手段も、常に一つとは限らない。徒歩かもしれないし、自転車にのってかもしれない。タクシーを利用するなんてことだってありえないわけではない。雨が降ってきたので、コンビニに行くことを止めたりすることだってありえる。コンビニへ向かう事が目的だとしても、その為の手段は一つではない。目的へ向かう方法がいくつかあり、あなたはその中の一つを選択することになる。

次のプログラムがあるとしよう:

begin
  Writeln('0');
  Writeln('1');
end.

プログラムは begin から始まり、

Writeln('0');

を実行し、その次に

Writeln('1');

を実行してプログラムは終了する。これまでに見てきたプログラムは、その処理過程が全て一本道であった。ここではコンピュータが実行するコードが、何らかの条件によって実行されたり、実行されなかったりするようなコードを見ていく。まずは論理型とはどういうものかについて見ていこう。

型とは、値に共通した特徴を表している形式のことである。整数型の値は 1 とか 221 などの整数だ。論理型の値は 2 つしかない。それは True と False である。次のコードを見てほしい。

begin
  Writeln(10 > 3);
  Readln;
end.
TRUE

実行すると "TRUE" と表示される。これは、

10 > 3

の演算結果が True になったということである。言葉で説明するとこうなる:「 10 は 3 より大きいか?大きいなら True を、そうでないなら False を演算結果として返す」。10 は 3 より大きい。だから True が返される。True や False は 1 や 20 などと同じである。1, 20 の型は整数型であるように、True, False の型は論理型であるということでしかない。

10 > 3

>

は、10 と 3 を比較する演算子であり、とくに関係演算子と呼ばれるものである。

今度は False が返される例をみよう:

begin
  Writeln(12 = 9);
  Readln;
end.
FALSE
12 = 9

は「12 と 9 は等しいか?等しいなら True を、等しくないなら False を返す」ということになる。12 と 9 はもちろん等しくないから、False が返される。

12 = 9

=

は関係演算子だ。"<" と "=" の 2 つの関係演算子をみてきたが、他にもいくつか関係演算子と呼ばれるものがある。それらも含めて、ここで表にまとめておく:

関係演算子 演算
= 等しいか
<> 等しくないか
< より小さいか
> より大きいか
<= 以下であるか
>= 以上であるか

論理型は Boolean で表す:

var
  b: Boolean;
begin
  b := 10 > 3;
  Writeln(b);

  b := 2 <> 2;
  Writeln(b);

  Readln;
end.
TRUE
FALSE

論理型の変数 b には、はじめに 10 > 3 の演算結果すなわち True が代入される。その次には、2 <> 2 の演算結果すなわち False が代入されている。「2 <> 2」は、 2 と 2 が等しくなければ True を、等しければ False が返される。2 と 2 は等しいので、「2 <> 2」は False を返す。

次に、プログラム処理を分岐するコードを見ていく。

begin
  Writeln(0);

  if 10 > 120 then
  begin
    Writeln(1);
  end;

  Writeln(2);

  Readln;
end.
0
2

次の部分に注目しよう:

if 10 > 120 then
begin
  Writeln(1);
end;

の部分は、次のように見る:

if 「論理型の値」 then
begin
  「文」
end;

「論理型の値」が True であれば、「文」は実行される。「論理型の値」が False であれば、「文」は実行されない。もう一度元のコードをみよう。

if 10 > 120 then
begin
  Writeln(1);
end;

「論理型の値」に相当するのは

10 > 120

である。そして「文」に相当するものは

Writeln(1);

である。

10 > 120 

が返す値は False であるから、「文」に相当する部分すなわち:

Writeln(1);

は実行されない。

別の例をもう一つみよう:

begin
  Writeln(0);

  if 120 > 10 then
  begin
    Writeln(1);
  end;

  Writeln(2);

  Readln;
end.
0
1
2
if 120 > 10 then
begin
  Writeln(1);
end;

の部分に注目する。今度は「論理型の値」に相当するものは

120 > 10

であり、「文」に相当するものは

Writeln(1);

である。

120 > 10

は True を返すから、「文」に相当するプログラムは実行される。すなわち:

Writeln(1);

は実行されるということになる。

ある条件によって実行したいコード、実行したくないコードがあるとき、上でみたように if 文を使う。新しい概念に慣れるには、とにかく沢山サンプルをみたり、自分でコードを書いたりするのが一番だ。条件分岐は難しくない。難しく感じたのなら、それは単に見慣れていないからなのであって、難しいからじゃない。サンプルをみて、そして自分でコードを書こう(掲載されているコードを、ちょっと自分なりに書き換えたりしながら実行してみると、あなたの理解度は指数関数的に上がる)。

文章で表したものをプログラムに書き下す作業をしていくことにする。まず最初は簡単な例から:

begin
  if 2 < 10 then
  begin
    Writeln(2);
  end;

  Readln;
end.
2

どうやらうまくコード化できたようだ。ようし、次の例を試してみよう。

begin
  if 2 = 2 then
  begin
    Writeln(10);
  end;

  Readln;
end.
2

これもうまくいった。どんどんいこう、今度は、

begin
  if 4 > (20 - 21) then
  begin
    Writeln(4);
  end;

  Readln;
end.
4

だいたいの感じがつかめたと思う。次は少し難しくなる。

begin
  if 2 > 20 then
  begin
    Writeln(20);
  end
  else
  begin
    Writeln(2);
  end;

  Readln;
end.
2

上のコードの中の次の部分はひとかたまりだと考えるように:

if 2 > 20 then
begin
  Writeln(20);
end
else
begin
  Writeln(2);
end;

これを図で表すとこうなる:

この図で注目すべき点は一つしかない。それはプログラムの処理が分岐されているということである。ひし形の図形に注目しよう。2 つの矢印が伸びているのが分かる。どっちの矢印に進むかは、ひし形の中に書かれている条件の結果による。その結果が True なら

Writeln(20);

を実行する方向へ進み、Falseなら

Writeln(2);

へと進む。条件は

2 > 20

であるから、その演算結果は False となり、結果として

Writeln(2);

が実行されることになる。

次のコードが、条件分岐を理解する山場となる。

begin
  if 2 > 20 then
  begin
    Writeln(2);
  end
  else if 2 = 2 then
  begin
    Writeln(4);
  end;

  Readln;
end.
4

このコードを図で表したのが下図だ。

ひし形が 2 つに増えている。コードを見ると if も 2 つあることに注目しよう。図を見ながら、矢印を順にたどっていくことにしよう。まず最初の矢印の先にはひし形の図形がある。

2 > 20 

という条件より、False の矢印へ進む。そうすると、またひし形の図形にたどり着く。そのひし形には

2 = 2

となっているから、True の矢印へ進む事になり、結果として

Writeln(4);

が実行されるというわけだ。

上のコードと図が理解できたなら、次のコードも簡単だ。次に示すコードと図が、上のコードと図と比べて、どこが変化しているかに注目してみよう。

begin
  if 2 > 20 then
  begin
    Writeln(2);
  end
  else if 2 = 2 then
  begin
    Writeln(4);
  end
  else if 3 <> 2 then
  begin
    Writeln(3);
  end;

  Readln;
end.
4

ひし形と、プログラムの if が対応している。ひし形が 3 つあれば、if も 3 つある。ひとつまえの図でやったように、最初の矢印から順に辿っていけば、それがプログラムの実行過程となる。

最後に else 節をみていく。if における条件が全て False になるときに実行したいコードは else 節に書く。

begin
  if 2 > 20 then
  begin
    Writeln(2);
  end
  else if 2 = 2 then
  begin
    Writeln(4);
  end
  else
  begin
    Writeln(3);
  end;

  Readln;
end.
4

else は楕円で表している。if による条件の結果が全て False であるときに else にたどり着くのが読み取れる。たとえば、次のコードは else 節のコードが実行される。

var
  x: Integer;
begin
  x := 120;

  if x < 10 then
  begin
    Writeln('10');
  end
  else if x < 100 then
  begin
    Writeln('100');
  end
  else
  begin
    Writeln('x >= 100');
  end;

  Readln;
end.
x >= 100

一番はじめに示したコードにも、次のように else があった:

begin
  if 2 > 20 then
  begin
    Writeln(20);
  end
  else
  begin
    Writeln(2);
  end;

  Readln;
end.
2

このコードを改めて図で表すと次のようになる:

さて、これからはこの条件分岐のことを if 文と呼ぶことにする。if 文での beginend の使い方をみていこう。

begin

  if 2 = 2 then
  begin
    Writeln(10);
  end;

  Readln;
end.
10

if 文に注目しよう:

if 2 = 2 then
begin
  Writeln(10);
end;
2 = 2

は True となるから、

 Writeln(10);

が実行される。このコードでは if の beginend は省略できる。だから次のように書いても同じだ:

begin

  if 2 = 2 then
    Writeln(10);

  Readln;
end.
10

if において実行される文がたったの一つだけであれば、beginend は省略できる。実行される文が複数なら beginend は省略できない。たとえば、次のようなコードを考えて見よう。

整数型の変数 x の値が 10 以下であれば、

Writeln('foo');
Writeln('bar');

を実行する。

これは、次のように書くことができる。

var
  x: Integer;
begin
  x := 4;

  if x <= 10 then
  begin
    Writeln('foo');
    Writeln('bar');
  end;
  
  Readln:
end;
foo
bar

if 文の beginend を省略したらどうなるか試してみよう。

var
  x: Integer;
begin
  x := 4;

  if x <= 10 then
    Writeln('foo');
    Writeln('bar');
  
  Readn;
end.
foo
bar

実行結果は省略前と変わっていない。しかし、条件部分の値を変えてみると本質的なものが見えてくる:

var
  x: Integer;
begin
  x := 100;
  
  if x <= 10 then
    Writeln('foo');
    Writeln('bar');

  Readln;
end.
bar

お分かりになっただろうか。これは、if の beginend を省略しないで書くとすれば、次のコード:

var
  x: Integer;
begin
  x := 100;
  
  if x <= 10 then
    Writeln('foo');
    Writeln('bar');

  Readln;
end.

これは、次のコードと同じ意味になるということなんだ:

var
  x: Integer;
begin
  x := 100;

  if x <= 10 then
  begin
    Writeln('foo');
  end;

  Writeln('bar');

  Readln;
end.
bar

if の beginend はそこで実行する文が一つであるときに限って省略できる。実行する文が複数あるなら beginend は省略してはいけない。

別に begin と end を、どんなときも省略せずに書いていれば、上のような間違いをおかすことはないが、普通は begin と end は(省略できる時は)省略する。なぜ省略するのか、それはタイプ数が節約されるのと、プログラムが見やすくなるためだ。begin と end を省略できるときに、それを省略するのは、ちょうど「セントラル・リーグ」のことを「セ・リーグ」と呼ぶのに似ている。セ・リーグと言ったとしても、それが何のことか分かるし、とにかく短いことが利点になる。もちろん、略さずにセントラル・リーグと言っても構わない。だけど、みんな「セ・リーグ」って言ってるでしょ。if 文における begin と end の省略もそれといっしょの感覚だと思う。

最後に if 文を使った簡単なプログラムをみていきたい。次のコードは、変数 Money の値に応じて出力メッセージが変化するプログラムである。

var
  Money: Integer;
begin
  Money := 300; // 所持金を代入する

  if Money < 10 then
    Writeln('あめ玉を買いました')
  else if Money < 500 then
    Writeln('ジュースを 2 本買いました')
  else if Money < 5000 then
  begin
    Writeln('漫画本を買いました');
    Writeln('ジュースを 5 本買いました');
  end
  else if Money < 10000 then
    Writeln('プラモデルを買いました')
  else
  begin
    Writeln('テレビを買いました');
    Writeln('ノートパソコンを買いました');
    Writeln('バイクを買いました');
  end;

  Readln;
end.
ジュースを 2 本買いました

if の begin と end に注目しよう。どんなときに begin と end を省略しているのか、あるいは省略していないのか。変数 Money には所持金を代入している。所持金をいろいろ変えてプログラムを実行すると面白いし、コードをよく理解できると思う。また、セミコロンにも注意しよう。else の直前にセミコロンを置くと文法エラーになる。

begin
  if 2 = 2 then
    Writeln(2) // セミコロンはおかない
  else
    Writeln(33);

  Readln;
end.
2

ここでは条件分岐についてみてきた。条件分岐と、(これから学ぶ)ループと関数定義の仕方が出来るようになれば、ある程度のプログラムは自分で書けるようになる。


up next

更新日:2004-12-20