WANtaroHP (F90 Tips)

 

Contents

π (pi) の値をモジュールを使って定義する

  • 管理人は,C 言語の math.h に定義されている M_PI の値を用いています.
module defpi
implicit none
real(8),parameter::pi=3.14159265358979323846D0
end module defpi

program f90_test
use defpi
implicit none
.... .... ....
end program


コマンドラインから文字列を取得する

  • gfortranで使える機能です.
  • コマンドラインにおいて,実行ファイル名に続いて入力する文字を,文字列変数として読み込みます.
call getarg(1,dummy)
call getarg(2,fnameR)
call getarg(3,fnameW)


文字列を数値に変換する

  • 文字列 dummy を数値 negv に変換します.
read(dummy,*) negv


数値を文字列に変換する

  • 実数 vec(i) を文字列 dummy に変換します.
  • ここでは文字列への変換時に,書式指定により,数字の前にカンマ(,)をつけ,15桁確保小数点以下7桁の書式で出力しています.カンマをつけて文字列とすることにより,文字列を結合して csv ファイルとして保存するときに活用できます.
write(dummy,'(",",e15.7)') vec(i)


連番ファイル名を生成して書き出す

  • do文の中で,連番ファイル名をつけながら出力します.
  • ここでのファイル名は,'_inp_xyz_01.txt','_inp_xyz_02.txt'という形でつけられ,ファイル名を示す文字列filenameに順次格納され使用されます.
do n=1,ntout+1
write (filename,'("_inp_xyz_",i2.2,".txt")') n
open(13,file=filename,status='replace')
do ne=1,NELT
i=kakom(ne,1)
write(13,*) x(i),y(i),tempe_s(i,n)
end do
close(13)
end do


行数の不明なファイルからデータを読み込む

  • 装置番号 11 として,既存のファイル fnameR を開きます.
  • データ行数が不明のため変数 io の値で読み込み行の有無を判断します.
  • ここでは,文字列配列 str について,文字数 mm=100,読み込み上限行数 nn=1000 の制限を設けていますので,do ループの範囲は 1 から nn までとし,ファイルの終端 EOF を確認したらループから抜け出るようにしています.
  • 読み込んだ行数は最後に変数 nd に格納します.
  • 整数変数 io の値は以下のとおり.
  • 0 正常
    負値EOF
    正値エラー
  • 整数変数 io の宣言を忘れないように!
integer,parameter::nn=1000,mm=100
character(len=mm)::str(1:nn)
integer::i,io,nd
character(len=50)::fnameR

call getarg(1,fnameR)

open(11,file=fnameR,status='old')
do i=1,nn
read(11,'(a)',iostat=io) str(i)
if(io<0)exit
end do
close(11)
nd=i-1


ファイル出力

  • 装置番号 12 に対し,新規ファイル fnameW を生成しデータを書き出します.
  • 文字列 str(i) の出力に際し,adjustl( ) で左詰めにし,trim( ) で右側の空白を出力しないようにします.
  • write(6,'(a)') のように装置番号を 6 とすれば,通常はコマンドプロンプトの画面出力になります.途中経過を監視する時などに使えます.
open(12, file=fnameW, status='replace')
do i=1,nd
write(12,'(a)') trim(adjustl(str(i)))
end do
close(12)


出力書式指定

  • 文字列変数 fmt3 に出力書式を指定します.
  • write 文で数値を fmt3 で指定した書式で,文字列変数 linebuf に書き出します.
  • 文字列変数 linebuf には十分な長さを与えておく必要があります.
fmt3="(i5,2(',',e15.7),3(',',e15.7))"
write(linebuf,FMT=fmt3) i,x(i),z(i),hvec(i),q0vec(i),hvec(i)


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

  • 出力を csv 形式で行う場合,文字列中に含まれる空白を削除したい場合があります. このような場合,del_spaces というサブルーチンを用いると便利です.
  • このサブルーチンは,こちらのサイト (Fortran入門) に掲載されているものを使用させていただいています.
  • 使用法は,削除したい空白を含む文字列変数 linebuf を del_spaces に渡すだけです.
  • write 文での出力時は,trim() により右側の空白を表示しないようにします.
call del_spaces(linebuf)
write (12,'(a)') trim(linebuf)
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


文字列に含まれるアンダーバーを空白に置き換える

  • 入力を csv ファイルから行う場合でも,Fortran では空白が含まれているとそれをデータ区切りとして認識します. このため,数値と空白を含む文字列が 1 行に存在するデータの場合,予め空白をアンダーバー ( _ ) にしておきあとから空白に置き換えるほうが便利な場合があります.この場合,rep_ub という自作サブルーチンを使って対応しています. (例:This_is_a_pen. ⇒ This is a pen.)
  • 使用法は,置き換えたい空白を含む文字列変数 dummy を rep_ub に渡すだけです.
  • 下の事例のように文字列の配列を扱う場合は,一度作業用変数(ここでは dummy ) にコピーし,変換後,もとの配列にコピーする必要があります.これは前述 del_spaces でも同様です.
dummy=str1(i)
call rep_ub(dummy)
str1(i)=dummy
subroutine rep_ub(s)
!Replaceing underbar with space
character (*), intent (inout) :: s
integer i
do i = 1, len(s)
if (s(i:i)=='_') s(i:i)=' '
end do
end subroutine rep_ub


pic
inserted by FC2 system