ログイン

FortranのTips

Top / Fortran

Japanese / English

まだまとまっていませんが・・・。

型変換

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)  ! 時・分・秒・ミリ秒

リンク