[itbase2018]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, * ) "Inputted number:", val  ! 読み込んだ値の表示

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

end program inputfromkb

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

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

$ ./inputfromkb
 Input a number:
123.4567                          <- キーボードから数値を入力する
 Inputted number:   123.456703    <- プログラムが数値を出力
 Input two numbers:
123.4567   890.123                <- キーボードから数値を入力する
 Inputted 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 桁
f5.2実数全 5 桁, 小数点以下 2 桁全 5 桁には小数点と空白を含む
e10.2実数全 10 桁, 小数点以下 2 桁 (mmE+-nn の形式)全 10 桁には小数点と空白と指数の E, + も含む
a1文字列 1 文字
x空白 1 文字空白文字 " " を書いて a1 と書式指定しても同じ.

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

書式指定意味使用例123 を出力した時の結果
i整数型i5" 123"
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 文を指定するために使われているラベルです. 上の例では, 101 番の format 文は一つの write 文でしか使っていませんが, 複数の 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:2019/01/24 11:28:23
Keyword(s):
References:[[itbase2018]惑星学実験実習の基礎II]