FORTRANプログラマーのためのC | (2) |
ここでは、FORTRANとC(ILE−C)を対比させて、FORTRAN→Cの変換の一助と
したいと思います。
ここでは、ILE−Cを単にCと呼びます。
◆入出力命令
端末への出力
端末への出力関数printfを使用します。
FORTRAN
WRITE(6,10)
10 FORMAT (' FORTRAN-PROGRAM')
STOP
END
最初のサンプルででてきた、
void main() {
printf("C-PROGRAM\n");
}
のprintfが標準出力の関数です。
printfのパラメータの一般形は、
printf(変換仕様の文字列,式1,式2,・・・);
で、式1以下は省略できます。変換仕様の文字列は、定数の形でも変数でも構いません。
上の例では、
void main() {
STR = "C-PROGRAM\n";
printf(STR);
}
としても同じ結果になります。
変換様式
一般に出力するときは、出力文字列の中に、内部データを変換様式で変換した文字列を挿入して出力します。
例えば、整数Jを7桁の10進数で出力するときは、
J=1234567;
printf(”J=%7d¥n”,J);
のようにします。%7dが変換様式で、この部分に”1234567”が挿入されて、
”J=1234567¥n”が出力されます。
¥nは改行用の制御文字です。
FORTRANとの対応の例を紹介します。
FORTRAN C 機能 A4 %4s 文字列の変換 I5 %5d 整数を10進数に変換 F6.2 %6.2d 実数(浮動小数点データ)を小数点以下とともに変換 E10.3 %10.3e 1.120e−001のような指数表現に変換
補足:
1.文字列の場合は最後のヌル文字の直前までを出力します。すなわち、FORTRANの
CHARCTER*4に’ABCD’が格納されているような場合、その後ろがヌル文字で
ないと正しく変換表示されません。
FORTRANでは1ワード(4バイト)をそのまま文字列に使用しているケースがあり、
ヌル文字を挿入する余地がありません。このような場合は%4sを%4.4sのようにして、
精度の桁数を与えるとうまく出力できます。
2.文字列の変換でデータが短いとき右詰にするには%の後ろに−記号をつけます。
”AB”を右詰4桁出力するときは、
%−2s
のようにします。
3.ホレリス様式は、固定の文字列で対応します。
1H1 ”1”
1H0 ”0”
1H△ ”△” (△は空白文字)
8HABCDEFGH ”ABCDEFGH”
4.printfによる出力はダイナミックディスプレイ画面という特殊な画面に表示されます。
ダイナミックディスプレイ画面の例
U.AA[0][0]=ABCD U.AA[0][1]=EFGH U.AA[0][2]=IJKL U.AA[1][0]=MNOP U.AA[1][1]=QRST U.AA[1][2]=UVWX 端末セッションを終了するためには,実行キーを押してください。 ===> F3= 終了 F4=ホヲbモ の終り F6= 印刷 F9=テu]n゙ 複写 F17= 最上部 F18= 最下部 F19= 左 F20= 右 F21=マーナ゙ー、cァ]n゙c
◆端末からの入力
端末からの入力はscanfという関数で行います。
例:
scanf(”%d %d %d”,&A,&B,&C);
scanfの中で変更(入力)されたデータをとりだすので、パラメータがアドレス渡しになっていることに注意して下さい。
入力データが複数あるときは、
123 345 6789
のように空白で区切ります。
123実行
345実行
6789実行
のように複数回にわけて入力もできます。
変換の様式指定の文字は、d,f,sなどです。変換はprintfと逆の変換が行われます。
変換指定文字 働 き d 入力を10進整数と解釈して変換する。 f 入力を小数点以下のある実数と解釈して変換する。 s 入力を文字列としてそのまま格納する。
◆印刷出力
印刷ファイル
FORTRANでは、改行や改頁などの印刷制御はレコードの先頭の1バイトを使用して行います。
AS/400では、印刷ファイルを作成時にそのような制御方式にしておく必要があります。
CRTPRTF FILE(WRKLIB/FPRINT) CTLCHAR(*FCFC)
出力操作
FORTRANのにおけるWRITE(6,700)・・・のようなFORMATつきの、
印刷装置などへの出力は printf でなく、 fprintf を使用します。
このときは、出力操作以外にファイルの定義、オープン、クローズなどの操作が必要です。
以下に例を示します。できるだけFORTRANに似せてのコーディングです。
#include <stdio.h> void main(){ FILE *FP ; char F700[]="%s%f,%f,%f\n" ; /* 変換様式の文字列 */ char STR[9]=" ANSWER=" ; float A=11. ; float B=22. ; float C ; FP = fopen("OUTPUT","w"); C= A + B ; fprintf(FP, F700, STR, A, B, C); fclose(FP) ; }
ファイルの定義
ファイルの定義はFILEという型でファイルポインターを宣言行います。
上の例のFPはファイルの情報の入ったデータのあり場所を示すポインターです。
このポインターは、オープンのとき取得し、以後入出力とクローズのときに使用されます。
ファイルのオープン
ファイルのオープンは fopen 関数で行います。引数はファイル名と、入出力モードの指定です。
fopen の戻り値はファイル情報の格納場所のアドレスポインターです。OPENに失敗するとFPにはヌル値が返ります。
例: FP=fopen(”PRINT”,”w”);
出力処理
出力操作は fprintf 関数で行います。引数はファイルポインター、変換様式の文字列、データのリストです。
printf 関数にファイルポインターが加わっただけで、変数様式の文字列の約束などはprintfに同じです。
例: fprintf(FP,F700,STR,A,B,C);
ファイルのクローズ
ファイルのクローズはfclose関数で行います。
引数はfopenで取得したファイルポインターです。
例: fclose(FP);
リスト型の様式変換
FORTRANでは、手軽な印刷出力のために様式をコンパイラーにおまかせする、リスト型の出力があります。
例:WRITE(6,*) I,A,B
リスト型の出力はCにはないので、int型の場合は%11d, float型の場合は%16.8f のような様式を準備する必要があります。
◆レコード型の入出力
レコード型の入出力は、ストリーム型と違い、データの様式変換はありません。
内部のビットパターンのまま転送が行われるので、格段に効率が高くなります。
順次アクセス
順次アクセスの場合、出力は_Rwrite、入力は_Rreadnで行います。
ファイルオープンは_Ropenで、クローズは_Rcloseで行います。
以下に例を示します。
#include <stdio.h> #include <stdlib.h> #include <recio.h> #include <errno.h> int main() { _RFILE *FP; char FL[] ="FILE1" ; /* 物理ファイル名 */ int RECLEN = 80 ; int I = 0 ; double A[10]={1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0} ; double B[10]={2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0} ; double C[10] ; if (( FP =_Ropen (FL, "ar")) == NULL ) { printf("OPEN ERROR ??/n" ); exit(1) ; } _Rwrite(FP , A, RECLEN); _Rwrite(FP , B, RECLEN); _Rclose (FP); /* -----------------------------------------------------*/ /*ここから読み取り専用でOPEN*/ if (( FP =_Ropen (FL , "rr")) == NULL ) { printf("OPEN ERROR ??/n" ); exit(1) ; } _Rreadn (FP, C ,RECLEN ,__DFT) ; /* 最初のレコード */ for (I=0;I< 10;I=I+1){ printf("C[%d]=%f??/n", I,C[I]); } _Rreadn (FP, C ,RECLEN ,__DFT) ; /* 2番目のレコード */ for (I=0;I< 10;I=I+1){ printf("C[%d]=%f??/n", I,C[I]); } _Rclose (FP); return (0) ; }
ヘッダーファイル
#include命令で取り込まれるファイルをヘッダーファイルといいます。
コンパイルに先立ち次のファイルをINCLUDEしています。
中には使用していないものもあります。しかしエラーにはなりません。
<stdio.h> 標準の入出力用
<stdlib.h> 乱数、絶対値、処理打切りなど標準処理関数。
<recio.h> レコード型入出力用の関数。
<errno.h> errno変数にセットされるマクロを定義。
ファイルオープンと入出力モード
if 命令の中で関数呼出をしてオープンし、FPにセットすると同じにそれがヌル値かどうかを判定しています。
参考とした本にはこのようなコーディングをしていましたが、このようなコーディングがよいのかどうかは疑問が残ります。
_Ropenの2番目のパラメータは入出力モードで、次のようなものがあります。
コード 機能 rr レコードの読取り専用 wr レコードの書込み専用。データがある場合には消去された後書込み。 ar ファイルの終りへのレコードの書込み ( 追加 ) rr+ レコードの読取り、書込み、更新 wr+ レコードの読取り、書込み、更新。データがある場合消去された後書込み。 ar+ レコードの読取りおよび書込。すべてのデータはファイルの終りに書込
出力
ファイルポインター、バッファーのアドレス、レコード長さを与えて出力します。
入力
ファイルポインター、バッファーのアドレス、レコード長さ、処理オプションを与えて入力します。
処理オプション定数でコンパイルのとき、16進数に置きかえられます。__DFTと__NO_LOCKがあります。
__DFT 読取時レコードがロックされる。
__NO_LOCK ロックされない。
ファイルクローズ
ファイルポインターを指定してクローズします。
◆FORTRANのダイレクトアクセス
WRITE(12’5)A,B,Cはダイレクトアクセスの出力命令です。
ASのFORTRANではWRITE(12,REC=5)A,B,Cとなります。
この命令のようなレコードナンバーを指定してのいきなりの書きこみは,Cではできません。
これは、COBOLやRPGなどの他の言語でも同様です。
FORTRANではDEFINE FILE命令があると、プログラム実行開始時に全件、ダミーレコードを書きこみしているようです。
これをCで実現するためには、同様のことをするプログラムを別途作成する必要があります。
具体的には、必要レコード数だけダミーレコードを出力します。
ついでそれを全件削除します。すなわち、ファイルに削除レコードだけの状態にします。
このようにすると、相対レコード番号(RRN)を指定して、関数_Rwritedで直接書出しができます。
目 次 前ページ
(C)COPYRIGHT ISHIOKA KATSUHIDE ,2000