手続き宣言 = 手続き見出し ”;” 指令 |
手続き表示 ”;” 手続きブロック |
手続き見出し ”;” 手続きブロック
手続き見出し = ”procedure” 名称 [仮引数並び]
手続き表示 = ”procedure” 手続き名
手続き名 = 名称
手続きブロック= ブロック
例1)『2数の最大公約数を求める』プログラム
PROGRAM rei1(input,output); VAR a,b,c,d : integer; BEGIN READ(a,b); IF a<b THEN BEGIN (1) c:=a; | a:=b; | b:=c | END; (1) REPEAT d:=a MOD b; a:=b; b:=d UNTIL d=0; WRITE(a) END.2変数a,bを読み込み、最大公約数を求めて、aに代入し出力するプログラムです。
例1の(1)の部分を手続きに直すと次のようなプログラムになります。
例2)
PROGRAM rei2(input,output); VAR a,b,c,d : integer; PROCEDURE okikae; BEGIN c:=a; a:=b; b:=c END; BEGIN READ(a,b); IF a<b THEN okikae; REPEAT d:=a MOD b; a:=b; b:=d UNTIL d=0; WRITE(a) END.このプログラムからわかること
例3)
PROGRAM rei3(input,output); VAR a,b,d : integer; PROCEDURE okikae; VAR c : integer; BEGIN c:=a; a:=b; b:=c END; BEGIN READ(a,b); IF a<b THEN okikae; REPEAT d:=a MOD b; a:=b; c:=d UNTIL d=0; WRITE(a) END.例3と例2との違いは、変数cの扱いである。
今度は、もう少し高度に、仮引数がある手続きについて述べる。
手続き見出し = ”PROCEDURE” 名称 [仮引数並び]
仮引数並び = ”(” 仮引数区域 {”;”仮引数区域 } ”)”
仮引数区域 = 値引数仕様 | 変数引数仕様 | 手続き引数仕様 | 関数引数仕様
| 整合配列引数仕様
値引数仕様 = 名称並び ”:” 型名
変数引数仕様 = ”VAR” 名称並び ”:” 型名
手続き引数仕様 = 手続き見出し
関数引数仕様 = 関数見出し
整合配列引数仕様 = 変数整合配列仕様 | 値整合配列仕様
変数整合配列仕様 = ”VAR” 名称並び ”:” 整合配列形式
整合配列形式 = 詰めあり整合配列形式 | 詰めなし整合配列形式
詰めなし整合配列形式 = ”ARRAY””[”添字型仕様{”:”添字型仕様}”]”"OF”(型名 | 整合配列形式)
詰めあり整合配列形式 = ”PACKED” ”ARRAY””[”添字型仕様”]””OF”型名
例3の手続きを、手続き見出しに仮引数並びがあるものに変更してみます。
例4)
PROGRAM rei4(input,output); VAR a,b,c,d : integer; PROCEDURE okikae(VAR x,y : integer); VAR z : integer; BEGIN z:=x; x:=y; y:=z END BEGIN READ(a,b); IF a<b THEN okikae(a,b); REPEAT d:=a MOD b; a:=b; c:=d UNTIL d=0; WRITE(a) END.例4の解説
例5)
PROGRAM rei5(input,output); VAR a,b : integer; PROCEDURE okikae(x,y : integer); VAR z : integer; BEGIN z:=x; x:=y; y:=z END; PROCEDURE amari(VAR k,l : integer); VAR m : integer; BEGIN m:=k MOD l; k:=l; l:=m END; BEGIN READ(a,b); IF a<b THEN okikae(a,b); REPEAT amari(a,b) UNTIL b=0 WRITE(a) END.11.2 関数
関数宣言 = 関数見出し ”;” 指令 | 関数表示 ”;” 関数ブロック | 関数見出し ”;” 関数ブロック
関数見出し = ”FUNCTION” 名称 [ 仮引数並び ]”:” 結果型
関数表示 = ”FUNCTION” 関数名
関数名 = 名称
結果型 = 単純型名 | ポインタ型名
関数ブロック = ブロック
関数は手続きの定義と似ているが、以下の2点が違っている。
(1)関数は値を返すので式の中で用いられる。
(2)関数の仮引数には「VAR」をつけることができない。
例)
FUNCTION gcd(a,b : integer) : integer
(1番目の「integer」は仮引数の型を表し、2番目は結果の型を表す。)
例4の次の部分を関数の形にしてみる。
REPEAT d:=a MOD b; a:=b; b:=d UNTIL d=0 *関数の形* FUNCTION gcd(a,b : integer) : integer; VAR d : integer; BEGIN REPEAT d:=a MOD b; c:=d UNTIL d=0; gcd:=a END.それでは、この関数を実際にプログラムの中に入れましょう。
PROGRAM rei6(input,output); VAR a,b,kotae : integer; PROCEDURE okikae(VAR x,y : integer); VAR z : integer; BEGIN z:=x; x:=y; y:=z END; FUNCTION gcd(a,b : integer) : integer; VAR d : integer; BEGIN REPEAT d:=a MOD b; c:=d UNTIL d=0; gcd:=a END; BEGIN READ(a,b); IF a<b THEN okikae(a,b); kotae:=gcd(a,b); WRITE(kotae) END.11.3 再帰的
「手続きや関数は再帰的な実行ができる。」とは、手続きや関数の中で自分自身の手続きや関数を
呼ぶことができるということである。
それでは、例として、階乗を計算するプログラムの中の関数の部分を書いてみる。
FUNCTION kaijyo(i : integer) : integer; BEGIN IF i<=0 THEN kaijyo:=1 ELSE kaijyo:=i*kaijyo(i-1) END;説明)
もう1つの例として、「ハノイの塔」のプログラムとそのHichartを示します。
プログラム
PROGRAM example(input,output); PROCEDURE hanoi(VAR n,x,y,z : integer); BEGIN IF n>0 THEN BEGIN hanoi(n-1,x,y,z); WRITELN('move',n:5,x:5,'to',y:5); hanoi(n-1,z,x,y) END; END; BEGIN hanoi(4,1,3,2) END.ハノイの塔