[Qiita@earth06: 数値モデルにでてくるFORTRAN77文法~完結編#NAMELISTによる変数への値の代入]
(https://qiita.com/earth06/items/f8d6e2d504b24af0cbb7#namelist%E3%81%AB%E3%82%88%E3%82%8B%E5%A4%89%E6%95%B0%E3%81%B8%E3%81%AE%E5%80%A4%E3%81%AE%E4%BB%A3%E5%85%A5)
基本
コード
program main
implicit none
character(len=256), parameter :: nml_path = './test.nml'
integer, parameter :: unit = 11
integer :: a = 1, b = 2
namelist /test/ a, b
open(unit, file=trim(nml_path), status='old')
read(unit, nml=test)
close(unit)
write(*, *) 'a', a
write(*, *) 'b', b
end program main
ネームリストに該当する変数が存在しない場合,単純に読み込みがスキップされるだけでエラーは発生しない
→デフォルト値を設定しておき,それを変更する場合のみネームリストを使う,ということができる
ネームリスト
書式
&{ネームリスト名前}
で始め,/
または&end
で結ぶ.
&test
a = 11
b = 12
/ ! &endでも良い
改行・カンマはなくとも良い
以下はいずれも動作する.但し,/
と&end
のどちらかは必ず必要.
&test a = 11 b = 12 /
&test a = 11, b = 12 /
&test a = 11 b = 12 &end
&test a = 11, b = 12 &end
私見:
改行して書くなら終わりは/
でも&end
でも良いと思うが,
1行に書くなら&end
の方が視認性高そう(/
だと書き忘れたときに気が付きにくい).
複数のネームリストがある場合,最初にヒットしたものが有効になる
1つ目のネームリストでbを与えない場合,2つ目からbを読み取る,ということはない.
&test a = 11, b = 12 &end
&test a = 21, b = 22 &end
! -> a = 11, b = 12
&test a = 11 &end
&test a = 21, b = 22 &end
! a = 11, b = 2
ネームリストのコメントアウト
変数のコメントアウト
&test
!a = 11
b = 12
/
! -> a = 1, b = 12
aとbを共にコメントアウトしてもOK (-> a = 1, b = 2).
改行のないネームリストとは相性が悪いが,
bをコメントアウトするときはa = 11!, b = 12
でもa = 11, !b = 12
でも良い.
ネームリスト自体のコメントアウト
最初に示したコードだと,ネームリスト自体&test
を削除するのはNG.
しかし,以下の通りIOErrorを陽に処理すると,この場合でも動作する(ネームリストが存在しない場合,デフォルト値のまま).
integer :: ios
read(unit, nml=test, iostat=ios)
配列の読み込み
2019年7月24日:ページ分割
ネームリスト内では(/
や[
などで囲まず,配列の要素をそのまま列挙する.
&nml_test
a = 1,2,3
/
- プログラム内で
/ネームリスト名/
として指定する際には,(:)
は付けない - ネームリストより配列が大きい場合でも問題なし
- ネームリストより小さい場合にはエラー
- 未割り付けの配列に読み込むことは不可
従ってネームリスト内の配列の大きさが分からない場合,
- 十分大きな配列を用意する
- センチネル値(ありえない値→その値になったらループを終える)を予め全要素に代入しておく
program main
implicit none
integer, allocatable :: a(:)
character(len=256), parameter :: nml_path = './test.nml'
integer , parameter :: nml_unit = 11, nml_size = 3
namelist /nml_test/ a ! "a(:)"と書くとコンパイラを通らない
allocate(a(nml_size)); a(:) = 0
open(nml_unit, file=trim(nml_path), status='old')
read(nml_unit, nml=nml_test)
close(nml_unit)
write(*, *) a(:) ! 1 2 3
deallocate(a)
allocate(a(nml_size+1)); a(:) = 0
open(nml_unit, file=trim(nml_path), status='old')
read(nml_unit, nml=nml_test)
close(nml_unit)
write(*, *) a(:) ! 1 2 3 0
deallocate(a)
allocate(a(nml_size-1)); a(:) = 0
open(nml_unit, file=trim(nml_path), status='old')
read(nml_unit, nml=nml_test) ! forrtl: severe (18): too many values for NAMELIST variable
close(nml_unit)
write(*, *) a(:)
deallocate(a)
open(nml_unit, file=trim(nml_path), status='old')
read(nml_unit, nml=nml_test) ! forrtl: severe (174): SIGSEGV, segmentation fault occurred
close(nml_unit)
write(*, *) a(:)
deallocate(a)
end program main