FortranのTips
まだまとまっていませんが・・・。
型変換
integer型の数値を文字列に変換する
character(32) :: c integer :: i = 5 write( c, * ) i c = adjustl( c )
文字列をinteger型の数値に変換する
character(32) :: c = "123" integer :: i read( c, * ) i
桁数を指定してinteger型の数値の先頭を0で埋める
character(5) :: c integer :: i = 5 write( c, '(i5.5)' ) i write( *, * ) c
文字列処理
大文字を小文字へ変換する
function lc( str ) character(*),intent(in) :: str character(len(str)) :: lc integer :: i do i=1, len_trim(str) if( str(i:i) >= 'A' .and. str(i:i) <= 'Z' ) then lc(i:i) = char(ichar(str(i:i))+32) else lc(i:i) = str(i:i) end if end do end function lc write(*,*) lc('This is a pen')
ファイル名から拡張子を取り出す
-
文字列の最後の . を探して、それ以降を取り出しているだけ。".tar.gz" みたいな拡張子には対応していない
integer :: p character(1024) :: fname, ext p = scan( fname, '.', .true. ) ext = fname(p+1,len(trim(fname))) write(*,*) trim(ext)
関数
sign(v1,v2)
v2>=0 なら |v1|、v2<0 なら -|v1| を返す。
modとmodulo
mod(v1,v2) modulo(v1,v2)
どちらも剰余を返すが、modはv1、moduloはv2の符号に従う。
ファイル操作
ファイルサイズを取得する (Fortran 2003)
もっとうまいやり方があるかもしれませんが・・・。
integer :: size open( 10, file='test.dr', form='unformatted', access='stream', & & status='old', action='read', position='append' ) inquire( 10, pos=size ) size = size - 1 write(*,*) size close(10)
テキスト読み込みの際に改行を考慮しない
read( 10, '(A6)', advance='no' ) c ! 最初の6文字以外は次のreadのために保持する read( 10, '(A6)', advance='yes' ) c ! 最初の6文字以外は捨てる
出力の繰り返し
write(*,'(100A13)') ('-9999 ',i=1,20)
- 100個繰り返さなくてもエラーにはならない。
出力バッファリングを止める(gfortran限定)
$ export GFORTRAN_UNBUFFERED_ALL=y
手続きポインタ(Procedure Pointers)
- つまりCで言うところの関数ポインタ
program test abstract interface function func( x ) import real :: x real :: func end function func end interface procedure(func1), pointer :: p => NULL() p => f1 write(*,*) p(2.0) p => f2 write(*,*) p(2.0) contains function f1(x) real f1, x f1= x**2 end function f1 function f2(x) real f2, x f2= x**3 end function f2 end program test
-
メモ(あまり自信はないが・・・)
- abstract interface で手続きの形状(引数)を決めている。
- importは上位スコープの変数を使えるようにする。上の例では不要かも。
- f1,f2は内部手続き(=contains中)にしたほうがよさそう。外部手続きだとコンパイル順序の関係で?未定義であるとおこられる。
- 引数なし手続きを設定した場合は procedure(), pointer :: p => NULL() でOK
Tips: ポインタが結合しているか調べる
associated(p)
- ポインタpが結合していれば .true.、NULL()など結合していなければ .false. を返す。
異なる型に対応したサブルーチン
module中の場合
interface func module procedure func1 module procedure func2 end interface ... subroutine func1(x) real(4) :: x ... end subroutine func1 subroutine func2(x) integer :: x ... end subroutine func2
時刻
実時間を得る
integer :: timer(8) call DATE_AND_TIME(values=timer) write(*,*) timer(1:3) ! 年・月・日 write(*,*) timer(4) ! UTCからの時差 write(*,*) timer(5:8) ! 時・分・秒・ミリ秒