言語要素の概要2

関数

ユーザ定義関数

「ユーザに二つの西暦年号を入力させ,その間の日数を計算する(両端の年を含む)」という課題を考える.計算の中核部分は,次のようになるであろう:


!
! year_start : 始まりの年
! year_end   : 終わりの年
!

answer=0

do year = year_start, year_end

	!......

	!
	!ここで西暦"year"年の日数を計算して,daysに入れる
	!

	answer = answer + days

end do

!
! ここで,答えはanswerに入っている
!

さて,「西暦"year"年の日数を計算して,daysに入れる」のところには,もちろん第三章でとり上げたようなアルゴリズムを使えばよい.

よいのだが,それでは,「ある年の日数を計算する」必要が,プログラムのほかの場所でも生じたらどうなるだろうか? 各場所で何回も例のIF文を書くか?

それは無駄というものである.一つの機能を持つプログラムのパーツは一回書けばそれでよい. これを実現するのがサブルーチン(後述)と関数(function)である.

つまり,「一つの西暦年数値を与えるとその年の日数を返してくれる」プログラムのパーツ(つまり関数)を作っておいて,必要があればそれを呼び出せばよいのである.

では使い方をみてみる.


関数は,何か値を与えられたときに(現在時刻を返す関数など,稀に全く値を与えられない関数もある),一つの値を返す.そのため,その返す値の型を最初に宣言する(integer functionの部分).その宣言の後に関数の名前(days_of_year),そして次のカッコの中に,受け取る値(year)を,複数あるときはコンマで区切って書く. 関数ブロックはこのfunction文から,end function文までである.

この,受け取る値のことを引数(ひきすう)という.

引数も変数だから,型宣言をしなければならない.それは普通の変数宣言と同じ.ただし,より一層引数の性格を明確にするためにintent属性をつけておくとよい.intent(IN)は,関数が一方的に受け取るのみの引数であり,この関数の中では一切改変されない引数であることを表す.

intent(IN)がついた引数を改変しようとするとコンパイル時にエラーがでる.

関数の戻り値は,関数を同じ名前(days_of_year)を持つ変数が仮にあると考えて,その「変数」に普通に代入すればよい.この代入を行わなかったとき,関数の値がどうなるかは保証されない.

関数の呼び出し(call)はどうなるか.すでに紹介したMOD(n,m)のように,ごく普通にdays_of_year(n)のように書けばそれ自体が関数の答え(値)となる.

ただし,一つ注意点.implicit noneをつけている場合,使うユーザ定義関数も型宣言をする必要がある(integer :: days_of_year).そうしないとコンパイルエラーとなる.

intent属性も,関数も宣言が必要なことも,一見するとわずらわしいように思えるが,大規模なプログラム開発に当たっては予期せぬエラーを未然に防ぐ強力な武器となる.

組み込み関数

↑の節ではユーザが定義する関数を紹介したが,FORTRANには最初から組み込まれている関数組み込み関数もたくさんある. このような関数を使うときには,型宣言は不要である.

よく使われる関数を紹介する.主に数学関数と文字列関数である.全ての関数を知りたければ,例えばリファレンス参照.

実数型:
名前 意味
SQRT(x) 平方根
ABS(x) 絶対値
SIN(x), COS(x), TAN(x) おなじみの三角関数
ASIN(x), ACOS(x), ATAN(x) 逆三角関数
EXP(x), LOG(x), LOG10(x) 指数関数と対数関数(自然・常用)
SINH(x), COSH(x), TANH(x) 双曲関数
AINT(x), ANINT(x) 小数点以下切り捨て,四捨五入
REAL(i) 整数iを実数にする
整数型
MOD(i1,i2) 剰余(i1をi2で割ったあまり)
INT(x), NINT(x) 小数点以下切り捨て,四捨五入
両方
MAX(a1,a2,...,an) 最大値
MIN(a1,a2,...,an) 最小値
文字列関係
名前 意味 返す型
ADJUSTL(s), ADJUSTR(s) 右詰め・左詰め 文字列型
CHAR(i) 文字コードiに対応する文字 integer
ICHAR(s) 文字sの文字コード 文字型
INDEX(s1,s2) 文字列s1の中で文字列s2を探し,最初に現れた先頭位置を返す(なければ0) integer
LEN_TRIM(s), LEN(s) 文字列の,予約されている長さ・実際の(右の空白を除いた)長さ integer
LGE(s1,s2), LGT(s1,s2), LLE(s1,s2), LLT(s1,s2) 文字列s1とs2を比較する.「辞書順」の大小(前後)関係. logical
REPEAT(s,n) 文字列sをn回コピーした文字列 文字列型
SCAN(s1,s2[,BACK]) 文字列s1の中から,文字列s2に含まれる文字を探し,もしあればその位置を返す.なければ0.BACKを.TRUE.(LOGICAL型の「真」を表す値)にすると,後ろから探す. integer
VERIFY(s1,s2[,BACK]) SCANの逆で,s1の中からs2に含まれない文字を探し,その位置を返す.BACKの意味も同じ. integer
TRIM(s) 文字列sの,右側の空白を消去した文字列を作る 文字列型

AGATASHI