問題がとけなかったらそのことを余り気にかけないで、もう少しやさしい問題をとくことで満足しなければならない。即ちまずこれと関連した問題をとこうとするのである。そうすれば又もとの問題を解こうという元気がでてくるにちがいない。人間がすぐれているのは、直接にはこえ難い障害物を迂回し、もとの問題がとけそうもない場合には何か補助の問題を考え出すところにあることを忘れてはならない。
『いかにして問題をとくか』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 文での begin
と end
の使い方をみていこう。
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 の begin
と end
は省略できる。だから次のように書いても同じだ:
begin if 2 = 2 then Writeln(10); Readln; end.
10
if において実行される文がたったの一つだけであれば、begin
と end
は省略できる。実行される文が複数なら begin
と end
は省略できない。たとえば、次のようなコードを考えて見よう。
整数型の変数 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 文の begin
と end
を省略したらどうなるか試してみよう。
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 の begin
と end
を省略しないで書くとすれば、次のコード:
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 の begin
と end
はそこで実行する文が一つであるときに限って省略できる。実行する文が複数あるなら begin
と end
は省略してはいけない。
別に 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
ここでは条件分岐についてみてきた。条件分岐と、(これから学ぶ)ループと関数定義の仕方が出来るようになれば、ある程度のプログラムは自分で書けるようになる。
更新日:2004-12-20