こんにちは。
この記事では、Fortranで動的割付けallocate
されている場合のcsv
形式の出力でつまづいた点を共有させていただきます。
##Fortranでcsv形式で出力する場合
x_out
をcsv形式を行う場合、下記の通りに記述します。
real(4) :: x_out(3)
character(256) :: linebuf
open (1, file='./your_outfile.csv', form='formatted', status='replace')
write(linebuf, '2(f7.2, ","), f7.2)') ! *** (書式設定)
call del_spaces(linebuf) ! *** (空白を詰めるサブルーチン)
write(1, '(a)') trim(linebuf)
close(1)
x_out(3)
と配列数が決まっている場合は、
Fortranの書式設定に(f7.2, ",")
のように記述して、小数点数字とカンマを記述しています。
※書式設定について
()
の前に数値を加えると書式設定が数値分反映されますが、配列数から一つ引いた分を記述しています。
配列数を全て加えると最後にカンマを残して出力されてしまうので、配列数から一つ引いた値を繰り返して、最後に独立して同じ書式を再び書いて、カンマをなくしています。
※サブルーチンについて
call del_spaces
のサブルーチンは、下記に記述している参考サイトから引用しております。
内容は、通常のwrite
では一つの出力の後に空白を出してしまうので、それを詰める機能となっています。
##本命の部分
以下、今回の状況になります。
上記と同様に、x_out
をcsv形式で出力したいと考えています。
上記との違いは,
Fortran内で動的割付をしており、shで配列の大きさを指定して渡し、出力したい点です。
以下、上手く行ったコードです。
nx = 40
today=$(date "+%Y%m%d%H%M")
./${prg} > ./log/${today}.log << EOF
&set_parm
nx = ${nx}
/
EOF
real(4), allocate :: x_out(:)
integer :: nx
character(4) :: cfmt_num
character(24) :: cfmt
character(256) :: linebuf
namelist /set_parm/ nx
read(5, nml=set_parm)
allocate(x_out(nx))
write(6,*) '-------------------------------------------------------'
write(6,*) '+++ Check Writing output system, '
cfmt = '(xx(F12.7, ","), F12.7)'
write(cfmt_num,"(I2)") nx-1
cfmt(2:3) = cfmt_num
open(2, file='./your_outfile.csv', form='formatted', status='replace')
write(linebuf, cfmt) x_out
call del_spaces(linebuf)
write(2,'(a)') linebuf
close(2)
write(6,*) ' && Successfuly output !!! '
この場合で、少し手間取った点は下記に記述しました。
- 書式設定内に変数を入れ込みたい
csv形式を出力したいので、コンマを記述する必要があります。
その際に配列数は動的なので、書式設定内も逐一変更しないで、変数を入れることで解決したいです。
cfmt = '(nx-1(F12.7, ","), F12.7)'
! *** →もちろん、ダメだった。
cfmt = '(' + str(nx) + '(F12.7, ","), F12.7)'
! *** →イメージとしては、こんな感じにしたい。
※ 書式設定内は文字列なので、配列数の整数型の数字を文字列に変換させて結合したいです。
この時、壁は二つあります。
- shから受け取った整数を、文字列に変換する。
→その際には、@implicit_noneさんの記事を参考にさせていただきました。 - 文字列を結合する。
→fortranの文字列結合には、//
がありますが2つ以上の連結では使用できませんでした。
そのため、あらかじめ数字が入るところにxx
を入れて、そこにcfmt(2:3) = cfmt_num
受け取った整数を文字列化した者を入れることで対応しました。
これらを行った結果、無事に今回のねらいを実装することができました。
より良い書き方などお気づきになった方はコメント等でご教授いただければ幸いです。
同じような点で困った人の手助けになれたら幸いです。
最後まで見ていただき、ありがとうございました。
##参考
・Fortran Tips集: csvファイルを書き出す方法
https://www.nag-j.co.jp/fortran/tips/tips_writeCSV.html
・Fortranで整数を文字列に変換する
https://qiita.com/implicit_none/items/39018f2848b5237fc3ea