火曜日3,4限

環境・建設計算機実習T


アルゴリズムの基礎(FORTRAN演習)  サブルーチン
 

    1.副プログラムの概念
      副プログラムの考え方
      副プログラムの特徴
      副プログラムの種類

    2.関数副プログラム

      関数副プログラムの例
      FUNCTION文
      外部関数の引用
      制御の流れとRETURN文

    3.サブルーチン副プログラム

      サブルーチン副プログラムの例
      SUBROUTINE文
      CALL文
      制御の流れとRETURN文

    4.引数の対応規則

      (1) 実引数と仮引数の個数
      (2) 実引数と仮引数の型
      (3) 実引数と仮引数の並びの順
      (4) 仮引数の再定義
      (5) 実引数が式またはカッコを含む場合
      (6) 実引数が配列の場合
      (7) 引数が文字列の場合
      (8) 仮引数のについて

    5.プログラムの構造と連結

      主・副プログラム間の構造
      主・副プログラム群の構造


 

1.副プログラムの概念

 

副プログラムの考え方

 プログラムは一般に、手続きの数が増えるにしたがって、その記述内容が複雑になる。というのは1つのプログラムの中に記述されるここの手続きは相互に関連し合っているので、手続きの数が増加すると、それらの相互関係も急激に複雑になるからである。それゆえ手続きを整然と記述することは非常に難しい。

このような場合、「1つのプログラムを複数の小さなプログラムに分割し、それらを個々別々に記述してはどうか」という発想が浮かんでくる。これはごく自然な考え方である。というのは物事を解決する場合、「全体を確定した上で部分に移る」というのが原則であり、またその考え方が作業の上からも容易だからである。

 これと同じように、プログラミングに際しても、問題領域全体の中から個々の手続きを見極めた上で、その手続きを分割・抽出し(全体の決定)、その後で部分としての手続きを、個々独立のプログラムとして記述していこう(部分の記述)と考える。

 FORTRANはこのようなプログラムの分割を可能にするために、副プログラムと呼ばれる手段(プログラム)を利用する。副プログラムは、個々の手続きを部分的に記述するプログラムではあるが、それはプログラムの体裁を成していて、1つのプログラム単位として独立している。その際、個々の手続きは、一般のプログラムが持っているデータ入力・編集・演算・出力といった手続きを、分割される前のプログラムから分割・抽出したものである。

副プログラムは主プログラム(メイン・プログラム)と呼ばれる”親”プログラムのコントロールを受ける。そして副プログラムは、主プログラムから見れば”子”プログラムとして、分割される前のプログラム機能の一部を担当する。

図-1 主プログラムと副プログラムの概念

 主プログラムと副プログラムの関係の例を図-1を用いて概念的に説明する。主プログラムMはプログラム全体の実行の流れ矢動作をコントロールする。主プログラムMはある時点で入力専用の副プログラムAを呼び出し、それに入力を代替させ、またある時点で出力専用の副プログラムBを呼び出し、それに出力を代替ささせる。

このように主プログラムと副プログラムの組は、そのプログラム同士が連係することによって、分割される前のプログラムと同じはたらきをする。

 

 

副プログラムの特徴

 副プログラムの説明に入る前に、副プログラムの基本的な特徴を述べる。この項は、本章の実習が終了した後に読み直すをより効果的である。それにより、副プログラムの本質を実感として把握することができるはずである。

(1)重複記述の回避

 1つのプログラムの中に同一の手続きが場所を離れて何回も出現する場合、その手続きを1つの副プログラムにまとめて記述する。同じ手続きを何回も重複して記述するとプログラム全体のまとまりが悪くなる。必要があればその副プログラムは、何回も利用することができる。副プログラムの利用はプログラムのサイズを小さくする上からも効果的である。

(2)相互独立

 副プログラムは主プログラムおよび他の副プログラムからデータの受け渡しを除いて、完全に独立している。また、主プログラムとほとんど同じような記述が許される。副プログラムが独立していることから、変数や配列の記述にあたっては、他の副プログラムの変数や配列名に一切の注意を払わなくてもかまわない。例えばある副プログラムでは事柄Aに対して用いた変数が、別の副プログラムでは事柄Bに対して用いられたとしても、それは相互に無関係である。

(3)個別翻訳

 副プログラムはそれぞれ個別に翻訳(コンパイル)することができるので、プログラムの全体が完成していなくても、個々の副プログラムだけでデバッグ作業ができる。したがって大規模プログラムの開発では、個々の副プログラムを一人一人のプログラマに割り当てることにより、同時並行的にその開発を進めることが可能となる。

(4)共同利用

副プログラムは作成の仕方によっては、多くのプログラム作成者から共通に利用することが可能である。すなわち多くの人々によって頻繁に利用される手続き、例えば分類、検索、乱数発生などの一般的な手続きを、”汎用的な仕様”のもとで副プログラムとしてまとめあげる。プログラム作成者は必要があれば、これらの副プログラムを”部品”として自分達のプログラムの中に取り入れて仕様することができる。このような副プログラムの集合体は一般にサブルーチン・ライブラリ−と呼ばれ、通常のコンピュータ・システムには多く備わっている。

 

 

副プログラムの種類

 副プログラムの種類としては、次に示すように関数副プログラムサブルーチン副プログラムおよび初期値設定副プログラムの3種類が存在する。

(1)関数副プログラム

 関数副プログラムは文関数では表現できない複雑な関数を記述する際に用いられる。

(2)サブルーチン副プログラム

 サブルーチン副プログラムは個別的にまとまった入力・出力・編集・演算・分類・検索などの手続きを記述する際に用いられる。この副プログラムで定義された手続きをサブルーチンという。

(3)初期値設定副プログラム

 初期値設定副プログラムは多量の初期データを蓄える際に用いられる。。しかし、この副プログラムには手続き(実行文)を記述することはできない。

    トップ・メニューへ

 

 

2.関数副プログラム

 

関数副プログラムの例

関数副プログラムは関数(前回授業)で述べた外部関数を定義するプログラムである。プログラム例は関数の3.外部関数を参照のこと。

 

 

FUNCTION文

 関数副プログラムを記述する方法を厳密に述べる。

 関数副プログラムはFUNCTION文によってその記述が開始され、END文によって終了する。この関数副プログラムの枠組みは、主プログラムの枠組みがPROGRAM文で始まり、END文で終了することに対応する。

FUNCTION文の一般形は次の通り。

 FUNCTION func( d1, d2,...., dn )

 funcは外部関数であり、それは英字名を用いて付けられる。外部関数名は主プログラムのPROGRAM文で指定されるプログラム名と同じであってはならない。diは引数えあり、変数名、配列名が用いられる。仮引数は主プログラムからデータを受け取る役目をするが、関数副プログラムの中で演算された値を仮引数に引き渡してもかまわない。仮引数の並びは、引数の順序、個数および型を示すことだけに意味があり、主プログラムの実引数の英字名とは一致しなくてもよい。

 外部関数は型を持っており、その宣言は文関数と同様に、「暗黙の型宣言」、「IMPLICIT文による宣言」、「型宣言文による宣言」により行われる。したがって暗黙の型宣言に合致しない型の外部関数、例えば複素数の外部関数CMPは、その関数の型を

          FUNCTION CMP(X,Y,Z)

          COMPLEX CMP, X, Y, Z

             ・・・

と型宣言文(あるいはIMPLICIT文)によって宣言をする必要がある。この場合、FUNCTION文と型宣言文を一緒にして、

         COMPLEX FUNCTION CMP(X,Y,Z)

         COMPLEX CMP, X, Y, Z

            ・・・

と、FUNCTION文の前に型を示すキーワードを付けても構わない。

 FUNCTION文とEND文の間の部分には、外部関数の手続きを記述する。そこには主プログラムとほとんど同様な形式で、宣言文、文関数定義文、実行文などを記述することができる。実行文の中には、関数の結果を主プログラムに引き渡すために、結果を外部関数名にセットする代入文

         FUNC = ・・・・

が1つ以上なければならない。またRETURN文も1つ以上記述されていなければならない。

 

 

外部関数の引用

 外部関数の引用は、主プログラムの実行文の式の中に外部関数を記述することによって行われる。式の指定が許されている実行文ではどんな実行文でもよいが、一般には次のように、代入文の式の中に記述される。

 v = ・・・func( a1, a2,・・・, an )・・・

 funcは外部関数名であり、aiは引数である。実引数には定数、変数、配列、配列要素、文字部分列、式を用いる。実引数は外部関数が引用される時点で、値が定まっていなければならない。実引数と関数副プログラムの仮引数とは、その並びの個数、順序、型がそれぞれ対応しなければならない。実引数が英字名の場合には、それは仮引数の英字名と異なってもよい。実引数と仮引数の詳しい対応規則については、4.引数の対応規則で述べる。

 

 

制御の流れとRETURN文

 外部関数の引用は次の順序で実行される。

 @ 実引数が式であれば、それが演算される。

 A 実引数とそれに対応する仮引数が結合される。

 B 関数副プログラム中の手続きが実行される。

 C 外部関数名に結果が出力される。

 関数副プログラムから主プログラムへの戻りは、RETURN文によっておこなわれる。この文は関数副プログラム中に必ず1つ以上なければならない。

 

主プログラム    PROGRAM MNTST

        REAL MEAN

        DIMENSION N(100)

        I=1

      10 READ(5,*,END=20) N(I)

        I=I+1

        GO TO 10

      20 A=MEAN(N,I+1)

        WRITE(6,*) 'AVERAGE=',A

        STOP

        END

副プログラム    REAL FUNCTION MEAN(BF, N)

        INTEGER BF(100)

        TOTAL=0

        DO 10 I=1,N

         TOTAL=TOTAL+BF(1)

      10 COTINUE

        MEAN=TOTAL/N

        RETURN

        END

例題 配列に保持されたデータを合計して平均値を求める関数副プログラムと、それを引用する主プログラムの例

 

 主プログラムMNTSTの実引数は配列Nと式(I−1)である。関数副プログラムMEANの仮引数は配列BFと変数Nである。仮引数BFは実引数の整数型配列Nと対応しているので、BFには整数型配列の宣言がされている。仮引数Nは実引数の整数式と対応している。

 

 

    トップ・メニューへ

 

3.サブルーチン副プログラム

 

サブルーチン副プログラムの例

 関数副プログラムは複雑な関数を定義することはできるが、原則として1関数しか定義できず、関数副プログラムは単に文関数を発展させたものにすぎない。

 副プログラムの考え方は関数に限らず、一般の手続きに対して適用してもかまわない。例えば、分類や検索などの手続きをひとまとめにして定義しても副プログラムの主旨(1.副プログラムの概念-副プログラムの特徴参照)に合致するものである。しかし、これらの手続きに適合する副プログラムは、1つだけではなく複数の結果の出力を可能とする形式の副プログラムでなければならない。

 このような役割を果たす副プログラムがサブルーチン副プログラムである。まず、簡単な例を用いてサブルーチン副プログラムを説明する。

今、A,B,Cをデータとして入力し、その3つを係数とする2次方程式

      AX+BX+C=0

の重根・実根を求める(ただし、虚根、重根、実根の区別もおこなう)プログラムを単一のプログラム(主プログラムだけ)の形式で記述すると、次の例題の左側のようになり、これを主プログラムとサブルーチン副プログラムに分割すると、右側のようになる。

 

   PROGRAM SBTST1

   READ(5,*) A, B, C

   D=B**2-4*A*C

   IF(D.LT.0) THEN

    IFLG=1

    X1=0

    X2=0

   ELSE IF(D.EQ.0) THEN

    IFLG=2

    X1= -B/(2*A)

    X2=0

   ELSE IF(D.GT.0) THEN

    IFLG=3

    X1=(-B-SQRT(D))/(2*A)

    X2=(-B+SQRT(D))/(2*A)

   END IF

   WRITE(6,*) 'FLAG',IFLG

  &  ,'A=',A,' B=',B,' C=',C

  &  ,' X1=',X1,' X2=',X2

   STOP

   END

主プログラム

  PROGRAM SBTST2

  READ(5,*) A, B, C

  CALL ROOT(A,B,C,IFLG,X1,X2)

  WRITE(6,*) 'FLAG',IFLG

 &   ,'A=',A,' B=',B,' C=',C

 &   ,' X1=',X1,' X2=',X2

  STOP

  END

サブルーチン副プログラム

 SUBROUTINE ROOT(A,B,C,IFLG,X1,X2)

 D=B**2-4*A*C

 IF(D.LT.0) THEN

  IFLG=1

  X1=0

  X2=0

 ELSE IF(D.EQ.0) THEN

  IFLG=2

  X1= -B/(2*A)

  X2=0

 ELSE IF(D.GT.0) THEN

  IFLG=3

  X1=(-B-SQRT(D))/(2*A)

  X2=(-B+SQRT(D))/(2*A)

 END IF

 RETURN

 END

例題 単一プログラム例(左)とサブルーチン副プログラムを用いた例(右)

 

 右側のプログラムの説明をする。

     SUBROUTINE ROOT(A,B,C,IFLG,X1,X2)

SUBROUTINE文という。この文は以下に続くプログラムがサブルーチン副プログラムであることを示す。SUBROUTINEで指定したROOTはサブルーチン名である。サブルーチン名のカッコの中のA,B,C,IFLG,X1,X2は文関数定義文、関数副プログラムと同様の仮引数である。

 サブルーチン副プログラムの仮引数は、主プログラムからデータを受け取るばかりではなく、結果を主プログラムに引き渡す働きもする。サブルーチン副プログラムROOTの例では、仮引数A,B,Cがデータを受け取り、IFLG,X1,X2が結果を引き渡す働きをする。

サブルーチンの引用は主プログラムSBTST2の中のCALL文と呼ばれる実行文

    CALL ROOT(A,B,C,IFLG,X1,X2)

でおこなわれる。ROOTは引用するサブルーチン名である。サブルーチン名ROOTのカッコの中のA,B,C,IFLG,X1,X2は文関数、外部関数と同様の実引数である。サブルーチンが引用されると、結果は実引数にセットされる。引用が終了すると、CALL文の次のWRITE文が実行される。

 

 

SUBROUTINE文

 サブルーチン副プログラムはSUBROUTINE文によってその記述が開始され、END文によって終了する。

SUBROUTINE文の一般形は次のとおり。

 SUBROUTINE sub( d1, d2,・・・, dn )・・・

 subはサブルーチン名であり、それは英字名を用いて付けられる。サブルーチン名は主プログラムのプログラム名あるいは他の関数副プログラムの外部関数と同じではいけない。diは仮引数であり、変数名あるいは配列名が用いられる。仮引数は主プログラムからデータを受け取り、主プログラムへ結果を返す働きをする。仮引数の個数は自由である。関数副プログラムが1つの関数しか定義できないのに対し、サブルーチン副プログラムはデータを引き渡す仮引数を何個も用いることにより、多くの関数(サブルーチン)を定義することが可能である。どの仮引数がデータを受け取り、どの仮引数が結果を引き渡すかを決める規則はない。プログラム作成者の習慣では、受け取り用の仮引数は左側に、引き渡し用の仮引数は右側に、それぞれまとめて記述するのが一般である。

 仮引数の並びは引数の順序、個数および型を示すことだけに意味があり、主プログラムの実引数の英字名とは一致しなくてもかまわない。なお、サブルーチンは外部関数のように型を持っていない。サブルーチンは名は単に、サブルーチンを識別するのに利用されるだけである。

 

図-2 主プログラムとサブルーチン副プログラムの枠組

 

 

CALL文

 サブルーチンの引用は、主プログラムのCALL文によって行われる(図-2)。CALL文の一般形は次の通り。

  CALL sub( a1, a2,・・・, an )・・・

subはサブルーチン名であり、aiは実引数である。実引数には定数、変数、配列、配列要素、文字部分列、式を用いる。実引数はサブルーチンが引用される時点で、値が定まっていないといけない。実引数とサブルーチン副プログラムの仮引数とは、その並びの個数、順序、および型がそれぞれ対応している必要がある。実引数が英字名の場合には、それは仮引数の英字名と異なってもかまわない。実引数と仮引数の詳しい対応規則については4.引数の対応規則で述べる。

 

 

制御の流れとRETURN文

サブルーチンの引用は次の順序で実行される。

 @ 実引数が式であれば、それが演算される。

 A 実引数とそれに対応する仮引数が結合される。

 B サブルーチン副プログラムの手続きが実行される。

 C 実引数に結果がセットされる。

 サブルーチン副プログラムから主プログラムへの戻りはRETURN文で行われ、主プログラム内のCALL文の次の実行文に戻る。REURN文はサブルーチン副プログラムに必ず1つ以上なければならない。また、必要があれば、サブルーチン副プログラム内にSTOP文を記述してもかまわない。

    トップ・メニューへ

 

 

 

4.引数の対応規則

 主プログラムが関数副プログラムあるいはサブルーチン副プログラムを引用すると、実引数と仮引数はそれぞれ並びの順序で結合され、データは引数を介して両プログラム間で受け渡される。この場合、実引数と仮引数は、次のような対応関係になければならない。

 

@ 実引数と仮引数は、個数、型、順序において、相互に対応していなければならない。

A 実引数となりえる要素は、定数、変数、配列、配列要素、文字部分列および式であり、仮引数となりえる要素は、変数と配列であるが、それらの英字名は両プログラム間で異なってもかまわない。

 

 ここでは、これらの規則を例を用いて詳しく説明する。以下の説明にはサブルーチン副プログラムを用いているが、その内容は関数副プログラムにもあてはまる。

 

(1) 実引数と仮引数の個数は同じでなければならない。次に誤った例を示す。

 

主プログラム  PROGRAM MAIN1

        |

      CALL SUB1(A,B,C,D,E)

        |

      END

副プログラム  SUBROUTINE SUB1(P,Q,R)

        |

      END

誤例 引数の数が異なる

 

 

(2) 相互に対応する実引数と仮引数の型は同一でなければならない。次に誤った例を示す。

 

主プログラム  PROGRAM MAIN2

      REAL A,B

      DOUBLE PRECISION C

        |

      CALL SUB2(A,B,C)

        |

      END

副プログラム  SUBROUTINE SUB2(P,Q,R)

      REAL P,Q,R

        |

      END

誤例 引数の型が異なる

 

 

(3) 実引数と仮引数の並びの順は一致してなければならない。次に誤った例を示す。

 

主プログラム  PROGRAM MAIN3

      DIMENSION P(10)

      CHARACTER C*10, P*5

         |

      CALL SUB3(N,P,C)

         |

      END

副プログラム  SUBROUTINE SUB3(N,C,P)

      DIMENSION P(10)

      CHARACTER C*10, P*5

         |

      END

誤例 変数Cと配列Pの順序が異なる

 

 

(4) 実引数が変数、配列要素、文字部分列の時、それに対応する仮引数は変数でなければならない。この場合、仮引数を再定義してもよい。次に正例を示す。

 

主プログラム  PROGRAM MAIN4

      DIMENSION A(10)

      CHARACTER C*5

         |

      A(3)=1000.

      CALL SUB4(A(3),C(2:4),X)

         |

      END

副プログラム  SUBROUTINE SUB4(P,CHR,Q)

      CHARACTER CHR*3

         |

      Q=2000.

      END

正例 仮引数を再定義した例

 

 

(5) 実引数は定数、関数引用(ただし文関数の引用は除外)は演算子を含む式またはカッコで囲まれた式であってもよいが、それに対応する仮引数は変数でなければならない。この場合、仮引数を再定義してはならない。引数を介したデータの受け渡しは主プログラムから副プログラムに対して行われるだけである。次に正例を示す。

 

主プログラム  PROGRAM MAIN5

         |

      CALL SUB5(5.,SQRT(X),2.8+N,(X+Y)/Z)

         |

      END

副プログラム  SUBROUTINE SUB5(A,B,C,D)

         |

      END

正例 実引数が式またはカッコで囲まれた式の場合

 

 

(6) 実引数が配列のときには、仮引数も配列でなければならない。さらに対応する配列の型、次元、大きさは同じでなければならない。次に正例を示す。

特に重要!

 

主プログラム  PROGRAM MAIN6

      DIMENSION A(10),B(100,20)

         |

      CALL SUB6(A,B,P,Q)

         |

      END

副プログラム  SUBROUTINE SUB6(X,Y,P,Q)

      DIMENSION X(10),Y(100,200)

         |

      END

正例 実引数が配列のとき

 

 

(7) 引数が文字型の場合、実引数の長さは仮引数のそれと等しいかそれよりも長くなければならない。実引数が文字部分列の場合には、文字部分列の長さが実引数の長さとなる。実引数が文字演算子を含んだ式であるならば、その結果が実引数の長さになる。次に誤例を示す。

 

主プログラム  PROGRAM MAIN7

      CHARACTER C*10

         |

      CALL SUB7('AB'//'XYZ',C(2:6))

         |

      END

副プログラム  SUBROUTINE SUB7(CHR1,CHR2)

      CHARACTER CHR1*4,CHR2*10

         |

      END

誤例 仮引数CHR2がそれに対応する実引数よりも長い

 

 

(8) 仮引数は、定数、式、配列要素、文字部分列であってはならない。次に誤例を示す。

 

主プログラム  PROGRAM MAIN8

      DIMENSION E(10)

      CHARACTER C*10

         |

      CALL SUB9(A,B,E(1),C)

         |

      END

副プログラム  SUBROUTINE SUB8(20.,X+Y,P(1),C(2:5))

      DIMENSION P(10)

      CHARACTER C*5

         |

      END

誤例 仮引数が血数、式、配列要素、文字部分列

 

 

    トップ・メニューへ

 

5.プログラムの構造と連結

 

主・副プログラム間の構造

今まで、主プログラムが1つの副プログラムを引用する例を述べてきたが、副プログラムの引用は1つに限らない。主プログラムは、いくつもの副プログラムを何回も引用してもよい。また、副プログラムが副プログラムを引用してもよい。

 

 

主・副プログラム群の構造

プログラムの設計段階で構想された1つの概念的なプログラムは、現実的には主プログラムと多くの副プログラムに分割して作成される。また、主プログラムや副プログラムは、それぞれ独立した翻訳(コンパイル)の単位となっている。作成された主・副プログラム群を1つの概念的なプログラムとして実行するには、それらのプログラム群をコンピュータ・システム上で統合化することによって実行可能プログラムを作成する。

この統合化は、個々の主・副プログラム群をコンパイラによって翻訳した結果を、リンケージ・エディタと呼ばれる基本ソフトウェアによって連結することによって行われる。

なお、コンパイラやリンケージ・エディタの操作は、通常、コマンドを用いておこなう。コマンドはコンピュータ・システムにより異なる。

    トップ・メニューへ



5.課題

    配列に保持されたデータの中から最大値と最小値を選び出すサブルーチンと、それを引用する主プログラムを作成しなさい。

      ・ データの読込は100個とする→ 配列は100
      ・ データの型は整数か実数
      ・ 主プログラムではデータ読み込みと結果の出力のみとする
      ・ 最大値と最小値は変数の比較でおこなう
        →組み込み関数は使わない

 


質問・意見等

 

940-2188

新潟県長岡市上富岡町1603-1 長岡技術科学大学 環境・建設系

 

環境・建設計算機実習T 一部担当

 

犬飼 直之(内線 9624)inu@nagaokaut.ac.jp


GLESCO

( GLobe, EStuary and COast )

Hydrauric Engineering Lab. Nagaoka University of Technology