プログラミング言語の文法はさまざまな規則から成り立ってます。そして、プログラムはそれらの規則に厳密に従って作られていて、コンパイラは文法にしたがって書かれたプログラムのみを解釈することができるように作られています。英語やフランス語のような自然言語においては、理解させる相手が人間なので、少々の文法の間違いがあっても理解してもらえますが、プログラムについては理解する相手がコンパイラというプログラムなので、間違いがあっても人間の心を読み取って間違いを訂正してくれたりはしません。そういうわけで、プログラミング言語の学習においては、正確な文法を覚える必要があります。
文法上、プログラムは記号というものを並べたもので表現されます。ここでいう「記号」はPascalの文法用語です。そして、記号同士が隣り合って区別がつかないときや、読みにくくなるときは、記号と記号との間に記号分離子というものを挟むことになってます。
記号は、次の5つのグループに分類されます。
これらのグループのおのおのを順番に説明していきます。
特殊記号 このグループは
+ - * / . , : ; = <> < <= > >= := .. ^ ( ) [ ]
の21個と
and array begin case const div do downto else end file for function goto if in label mod nil not of or packed procedure program record repeat set then to type until var while with
35個、計56個からなる。後者の35個を語記号、もしくは、予約語と呼ぶ。語記号はしばしば下線付きで書いたり
begin
太字で書いたり
begin
する。これは、次に説明する名前と区別するためである。
名前 英字(A〜Z a〜z)と数字(0〜9)からなる文字の列で最初の文字は英字であるようなものが、名前です。具体的には、前で変数名として使った l や m や n は名前になります。また、プログラム名として使ったkantan1も名前です。「変数名」は変数のために使われる名前であり、ここで紹介した名前が満たすべき条件を満たさなければなりませんし、「プログラム名」も同様です。
数 数という記号のグループは、整数という記号のグループと実数とという記号のグループに大別されます。ここでいう「数」、「整数」、「実数」はPascal用語なので注意してください。
整数 次の形をしたものが整数と呼ばれる記号です。
〈符号〉〈数字列〉
但し、〈符号〉は、
+ もしくは - もしくは何も書かないかのいずれか
です。1000や16は、整数ですし、+10 や -12 も整数です。010 や 0035 も、もちろんここでいう整数になります。
実数 これはまだ登場してので、出てきたときに説明します。
文字列 前に説明したとおり、文字の並んだ列をデータとして表現したものです。表記法は、文字の列をクオート「'」で囲んだものです。文字列の中に現れる文字は、Pascal文字セットはもちろん、$や\なども許されます。一般には、ASCII文字セット(教科書23ページ)は、まず問題ありません。漢字や平仮名などが使えるかどうかはコンパイラによってまちまちです。わからないときは使えないと思っておきましょう。また、文字列のなかにクオート自体が含まれるときには、文字列に含まれるクオートは、2つ連続して書くことになっています。たとえば、
can't
という文字の列を表現する文字列は、
'can''t'
と書くわけです。
記号についてざっと見てきましたが、次に記号分離子について説明します。
記号分離子(分離符) 記号分離子は、記号と記号の間において記号と記号を分離するためのものです。また、プログラムの先頭に置くこともできます。記号分離子は次の3種類に大別できます。
注釈とは、プログラムの中にいれておいて、プログラムの説明につかいます。たとえば、
program kantan4(input,output); {kantan4 wa nyuryoku sareta kazu wo 2 bai ni shite shutsuryoku shimasu.} var n : integer; begin read(n); writeln(n*2) end.
というふうに中カッコで説明文「kantan4 wa ... shimasu.」を囲んだものが注釈です。注釈は、
{ 0個以上の閉じ中カッコ以外の文字 }
(上の例のように)注釈の中身は複数行になってもかまいませんし、空白を含んでもかまいません。漢字を含んでよいかどうかは、コンパイラに依存しています。
記号分離子(分離符)の使用法をまとめると次のようになります。
kantan1のプログラムをできる限り、記号分離子(分離符)を使用しないで書いてみなさい。
program kantan1(input,output);begin writeln(1+1) end.
kantan1のプログラムで使用している語記号(予約語)に対して下線を引きなさい。
program kantan1(input,output);begin writeln(1+1) end.
kantan1のプログラムで使用している名前に対して下線を引きなさい。
program kantan1(input,output);begin writeln(1+1) end.
プログラムkantan6思い出してください。
program kantan6(input,output); var m:integer; n:integer; begin read(m,n); writeln(m+n,m-n,m*n,m div n) end.
このプログラムは入力された二つの整数の和、差、積、商を計算してその計算結果を画面に出力するというものでした。ほとんどの整数でうまく動作するのですが、ただ、二つ目の整数が0であったとき、このプログラムは、「整数÷0」を計算してしまうことになってしまいます。整数について通常、数学では0による割り算は定義されていませんでした。このプログラムを実行して、二つ目の整数を0として入力すると次のようになります。
sino% pc kantan6.p …コンパイル sino% kantan6 …機械語プログラムの実行 10 0 …整数10と整数0を入力する。 libm-290 : UNRECOVERABLE …エラーlibm-290:復旧不能 Scalar integer value divided by a scalar integer zero. …スカラー整数値がスカラー整数0により割り算された。 Abort (core dumped) …実行中断(コアがダンプされました) sino%
この実行結果からわかることは、プログラムが実行中に異常終了していることです。通常プログラムは実行時エラーを出さないように作らなければなりません。四則演算をするプログラムにおいては、割る数として0を入力されてしまうと、それに対して、商を計算することはできません。このような場合は割り算を計算するまえに、割る数が0でないかチェックしておいて、0ならば割り算を計算しないようにプログラムを作っておくべきなのです。このことを踏まえると次のようにプログラムを変更することも考えられます。
program kantan9(input,output); var i,j,s,d,p,q:integer; begin read(i,j); if j = 0 then writeln(i,i,0,'?') else writeln(i+j,i-j,i*j,i div j) end.
その9のプログラムは、整数10と0とを入力すると、「10 10 0 ?」と1行だけ出力するというものでした。この出力の後に、「The second input integer should not be zero.」(二番目に入力される整数は0であってはならない)という文を次の行に出力したいときには、
program kantan10(input,output); var i,j,s,d,p,q:integer; begin read(i,j); if j = 0 then begin writeln(i,i,0,'?'); writeln('The second input integer should not be zero.') end else writeln(i+j,i-j,i*j,i div j) end.
とすればよいのです。ここででてきた新しい事柄は、
if <式> then begin <文> ; <文> end else <文>
というbegin ... endという部分を含んだ形のif文です。
begin <文> ; <文> ; <文> ; <文> ; <文> end
は複合文と呼ばれる文です。この複合文の実行とは、内側にある文を左から順番に実行するということを意味します。これは実行文部と同じ形で、同じ意味をもっています。if文のelseのところに複合文を置くことはもちろんできますし、複合文の内部に更に複合文をおくこともできます。
if <式> then <文> else begin <文> ; <文> end
begin <文> ; begin <文> ; <文> end ; <文> ; <文> ; <文> end
次に実数の取り扱いについてみていくのですが、前の部分で紹介した、二つの整数の最大値を表示するプログラムkantan8を変更してみました。これは、二つの実数の最大値を表示するプログラムです。
program kantan11(input,output); var x,y:real; begin writeln('Please input two real numbers'); read(x,y); if x>y then writeln(x) else writeln(y) end.
kantan8とkantan11との違いは、
ということです。本質的に新しい事柄は
などがあります。実数というデータの種類を表現する型として、Pascalでは実数型が提供されています。その型名はrealです。実数型の変数の宣言の仕方は、整数型の変数の場合と同様です。
整数型の式の間で可能であった、実数型の式と実数式との大小比較も可能です。
例:x < y や x <> y + zなど
整数型の式の間では、加減乗除の演算ができましたが、実数型の式の間でも、加減乗除の演算が用意されています。但し、割り算については、別の記号「/」を用います。
例:x+y x-y x*y x/y
その他、sin(x)をはじめとして、いろいろな関数があらかじめ用意されていますが、それらについては後で紹介します。心得ておいてほしいこととしては、Pascalの世界では、整数型のデータと実数型のデータとは基本的には別物としてみなされているということです。
従って、Pascalでは整数の「いち」と実数の「一」とは異なる表わし方をします。整数は「1」と書きますが、実数では「1.0」というふうに書いて区別します。
ここまでの知識で、入力された五つの正の実数の最大値を出力するというプログラムを作成することができます。プログラムを作る前に考えておかなければならないこととして、五つの実数がすべて負であったときのことですが、そのときには最大値を0とすることにします。この仮定は若干作為的ですが、教科書の例題1.2に倣って定めました。
program kantan12(input,output); var x,max:real; begin max := 0; read(x); if x > max then max := x; read(x); if x > max then max := x; read(x); if x > max then max := x; read(x); if x > max then max := x; read(x); if x > max then max := x; writeln('maximum = ', max) end.