自分用 Fortran program sample

 




module による pi の定義

  • pi などプログラム内で共通で用いる定数などは,module で定義しておきます.
  • ここでは pi の値は C 言語の math.h に定義されている M_PI の値を用いています.
  • module を使う場合は,プログラム本体で implicit none の前に use により module 名を記述します.
module defpi
    implicit none
    real(8),parameter::pi=3.14159265358979323846D0
end module defpi

program f90_for_basic
    use defpi
    implicit none
    .....
    .....
    .....
end program f90_for_basic


コマンドラインからの入力

  • gfortran で使える機能です.
  • プログラム本体で組み込みサブルーチン getarg() を用いることにより,コマンドラインから文字列を読み込みます.
call getarg(1,dummy)
call getarg(2,fnameR)
call getarg(3,fnameW)

実行用スクリプトの事例は以下のとおり.

./f90_for_basic 4 inp_dat.txt out_dat.txt
実行プログラム:f90_for_basic
dummy=4
fnameR=inp_dat.txt
fnameW=out_dat.txt


文字列を数値に変換

文字変数 dummy に格納されている文字列を,数値変数 ndata に変換します.

read(dummy,*) ndata


行数不明のファイルからの読み込み

  • ファイル fnameR に格納されたデータの行数が不明の場合,iostat を用いて eof を検知し,ループから抜けます.
  • 整数変数 io の値は以下のとおり.なお整数変数 io の宣言を忘れないように!
io 0 負値正値
意味 正常eofエラー
  • 下の事例では,nn を予想されるデータ行数より確実に大きい値として,do ループを用いています.
  • ループを抜けた後,行数を整数変数 nd に格納します.
open(11,file=fnameR,status='old')
    read(11,'(a)') strcom
    do i=1,nn
        read(11,*,iostat=io) str(i)
        if(io<0)exit
    end do
close(11)
nd=i-1


アンダーバーを空白に変換

  • 入力を csv ファイルから行う場合でも,Fortran では空白が含まれているとそれをデータ区切りとして認識します. このため数値と 'Surge Tank' のような空白を含む文字列が1行に存在する場合,予め空白をアンダーバーにしておき, あとから空白に置き換える方が便利な場合があります.
  • このため,アンダーバーを空白に変換するサブルーチンを作りました.(例:This_is_a_pen. => This is a pen.)
  • サブルーチンは以下のとおり.
subroutine rep_ub(s)
    character (*), intent (inout) :: s
    integer i
    do i = 1, len(s)
        if (s(i:i)=='_') s(i:i)=' '
    end do
end subroutine rep_ub

使用法は以下のとおり.str(i) に格納された文字列を,文字列変数 dummy にコピーし,サブルーチン rep_ub( ) を呼びます. 処理完了後,書き換えられた文字列変数 dummystr(i) にコピーします.

do i=1,nd
    dummy=str(i)
    call rep_ub(dummy)
    str(i)=dummy
end do


連番ファイルの生成と書き込み

  • do 文の中で,連番ファイルを生成します.
  • ここでのファイル名は,_test_01.txt, _test_02.txt, _test_03.txt, ... という形でつけられ, ファイル名をしめす文字列変数 filename に格納され使用されます.
do i=1,nd
    write (filename,'("_test_",i2.2,".txt")') i
    open(13,file=filename,status='replace')
    .....
    .....
    close(13)
end do


csv ファイルの書き出し

  • 装置番号 12 で新規ファイル fnameW を生成しデータを書き込みます.
  • ここでは数値 datax(j) を コンマ(,)付き e15.7 で,文字列変数 dummy に書き込み,これを連結していきます.
  • 書き込み時は,adjustl( ) で左詰めにし,trim( ) で右側の空白を出力しないようにします.
  • サブルーチン del_spaces( ) は,次項目で紹介している「文字列に含まれる全ての空白を削除する」サブルーチンです.
  • write(6,'(a)') のように装置番号を 6 とすれば,通常は画面出力になり,途中経過監視などに使えます.
open(12,file=fnameW,status='replace')
    write(12,'(a)') trim(adjustl(strcom))
    do i=1,nd
        linebuf=''
        do j=1,ndata
            write(dummy,'(",",e15.7)') datax(j)
            linebuf=trim(adjustl(linebuf))//dummy
        end do
        call del_spaces(linebuf)
        write(12,'(a)') trim(adjustl(str(i)))//trim(adjustl(linebuf))
    end do
close(12)


文字列に含まれる全ての空白を削除する

  • 「csv ファイルの書き出し」で示したように,出力を csv 形式で行う場合,文字列に含まれる空白を削除したい場合があります. こ場合に以下のサブルーチンが利用できます.
  • このサブルーチンは 'nag Fortran入門' (www.nag-j.co.jp/fortran/index.html) に掲載されているものを使用させていただいております.
  • 使用法は,削除したい空白を含む文字列をサブルーチン del_spaces( ) に渡すだけです.
  • write 文の中では trim( ) を用いて右側の空白を出力しないようにします.
subroutine del_spaces(s)
    character (*), intent (inout) :: s
    character (len=len(s)) tmp
    integer i, j
    j = 1
    do i = 1, len(s)
        if (s(i:i)==' ') cycle
        tmp(j:j) = s(i:i)
        j = j + 1
    end do
    s = tmp(1:j-1)
end subroutine del_spaces


pic
inserted by FC2 system