4章:関数とサブルーチン
4.3 サブルーチン
ここでは、副プログラムのうちサブルーチン(サブルーチン副プログラム)について説明する。サブルーチン副プログラムは、関数副プログラムと同様、主プログラムからの値を使って処理を行い、結果を主プログラムに返す。
しかし、関数副プログラムと違い、複数の値を引数の型で返すことができるため、非常に便利である。また、値をまったく返さない場合もある。
![](img/chap4-02.gif)
4.3.1 サブルーチン副プログラム
ここでは、サブルーチン副プログラムについて説明する。
サブルーチン副プログラムは以下のように定義する。
SUBROUTINE サブルーチン名(仮引数1,仮引数2,・・・)
宣言部
命令1
命令2
・・・
END SUBROUTINE サブルーチン名
■サブルーチン名
サブルーチン名の付け方は通常の変数名と同じである。
■仮引数1,仮引数2,・・・
サブルーチン中で使用する仮の引数。この定義の中だけで有効なため、プログラム中で使用している関数名も使用することができる。
■宣言部
サブルーチンおよびサブルーチン中で使用する変数(引数、戻り値含む)の型宣言が必要である。入力用引数には「INTENT (IN)」を、出力用引数には「INTENT (OUT)」を、入出力両用引数には「INTENT (INOUT)」を指定する。
■命令
複数の引数について処理を行っても良いし、値をまったく返さず、何らかのタスクを行うだけの内容でも良い。
(例)円の面積と円周の長さを求めるサブルーチン
SUBROUTINE MENSEKI_TO_ENSHUU (HANKEI)
IMPLICIT NONE
REAL, INTENT(IN) :: HANKEI
REAL, INTENT(OUT) :: MENSEKI, ENSHUU
MENSEKI = PI*HANKEI**2
ENSHUU = PI*HANKEI*2
END SUBROUTINE MENSEKI_TO_ENSHUU
サブルーチンの引用
サブルーチンは以下のように引用する。
CALL サブルーチン名(実引数1,実引数2,・・・)
上で定義したサブルーチンを引用して半径2.0の円の面積と円周を求める場合は、
CALL MENSEKI_TO_ENSHUU (2.0)
と記述する。
(例)3つの整数を昇順に並べ替える
PROGRAM SHOUJUN_NARABEKAE
INTEGER :: A,B,C
READ*, A,B,C
IF(A > B) CALL SWAP(A,B)
IF(B > C) CALL SWAP(B,C)
IF(A > B) CALL SWAP(A,B)
PRINT *, A,B,C
END SHOUJUN_NARABEKAE
SUBROUTINE SWAP(X,Y)
INTEGER :: X,Y,Z
Z=X; X=Y; Y=Z
END SUBROUTINE SWAP
4.3.2 引数
サブルーチン副プログラムは、他のサブルーチン副プログラムの引数として使うこともできる。このような場合の注意点は以下の通りである。
- 引数として使用できるサブルーチンはモジュール副プログラム、外部副プログラム、組み込み副プログラムのみである。
- 仮引数にINTENT属性を使うことはできない。
- 再帰サブルーチンを定義する場合には「RECURSIVE SUBROUTINE サブルーチン名」を使用する。
4.3.3 組み込みサブルーチン
Fortran90には、乱数発生やシステム時間の取得など、以下の便利な組み込みサブルーチンが用意されている。
サブルーチン名 | 内容 |
---|---|
SYSTEM_CLOCK (count, count_rate, count_max) |
システム時計に時刻を問い合わせる。 count(整数):システム時計の時刻を返す。 count_rate(整数):1秒間に刻む回数。 count_max(整数):countの最大値。 |
RANDOM_NUMBER (harvest) |
0~1の乱数を発生させる。 harvest(実数):乱数の値を返す。 ※ 毎回同じ乱数を生成。 |
RANDOM_SEED (size,put,get) |
乱数を発生させる際の基準となるもの(種子)を設定する。 size(整数):種子保存に必要な整数の個数。 put(整数):種子の値を設定する。 get(整数):種子の値を返す。 |
DATE_AND_TIME (date, time,zone, values(1:8)) |
日付と時刻を問い合わせる。 date(長さ8の文字型):年月日を返す。 time(長さ10の文字型):時・分・秒・ミリ秒を返す。 zone(長さ5の文字型):グリニッジ標準時からの時差を返す。 values:(1:3)に年月日、(4)に時差、(5:8)に時・分・秒・ミリ秒を返す。 |
(例)システム時計の時刻をもとに乱数を発生させる
PROGRAM RANSUU_HASSEI
REAL D
INTEGER C
CALL SYSTEM_CLOCK(COUNT=C)
CALL RANDOM_SEED(PUT=(/C/))
CALL RANDOM_NUMBER(D)
PRINT *,D
STOP
END RANSUU_HASSEI