プログラムを作成する場合、単に「命令を順番に実行するだけ」ということはあまりありません。さまざまな状態に応じて必要な処理を行えるようにしなければいけないでしょう。こうした場合に重要になるのが「制御構文」です。制御構文とは、文字通り実行していく処理を制御するための構文です。これは大別して「条件分岐」と「くり返し」の2つからなると考えて良いでしょう。
条件分岐は、ある条件を設定しておき、これの結果に応じて実行する命令などを変更するというものです。これには2つの構文が用意されています。
・if文について
一番の基本でありもっとも多用されるのが「if文」と呼ばれるものです。これは、以下のような形をしています。
if 条件となるもの then |
・・・正しい時に実行する命令・・・ |
else |
・・・正しくない時に実行する命令・・・ |
これが、if構文の基本形です。 グリーンとなる部分は必須の部分で、必ず記述します。ピンクの部分はオプションで、必要ならば記述し、特にいらなければ省略できます。
正しい時に実行する命令、および正しくない時に実行する命令は、基本的に「1つの命令だけ」が記述されます。が、もちろん複数の命令を実行したい時もあるでしょう。そんなとき、Delphiでは命令の最初と最後に「begin」と「end」を記述します。こうするとbegin〜endまでが1つの文のように扱われるのです。
・・いや、今まで「Delphiでは・・」なんて当たり前のようにいってきましたけど、正確にいえば「Object Pascalでは」ですね。Delphiでは、Object Pascalという言語を採用しています。ですから、こうした基本的な文法などはDelphiの決まりというより、このObject Pascalの決まりと考えましょう。まだ両者が良く区別できないかも知れませんけど・・。
まぁ、これだけではちょっとわからないでしょうから例を上げておきましょう。例えば「変数Aが0かどうかで異なる値を変数Bに入れる」というようなものを考えてみます。
if A = 0 then B = 1 else B = -1; |
このようになるでしょうか。ここではわかりやすいように改行しましたが、Object Pascalでは、文はセミコロンで終わりになります。つまり、上の文ならば「if A = 0 then B = 1 else B = -1;」というように、1行で書いてしまってもかまわないんです。あくまで「最後に;をつける」ということさえしっかり守れば、途中の改行は好きにやってかまいません。
もう一つ、「複数の命令」を実行する例もあげておきましょう。この場合には、beginとendをつけるので、ちょっと感じが変わってきます。
if A = 0 then begin B = 1; C = 100; end else begin B = -1; C = -100; end; |
良く見ると、基本的な形は変わってないことがわかりますが、ずいぶんと厳めしいソースコードになりますね。同じif文でも、このようにbegin〜endをつけるだけで雰囲気が変わってきます。早く、これらの変化に慣れておきましょう。
・begin〜endとセミコロンのルールについて
Delphiを使いはじめて最初に戸惑うのが、このObject Pascal特有の「セミコロン」と「begin〜end」の使い方でしょう。「なぜここにセミコロンをつけてこっちは付けないのか」とか「なぜここでbegin〜endを書いてここでは書かなくていいのか?」ということで頭を悩ませることは多いものです。
これは、基本となるルールが頭に入ってないで「なんとな〜くソースコードを書いている」と、はまってしまう罠なんです。Pascalという言語は、非常に厳格な構文になっているので、なによりもまず書き方の基本ルールをしっかり叩き込んでおく必要があります。begin〜endとセミコロンについては、以下のことをよっく理解しておいて下さい。
・セミコロンは、どんなに長くても1つの文では最後に1つつけるだけ!
例えば、上のif文は何行にも渡って書かれていますが「1つの文」なのです。私たちは、つい「改行すると文は終わり」と思ってしまいがちですが、何行あってもPascalの世界では1つの文です。ですから、最後にセミコロンをつけるだけで、それ以外にはつけないんですね。・ begin〜endの中は、別世界だ!
begin〜endで括られた中は、別世界なのだと考えて下さい。この中にいくつの命令が書いてあっても、それは「begin〜end」という1つの文なのです。例えば、上のifの例では、elseの前にあるendにはセミコロンがありませんね? ところが、その中では1つ1つの文の終わりにセミコロンがついています。「なんでだ?」と思う人は多いでしょう。if文は、全体で1つの文ですから、途中にはセミコロンは絶対につきません。begin〜endの内部は、「別世界」なので、その内部だけは1つ1つの文の末尾にセミコロンをつけていくつもの文が書けるんです。
・条件となる式について
ifでは、まず条件となるものを設定し、それによって処理を制御します。この「条件」となるものは、すべて「正しいか、そうでないか」という形で判断できるものだ、ということを理解して下さい。これには、大きく分けて以下の2つのようなものが使えるでしょう。
・値を比較する式
これがもっとも多用されるでしょう。「AとBは正しい」とか「AはBより大きい」とかいった、2つの値を比較する式です。Object Pascalでは、このために以下のような記号が用意されています(すべてAとBの2つの値を比較する形で記述してあります)。A = B(AとBは等しい) A <> B(AとBは等しくない)
A < B A <= B A > B A >= B・真偽値の値
もう1つ多用されるのが「真偽値」です。前に登場したBooleanってやつですね。これはTrueとFalseの二者択一の値です。この値を収めた変数とか、真偽値のプロパティなどは、そのまま条件として使えます。Trueならばthen以降を実行し、Falseならelse以降を実行するようになるんです。
・case文について
もう1つの条件分岐が、case文と呼ばれるものです。これは、ちょっとifよりもややこしい感じです。基本形は、以下のような形になるでしょう。
case チェックする値 of |
値1 : ・・・実行する命令・・・; |
値2 : ・・・実行する命令・・・; |
・・・必要なだけ続ける・・・ |
else |
・・・それ以外の場合・・・ |
end; |
グリーンのところが必須の部分です。ブルーの部分は、必要に応じて記述していくところで、ピンクの部分は例によってオプション(いらないなら書かなくていい)です。
caseは、「case 値 of」と記述された値(変数とかプロパティだね)をチェックし、その値の部分にジャンプする働きをします。ジャンプする先は「値 : 実行する命令;」というように、値の後にコロンをつけ、その後に命令を書きます。重要なのは「この値ごとにジャンプする部分は、1つの文である」ということです。つまり、最後にセミコロンをつけるのです。最後の「else 〜」ももちろん1つの文です。ここがifと違うところですね。つまりcase文は、「case 〜」から「end;」までの間に、必要に応じていくつもの文を組み込んだ形をしているわけです。
各値の文では、原則として1つの命令しか実行できません。が、ifの時と同様に、begin〜endを使って複数の文を書くこともできます。また、このcaseで使える値のタイプは、整数やキャラクタといった限られたものだけで、テキストや実数などは使えません。もちろん、値以外のもの(式とか比較の記号とかね)を使ってジャンプすることもできません。まぁ、慣れない内は「ジャンプ先には整数しか使えない」と思っておきましょう。
では、これも簡単な例を上げておきましょう。やはり変数Aの値によって、異なる値を変数Bに代入するようなものを考えてみましょう。
case A of 0: B := 0; 1: B := 10; 2: B := 100; else B := -1; end; |
基本形がわかれば、そう難しいものではありませんね? これで、Aの値が0ならば「0:〜」という文にジャンプしてそれだけを実行し、構文を抜けるようになるわけです。ついでですから、複数の文を実行する例も上げておきましょうか。
case A of 0: begin B := 0; C := 0; end; 1: begin B := 10; C := 2; end; 2: begin B := 100; C := 4; end; else begin B := -1; C := -1; end; end; |
これもbegin〜endをよく見れば、やっぱり基本形と同じく「値ごとに1つの文を書く」という形になっていることがわかるでしょう。 わかりやすく細かく改行しているので全体の仕組みが見やすいと思いますが、もちろん改行しないで書いてもかまいません。
このcase文は、割と使い方が限定される感じがあるので、「基本はif、状況によってはcaseもあり得る」という程度に考えておけばいいでしょう。ifだけで、caseと同じこともできるんですから。まずifを完璧に使いこなせるようになりましょう。
では、もう1つの制御構文である「くり返し」に進みましょう。繰り返しは、文字通り「命令を必要なだけくり返す」ためのものです。が、もちろん「永遠にくり返し続ける」わけではありません。必要に応じてくり返し、必要がなくなったら先へ進むわけです。この「どうやって『まだくり返すよ』ということを教えるか」によって、いくつかの繰り返し構文が用意されています。
・for文について
繰り返しのもっとも基本となるのが、このfor文です。これは、数字を使って繰り返し回数をチェックし、それによってくり返すかどうかを決めよう、という方式です。この基本形を整理すると以下のようになります。
for 変数 := 初期値 to 終了値 do |
・・・くり返し実行する命令・・・ |
for 変数 := 初期値 downto 終了値 do |
・・・くり返し実行する命令・・・ |
2つありますが、どちらも基本は同じです。――この構文では、繰り返し回数をチェックするための専用の変数を1つ用意する必要があります。これは整数のタイプの変数で、プロシージャの最初のvar部分で使用宣言しておかないといけません。これはよく忘れるので注意して下さい。また変数名は、昔から「i」「j」「k」というように、iから始まる1文字のアルファベットを使うのが一般的です。別に、そうする必要はないんですが、こう決めておくと変数名を見ただけで「これは繰り替えし用だな」ってわかりますから便利なんですよ。
この構文では、最初に変数に初期値の値を代入します。そしてdoの後にあるくり返す命令を実行すると、再びfor部分に戻り、変数の値を1増やします。2番目の「downto〜」の方は、1減らします。そうして繰り返しを実行しては最初に戻って変数を1増減し・・というのをくり返していき、変数の値が終了値より大きくなったら、そのまま構文を抜けて先へと進みます。・・例えば「for i := 1 to 5」ならば、最初に変数iに1を代入し、iの値が5になるまでは繰り返しをします。そして6になったら(終了値より大きいので)繰り返しは実行せず先へ進むのです。
A := 0; B := 1; for i := 1 to 10 do begin A := A + i; B := B * i; end; |
例えば、これは1〜10までの全ての整数を足した値と、かけた値を計算するものです。forの後に、例によってbegin〜endを使って複数の命令を設定してあります。for文を使うと、決まった回数をくり返すだけでなく、 このように「○○から××まで順番に何かをする」というようなこともできるんですね。
・while文とrepeat文について
forは、変数の値をチェックして実行していましたが、この方式では、繰り返しに入る段階で、何回繰り返すかがわかっていないといけません。「くり返している時に状況に応じてくり返すかどうか決める」 というように、回数ではなく状況に応じて繰り返しをきめる方式の構文が「while文」と「repeat文」です。
これら2つは別々の構文ですが、基本的な働きが似通っていますので、一緒に覚えておくのが良いでしょう。構文の基本形を以下に示しておきます。
while 条件となるもの do |
・・・くり返し実行する命令・・・ |
repeat |
・・・くり返し実行する命令・・・; |
・・・いくつでも文が書ける・・・ |
until 条件となるもの |
どちらも、条件となるものを設定し、それが成立する間は繰り返しを続け、成立しなくなったら抜け出す、という働きをします。似ていますけど、細かな点が違いますね?
まず、while文では、最初に条件となるものを指定しますが、repeatでは最後に指定をします。つまり、最初と最後のどちらで条件をチェックするか、という違いですね。どっちでも似たようなものだと思うでしょうが、厳密には違います。もし、くり返す条件が最初から成立しなかった時、whileでは繰り返し部分を全く実行せずに先へ進みますが、repeatでは1度実行して先へ進むのです。repeatは繰り返し部分を実行した後で条件をチェックしますから、例え最初から条件が成立しなくとも、必ず1度は実行するんですよ。
また、whileはforなどと同様に実行する文は1つだけです。複数実行する場合にはbegin〜endを使う必要があります。これに対してrepeatは、repeat〜until間にいくらでも文を書くことができます。ですから、begin〜endを使う必要はありません。
A := 0; B := 1; i := 1; while i <= 10 do begin A := A + i; B := B * i; i := i + 1; end; |
簡単な例をあげておきましょう。これは、先ほどの「1〜10までの全ての数字を加算・積算する」というサンプルを、forでなくwhileを使って書き直したものです。whileで「i <= 10」が正しいかチェックし、これが成立しなくなったら(つまり10より大きくなったら)繰り返しを抜けます。先ほどの例と比べてみると、whileの働きがよくわかりますよ。
・・今回は、Delphiはほとんど使わず説明をしてきました。これらの基本構文は、実際にソースコードを書く上で基本中の基本となるものですから、確実に覚えておくようにして下さい。もし「全部一度に覚えられない」という人は、とりあえず「if文」と「for文」の2つだけしっかり覚えましょう。これで、当分はなんとかなるはずですから。