[itbase2019]Fortran 実習 入出力

データ解析や数値計算には入力データが必要なことが多いでしょう. また, 解析結果や計算結果は何かしらの形で出力しなければなりません. ここでは, Fortran での入出力を簡単に体験してみましょう.

注意

  • 前回説明したように, Fortran のプログラムの実行のためには, エディタでプログラムを書くだけでなく, 「コンパイル」する必要があります.
  • 今回の資料では, プログラムのコンパイル方法の詳細は説明していません.
  • 意味が解らなければ前回の資料を復習しましょう.

入出力文

入力文

Fortran では下に示す入力の命令が用意されています.

命令入力元使用例
readキーボードとファイルread( 5, * ) num

ここで read の引数の "5" と "*" はそれぞれ「装置番号」と「書式」を 表しています. これらについては後で説明します.

なお, read 文には, 装置番号と書式の他にも様々な指定が可能です. 興味があれば調べてみると良いでしょう.

出力文

Fortran では下に示す出力の命令が用意されています.

命令出力先使用例
print画面print *, 5.0
write画面とファイルwrite( 6, * ) 5.0

print は画面にしか出力できませんが, write はそれに加えて ファイルに出力することもできますので, write の方が用途が 広いことになります.

ここで print および write の引数の "6" と "*" はそれぞれ 「装置番号」と「書式」を表しています. これらについては後で説明します.

装置番号

read と write で入出力する際に, 入力元や出力先を 指定するために使うのが装置番号です.

上の read/write の使用例では, 5 と 6 がそれらに対応します. 装置番号の 5 と 6 は特別な番号で, 5 はキーボード (「標準入力」とも呼びます) を表し, 6 は画面 (「標準出力」とも呼びます) を表します.

従って,

read( 5, * ) num

write( 6, * ) 5.0

はそれぞれ, キーボード (標準入力) からの読み込みと画面 (標準出力) への 出力を表しています.

5, 6 以外の数字は, ユーザが決めることができて, ファイルに割り当てて 入出力に使います.

キーボードから入力と画面への出力の例

下のようなプログラムを inputfromkb.f90 というファイル名で作成して 実行してみましょう.

program inputfromkb

  implicit none

  real :: val
  real :: val2

  write( 6, * ) "Input a number:"        ! 入力を促す
  read ( 5, * ) val                      ! キーボード (装置番号 5) から読み込み
  write( 6, * ) "Input number:", val     ! 読み込んだ値の表示

  write( 6, * ) "Input two numbers:"     ! 入力を促す
  read ( 5, * ) val, val2                ! キーボード (装置番号 5) から読み込み
  write( 6, * ) "Input numbers:", val, val2  ! 読み込んだ値の表示

end program inputfromkb

この例では, 一つ目の write 文で数値の入力を促し, read で値を読み込み, 二つ目の write 文で入力した数値を表示しています.

このプログラムをコンパイルして作った実行ファイル inputfromkb を 実行すると下のようになります. (プログラムは "Input a number:" と表示して数値の入力を促しますので, キーボードから数値を入力する必要があります.)

$ ./inputfromkb
 Input a number:
123.4567                          <- キーボードから数値を入力する
 Input number:   123.456703    <- プログラムが数値を出力
 Input two numbers:
123.4567   890.123                <- キーボードから数値を入力する
 Input numbers:  123.456703   890.123    <- プログラムが数値を出力

書式

上に書いた read, print, write の使用例に現れる "*" は「書式」の指定 を表します. ここで言う書式とは, 例えば数値を出力する際に, 何桁で出力するのかを 意味します.

上の例で示している "*" の指定は最も簡単で, 「適当に」入出力する指定です.

例えば, 下のプログラムを outputnum.f90 というファイル名で作成し, コンパイルして実行してみましょう.

program outputnum

  implicit none

  integer :: num
  real    :: val

  num = 1
  val = 1.234567890

  write( 6, *                                 ) num, ",", val, ",", val
  write( 6, "(i5, x, a1, f5.2, x, a1, e10.2)" ) num, ",", val, ",", val

end program outputnum

例えばこのプログラムをコンパイルして作った実行ファイル outputnum を 実行すると下のようになります.

$ ./outputnum
           1 ,   1.23456788     ,   1.23456788
    1 , 1.23 ,  0.12E+01

書式に "*" を指定したことで, 1 行目は「適当に」出力されていますが, 2 行目は "(i5, x, a1, f5.2, x, a1, e10.2)" に従って出力になっています. この指定のそれぞれは下のような意味があります.

"(i5, a1, f5.2, a1, e10.2)" の指定は, i5 が num に対する書式指定, x が空白 1 文字を書く指定, a1 が一つ目の "," に対する書式指定, f5.2 が一つ目の val に対する書式指定, a1 が二つ目の "," に対する書式指定, x が空白 1 文字を書く指定, e10.2 が一つ目の val に対する書式指定に対応します. それぞれ下のような意味になります.

書式指定意味備考
i5整数全 5 桁
i5.5整数全 5 桁値が 5 桁に満たない場合は 5 桁になるようにゼロで埋められる
f5.2実数全 5 桁, 小数点以下 2 桁全 5 桁には小数点と空白を含む
e10.2実数全 10 桁, 小数点以下 2 桁 (mmE+-nn の形式)全 10 桁には小数点と空白と指数の E, + も含む
a1文字列 1 文字
x空白 1 文字空白文字 " " を書いて a1 と書式指定しても同じ.

その他のものも含めると, 指定に使う文字 (変換記号) には下のような ものがあります.

書式指定意味使用例123 を出力した時の結果
i整数型i5" 123"
i5.5"00123"
f実数型f7.2" 123.00"
e実数型, mmE+-nn の形式e9.2" 0.12E+03"
d倍精度実数型, mmE+-nn の形式d9.2"0.12D+03"
l論理型--
a文字型--
x空白--

注意: 上の表における, 「123 を出力した時の結果」にある ダブルクォーテーションは出力されません. 数値の前に空白が入ることを 表すために書いています.

また, 同じ指定を繰り返す時には, まとめて指定することもできます. 例えば, 下のような出力,

write( 6, "(i5, x, a1, i5, x, a1, e10.2)" ) num, ",", num, "," val

では, i5, x, a1 が 2 回繰り返されています. これらはまとめて,

write( 6, "(2(i5, x, a1), e10.2)" ) num, ",", num, ",", val

とすることもできます.

format 文

書式指定が長くなる場合, あるいは, 同じ書式を何度も使う場合には, 下のように書式を別の行に書くこともできます.

program outputnumformat

  implicit none

  integer :: num
  real    :: val
  real    :: val2

  num = 1
  val = 1.234567890
  val2 = 0.987654321

  write( 6, *   ) num, ",", val, ",", val
  write( 6, 101 ) num, ",", val, ",", val
  write( 6, 101 ) num, ",", val2, ",", val2

101 format( i5, a1, f5.2, a1, e10.2 )

end program outputnumformat

ここで使われているのは format 文で, 書式指定のための命令文です. そして, 101 は, その format 文を指定するために使われているラベルです. 複数の write 文で同じ format 文を使うこともできます.

このような書式指定をすることで, 出力の見た目を整え, 結果を わかりやすく示すことができます.

練習問題

上に示したプログラム outputnum.f90 を変更して, プログラムの実行結果の出力が下のように 1 行目と 2 行目が 揃うように書式指定と出力変数を工夫してみましょう. (やり方は複数あり得ます. 思いついた方法でやってみましょう.)

出力結果の例

$ ./outputnum
           1 ,   1.23456788     ,   1.23456788
           1 ,   1.23           ,   0.12E+01

ファイルからの入力/への出力

ファイルを開く

Fortran でファイルを開くためには例えば下のような open 文を用います.

open( 11, file = "test.txt", status = "unknown" )

一般的には,

open( <装置番号>, file = <ファイル名>, status = <ステータス>, ... )

となります.

<装置番号> は, read 文や write 文で説明したものと同じものです. つまり, open は, ファイル名と装置番号を関連付けており, ファイルからの入力やファイルへの出力には, その入力元/出力先の ファイルに対応した装置番号を指定します.

ステータスには下に示すような種類を指定することができます.

ステータス意味
unknown「適当に」開く (読み込みでも書き込みでも)
old読み込み用に開く
replace書き込み用に開く

open 文には, 装置番号, ファイル名, ステータス以外にも, 様々な 指定が可能です. それらを使うことでかなり柔軟な処理が可能になります. ここでは詳細を説明しませんが, 興味があれば調べてみると良いでしょう.

ファイルを閉じる

Fortran でファイルを閉じるためには下のような close 文を用います.

close( 11 )

一般的には,

close( <装置番号> )

となります.

<装置番号> は, read/write/open 文で説明したものと同じものです. open 文で開いたファイルを閉じるときに, 対応する装置番号を指定します.

ファイルへの出力の例

下のようなプログラムを outputtofile.f90 というファイル名で作成して 実行してみましょう.

program outputtofile

  implicit none

  real :: val

  write( 6, * ) "Input a number:"               ! 入力を促す
  read ( 5, * ) val                             ! キーボードから入力

  open( 11, file="output.txt", status="replace" ) ! ファイルを開く
  write( 11, * ) val                              ! ファイルへの出力
  close( 11 )                                     ! ファイルを閉じる

end program outputtofile

このプログラムでは, キーボードから入力した数値をファイル, output.txt, に 出力しています. 実行した後で, ファイルができているかどうか, また, ファイルの中に 数値が保存されているかどうかを確認しましょう.

ファイルからの入力の例

ファイルからの入力を試すために, 入力データを用意しましょう.

emacs を使って, input.txt という名前のファイルに下の内容を書き込みましょう.

5   105
10  110
15  115

また, 下のようなプログラムを inputfromfile.f90 というファイル名で 作成し, 実行しましょう.

program inputfromfile

  implicit none

  integer :: val, val2

  open( 11, file="input.txt", status="old" )  ! ファイルを開く
  read ( 11, * ) val                          ! ファイルから数値を一つ入力
  write(  6, * ) val                          ! 画面に数値を出力
  read ( 11, * ) val
  write(  6, * ) val
  read ( 11, * ) val, val2
  write(  6, * ) val, val2
  close( 11 )

end program inputfromfile

このプログラムは, input.txt から数値を入力し, それを画面に出力しています. read 文一つにつき, 一つの数値を読んでいることに注意しましょう. read 文では基本的には 1 行ずつ読み込みます.

練習問題

上で使った inputfromfile.f90 を基にして, input.txt に保存されている 数字を読み込み, その和を求めて, その値をファイル output.txt に 出力するプログラムを作りなさい.

Last modified:2020/01/16 09:14:43
Keyword(s):
References:[[itbase2019]惑星学実験実習の基礎II] [[itbase2020]惑星学実験実習の基礎II]