gtool4/Fortran 90 library document
2000年11月28日 豊田英司
ライブラリインターフェイスが概念モデルより煩雑になることは極力避けねばなりません。Fortran で gtool4 を作っていく過程では、まっさきに文字処理でその問題にぶちあたりました。Fortran 言語には組み込みの文字型があるのですが、コンパイル時に固定された長さの文字列しか表現できないのです。普通、ファイル名でも属性値でも図のキャプションでも、およそ文字列などというものは長さが変わってあたりまえです。では、どうしたらいいのでしょう?
Fortran には文字型というものがあります。これは固定長の文字列です。サブルーチン引数を除き、文字型変数の長さはコンパイル時に決定します。代入文で、右辺の長さが左辺から期待されている長さと違う場合には、短すぎる場合には切り捨て、長すぎる場合には空白 (ほとんどの場合 ASCII のスペースである) を補います。
比較演算子も文字列末尾の空白はあたかも存在しないかように比較を行います。
Fortran 90 からは組み込み関数 TRIM によって文字列末尾の空白を除去した文字列を返すことができるようになりましたので、文字列評価をする文脈で常に TRIM(文字列) を使うことにすれば、曲がりなりにも可変長文字列のような取り扱いが可能です。ただし、この場合、文字列の値の末尾の空白は表現できないという制約がかかります。
C には文字型というのはありません。整数と実数しかないんですね。普通 char という名前の整数型の配列をよく使います。しかし、文字処理を行なう関数では NUL (値ゼロ)の配列要素があったらそこで文字列が終わり、とすることで可変長の文字列を処理できるようにしています。その場合、文字列の値に NUL が含まれない、という制約がかかりますが、それはそれなりに妥当と言えるでしょう。
一見便利なようですが、固定長の配列にまったく NUL が入っていないとプログラムが暴走してしまうので、まじめにチェックし始めるとかなり面倒です。
固定長バッファと長さをそれぞれの文字オブジェクトに1つづつ管理します。文字列の値に長さ以外の制約がまったくかかりません。
ISO 1539-2: 1994 というものが type(VARYING_STRING) 型とそれにアクセスする手続の仕様を決めています。これにしたがうことにしました。ただし、ポインタ割付を行うとメモリリークするので、 Pascal 方式の固定長文字列とし、最大文字長は 500 文字としました。ファイル名やメッセージとしての利用に関してはこれで無限長と考えることができるでしょう。
文字列末尾の空白を無視できないかもしれない文字処理については、以下の指針に従わねばなりません。
関数値と INTENT(OUT) 引数は必ず type(VARYING_STRING) 型にする
実行時にならないと長さが決まらない、長さに自明な上限のない文字列は type(VARYING_STRING) 型にする
INTENT(IN) 引数はなるべく character(len = *) 型にする。これは文字型定数を与えて呼び出すことを可能にするためである。なお、総称名を用いて type(VARYING_STRING) 型の文字列を受け取る手続を併設することを強く推奨する
文字列末尾の空白を無視でき、自明な最大長が存在するような文字処理については以下のような手法が認められます。
インターフェイスモジュールが推奨する文字長を定数宣言する。ユーザは勝手な長さではなく、この定数を用いて長さを宣言しなければならない。
関数値はその最大長の長さで与えるものとする
手続引数は必ず character(len = *) で宣言するものとする。長さの想定は誤りの原因となるからである。
文字列値の印字は必ず trim() をかけてから行う。
文字列値の連結は必ず trim(左辺) // trim(右辺) とする。
現状では文字列末尾の空白を無視できそうな処理についても type(VARYING_STRING) が用いられています。このため型変換が頻発しています。あまり効率的なことではないので、誰か名案教えて。