計算物理学II (第8回)

今回の内容• ファイル⼊出⼒• グラフ作成

標準⼊出⼒• 標準⼊⼒(キーボードからの⼊⼒)
read (*,*) var
read (5,*) var1, var2

scanf(“%d”, &var);scanf(“%lf %lf”, &var1, &var2);
fscanf(stdin,”%d”, &var);• 標準出⼒(画⾯への出⼒)
write (*,*) var
write (6,*) “var1 var2 = “, var1, var2
print *, var

printf(“%d¥n”, var);printf(”var1 = %f, var2 = %f¥n”, var1,var2);
fprintf(stdout,”%d¥n”, var);• 標準エラー出⼒(画⾯への出⼒)
Fortranwrite (0,*) “Error”fprintf(stderr, “Error¥n”);

read, writeの１つ⽬の引数(unit)でファイル装置番号を指定する。*とすると標準⼊出⼒になるが、5が標準⼊⼒、6が標準出⼒、0が標準エラー出⼒となっている
C⼊出⼒の型を明⽰。 %d 整数型、%f 実数型 %lf 倍精度実数型(⼊⼒のみ指定)
scanfのときは読み込みたい変数の前に&をつける(変数のアドレス)。 \nは改⾏
stdin(標準⼊⼒), stdout(標準出⼒), stderr(標準エラー出⼒)はstdio.hで定義されている

ファイル⼊出⼒(リダイレクト)
シェル側でファイルに⼊出⼒

シェルでリダイレクトによって標準⼊出⼒をファイルに変更
Linuxのリダイレクトの部分を復習してください

実⾏ファイルa.outを実⾏するときの標準⼊⼒を inputという名前のファイル、標準出⼒を output 標準エラー出⼒をerrorという名前のファイルにする場合は./a.out < input > output 2> error
標準出⼒と標準エラー出⼒両⽅をoutputに書き出す場合./a.out > output 2>1&

プログラム内でのファイル⼊出⼒
Fortranでファイルを指定! 装置番号1としてinputfile.txtを開く
open( 1, file=ʻinputfile.txtʼ, action=ʻreadʼ)! 装置番号2としてoutputfile.txtを開く
open( 2, file=ʻoutputfile.txtʼ, action=ʻwriteʼ)! 装置番号1(inputfile.txt)から読み込んだ値をvarに代⼊read(1,*) var! 装置番号2(outputfile.txt)に変数varの値を出⼒
write(2,*) var
close(1) ! 装置番号1のファイルを閉じる!(この後装置番号1は他のファイルに当てることができる)
close(2) ! 装置番号2のファイルを閉じる

Cでファイルを指定
FILE *fp1, *fp2;/* FILE型ストリーム。 stdio.hで定義されている */fp1=fopen(ʻinputfile.txtʼ, ʻrʼ);// inputfile.txtを読み込み専⽤として開く
fp2= fopen(ʻoutputfile.txtʼ, ʻwʼ);// outputfile.txtを書き込み専⽤として開く。
fscanf(fp1, “%lf”, &var);// fp1ストリームから倍精度実数varを読み込む
fprintf(fp2, “%f”, var);// fp2ストリームに倍精度実数varを書き込む
fclose(fp1); // ファイルを閉じる
fclose(fp2); // ファイルを閉じる

Fortran: 装置番号5,6,0は標準⼊⼒、出⼒、エラー出⼒に予約されているのでこれ以外の番号を指定
C: fopen関数の読み書きのモード：
r 読み込み, w 書き込み, a 追加書き込み(ファイルが存在する場合は末尾から書き込む)

ファイル⼊出⼒(Fortran)
open関数で指定できるのはunit指定⼦:
file指定⼦：
status指定⼦：

装置番号を指定。 unit=は省略して数字だけでもOK
ファイル名を指定
ʻoldʼ すでにファイルが存在する場合
ʻnewʼ ファイルが新しく作られる場合
ʻreplaceʼ ファイルが存在する場合は前のファイルが削除される
ʻunknownʼ デフォルト値。ファイルがない場合は新しく作成。

action指定⼦：

ʻreadʼ 読み込み専⽤でファイルを開く (間違えて書き込むミスを防ぐ)ʻwriteʼ 書き込み専⽤でファイルを開くʻreadwriteʼ デフォルト。読み書き可能

position指定⼦:

ʻasisʼ デフォルトの場所、通常ファイルの先頭位置
ʻrewindʼ ファイルの先頭位置
ʻappendʼ ファイルの末尾位置

すでに存在するファイルに追記したい場合はopen(unit=1, file=ʻファイル名ʼ, status=ʻoldʼ, position=ʻappendʼ)などとしてファイルを開く

書式指定(Fortran)• write,printで出⼒の書式指定ができる• writeの2つ⽬の引数、またはprintの*を書式に置き換える
write(*,ʼ(i5)ʼ) ivar
! 5桁までの整数を表⽰
write(*,ʼ(3f15.8)ʼ) x, y, z ! 実数を15桁で、⼩数点以下は8桁として3つ表⽰
write(*,ʼ(2i5,3f15.8)ʼ) i, j, x, y, z ! 5桁までの整数を2つ表⽰、その後15桁,⼩数点以下8桁で実数を3つ表⽰
編集記述⼦

形式

意味iiw

幅wの整数

ffw.d

幅w,⼩数点以下d桁の実数

eew.d幅w,⼩数点以下d桁の実数

aaw

幅wの⽂字列xx

空⽩//改⾏

write(*,ʼ(3x,i5)ʼ) 123
write(*,ʼ(f8.2)ʼ) 123.4567
write(*,ʼ(e8.2)ʼ) 123.4567
write(*,ʼ(a8)ʼ) ʻabcʼ

書式指定しない(*と書く)場合はデフォルトの書式が適⽤される(システム依存)_____123__123.45_0.12E+3_____ABC書式指定(Fortran)• 書式指定は⽂字列配列に代⼊したものを指定してもOK• writeの指定⼦はunit(装置番号を指定)、fmt (書式を指定)• ⽂字列操作で書式をプログラム実⾏中に決定したい場合に使える
real*8 :: a, bcharacter(50) :: format1
format1 = ʻ(a, f15.5)ʼ

! ⽂字列配列format1に書式を代⼊

write(unit=*, fmt=format1) “a = “, a ! 書式はformat1で指定する
write(unit=*, fmt=format1) “b = “, b書式指定(C)• printf, fprintfで出⼒の書式指定ができる。
サイズ指定なし

サイズ指定

整数%d%5d (5桁の整数)

実数%f%15.10f 全桁数15で⼩数点以下が10桁

実数(指数表⽰)%e%15.10e

⽂字%c⽂字列%s%10s (10桁の⽂字列)• scanf, fscanfでは単精度・倍精度実数も明⽰的に指定する
サイズ指定なし
整数%d

倍精度整数%ld

実数%f

倍精度実数%lf

バイナリ⼊出⼒(発展)• バイナリ⼊出⼒ (バイナリ=2進数)• 倍精度実数は10進数の形式 (1.00000E+02など)で出⼒すると情報が落ちる。(メモリ上では64ビット、仮数部と指数部に分けて2進数で保持)• ファイル⼊出⼒するときに2進数(バイナリ)のまま扱うことができる• ただしテキストとして開いて読むことはできない(0と1が並んでいるだけでありバイナリエディタが必要だが読めたものではない)。
• 計算の途中経過出⼒、途中から再開するときなどに使う。図にする必要のないデータの保存もバイナリで⾏うのが⼀般的
バイナリファイルに出⼒する
open(1, file=ʻoutput.datʼ, form=ʻunformattedʼ)
write(1) var ! unformattedの場合は書式なし出⼒
close(1)バイナリファイルから読み込む
open(2,file=ʻoutput.datʼ, form=ʻunformattedʼ)read(2) var! 書式なしのread⽂
close(2)fp=fopen(ʻoutput.datʼ, ʻwbʼ); //wbはバイナリ書き込み// varが倍精度実数の場合、//fwrite(データアドレス、データ⼀つのサイズ、個数、ストリーム)
fwrite(&var,sizeof(double),1,fp);
fclose(fp);
fp=fopen(ʻoutput.datʼ, ʻrbʼ);// rbはバイナリ読み込み
fread(&x, sizeof(double),1,fp);//xに倍精度実数データを格納
fclose(fp);グラフ作成出⼒するときはgnuplotなどで読み込みやすい形式でgnuplotでは⼀⾏ずつデータを読み込んで特定の列と特定の列をx, yとしてグラフに描画
y=f(x)を0から10までの領域で書きたい場合 (関数f(x)は⽤意されていると仮定)
f(x)の値だけではなくxの値も描画のためには必要
open(10,file=“fx.dat”)
x = 0.0d0
dowrite(10,*) x, f(x)x = x + 1.0d-2
if( x > 10.0d0) exit
end doclose(10)fp=fopen(“fx,dat”,”w”);
for( x = 0.0; x<=10.0;x+=0.01){
fprintf(fp,“%f %f ¥n” , x, f(x));}
fclose(fp);

刻み幅は0.01としているが図にするときになめらかに⾒える程度に選べば良い。
標準出⼒に出⼒してもいいが、プログラムの他の場所で標準出⼒を使うかもしれないのでグラフに必要なデータ以外と混在しないように独⽴のファイルに出すほうがよい。

演習• ファイル⼊出⼒ (15)
• 3x3の⾏列を2つのファイルから2つ読み込んで⾏列積を計算、結果を他のファイルに出⼒• グラフ作成 (16,17)• (16) gnuplotで読み込めるデータファイルの作成• (17) ロジスティック写像