• 締切済み

FORTRAN

まだ素人で。試行錯誤行っています。 現在、アメダス(一ヶ月平均)を読み取り、必要に応じて計算するようなプログラムを作っています。しかし、アメダスはバイナリのため、それを読めるようなプログラムが必要なのですが、 ===AMEDAS DATA FILE NAME OF THE MONTH (UNCOMPRESSED) 'Amd1976.01' ===INDEX FILE OF THE YEAR =========================== 'idx1976.01' ===OUT PUT FILE NAME============================== 'pre1976.01' ===SORT OF DATA, 50:presipitation, 60:wind direction, 70:wind speed, 80:insolation, 90:temperature, 67:wind direction+speed 50 ==BEGIN AND END OF STATION NUMBER===================== 10000 99000 で、指定するとそのファイルのバイナリが読めるようになっています。 それで順序は、 f77 ame_M2.for → ./a.exe → g95 1976search.f90 → ./a.exe で行っております。ame_M2.forはバイナリを読むプログラムです。1976search.f90は自分が作った、アメダスデータを必要に応じて計算をするプログラムです。ただ、これでは、1976年1月(一ヶ月分)のデータだけ呼んで計算する形なので、今、1976年1月から1999年12月までを一気に読んで計算させたいんです。どうすればよいでしょうか??今自分でも考え中なのですが、なにかアドバイス、案などありましたら教えてください。できれば、上の指定するファイルとバイナリを読むプログラムをほぼいじらないで、自分の作った計算プログラムだけで、行うことは可能なのでしょうか?? program main integer :: day,hour(1:24) integer :: i,j,n open(11, file='pre1976region.csv', status = 'unknown') open(10, file='pre1976.01', status='old') open(10, file='pre1976.02', status='old') do j = 1,30000000000000000 read(10,"(11x,I5,62x)", iostat=io) number if(io < 0) exit if (number == 53376 ) then do i = 1,40 select case(i) case(1:2,8,14,20,26,32,38,40) read(10,*) case default read(10, "(I2,1x,3(6I3,1x),6I3)") day, hour(1:24) where (hour(1:24) == 999) hour = 0 write(6,*) day,sum(hour) end select end do end if end do close(10) close(11) end program これが、僕が作ったプログラムでして、numberに地点番号を入力すればその地点の一月の毎日の雨の量がわかるようになっています。これをまず、20年近く読んで、たとえば東京をみたいとすると、その東京だけの20年分を見るようにしたいんです。 言葉足らずで、これを見せないと助言できないとかがありましたら、お教えください。

  • ryoji
  • お礼率57% (90/156)

みんなの回答

  • A88No8
  • ベストアンサー率52% (834/1602)
回答No.3

こんにちは >ファイルが違うのでcygwin上ではcd /d/1977に移るようにしなければいけませんよね  以下にファイル名にUNIX系OS上でのパスを含める例を書きます。 open(11, file='./path/pre1976region.csv', status = 'unknown')  応用として上記例で文字列定数'./path/pre1976region.csv'に文字列型変数を使えるならばパス(pathの部分は格納場所のパスに置換える)を含めたファイル名をあらかじめ準備しreadして宣言することも可能になるでしょう?ということをいいたかったのですが..  混乱するということであれば一度データをREAD/WRITEして変換しアメダスから切り離した統合した独自データとしてファイルで持つ処理を実現した方が早道ではないですか?  アメダスのデータをバイナリを含めて取り込むプログラムが出来ているのですから同じ路線で構築できるようにした方が質問者さんが速く目的にたどり着けそうです。 今はたどり着いてから全体をまとめることを構想することをお奨めします。 >例えば、ここでの配列とは?12ヶ月とかでいいんでしょうか?iは、01から12とあって01の表現はどうすれば?1と扱って大丈夫なのでしょうか?  ヒントになるかどうかわからないけどfortranの場合は、ループ変数と文字列定数は分けた方が簡単かも.. INTEGER :: i CHARACTER(LEN=2)::month(1:12) = (/ '01','02','03','04','05','06','07','08','09','10','11','12' /)  DO i = 1, 12   PRINT *, month(i)  END DO END

  • A88No8
  • ベストアンサー率52% (834/1602)
回答No.2

こんにちは >現在1976というファイルに1976.01、1976.02、1977というファイルに1977.01、1977.02という感じでアメダスデータがある状態です。まずそれをひとつにまとめるということでしょうか?  アメダスデータは、どんどん増えていくという前提であらかじめ読むべきファイル名をテキストファイルに定義しておき、実行時にファイル名を取得して読み込んでいくような作りにして置けば自由度が高いかなというアイデアです。  しかし、いつも20年近く前からの開始のデータで開始時期を変更はないならば、一つのファイルににまとめてしまうのも良いアイデアだと思います。  あと新たに増えたデータファイルはどうするか? (1)20年近く前からの開始のデータファイルに新データをアペンドする処理を別に実行してから処理を回す。 (2)20年近く前からの開始のデータファイルと新データファイルをテキスト形式の定義ファイルにファイル名を定義し、それを元にファイルを読み込んで処理を回す。  (1)か(2)のいずれかですよね。 >バイナリを読むファイルはどうすうればよいでしょう?  すいませんが意味が分かりません。データファイルを読み込んで立派に処理を実現されているので解決済みの問題と受け止めています。  バイナリの場合カンマや空白文字で区切られていること自体考えられないので入力ファイルのデータ構造が判らないと何ともいえないですね。  外していたらごめんなさい。

ryoji
質問者

お礼

ありがとうございます。ちょっと混乱しています。テキストファイル?テキストデータ?それに1976ファイル、1977ファイルを読むようにプログラムを書くということですよね?現在cygwinで行っていますが、1976ファイルを読み終わると、ファイルが違うのでcygwin上ではcd /d/1977に移るようにしなければいけませんよね?そいうこともテキストデータ内のプログラムで行えるのでしょうか?バイナリのほうですが、現在、毎回一ヶ月ごとにAme.inというテキストデータで読む月を指定し、それを読んでバイナリを読めるように直すプログラムをコンパイルし実行し、できたファイルを計算するのですが、その実行も含めてテキストデータのプログラムに定義する(できる)ということでしょうか?それができても少なくとも、一ヶ月読んで次の一ヶ月には、cygwin上でenterキーをコンパイル、実行するために2回押す必要がありますよね?言葉だとうまく表現できなくてすいません。なんとなくわかってきてるのですが。うまく書けません。人の質問を調べていると、例えばwrite(配列,'1976.''i')k、とメモリーの配列に書き込み、このiにdo パラメータのkを当てれば、1重のループで順次開けると。例えば、ここでの配列とは?12ヶ月とかでいいんでしょうか?iは、01から12とあって01の表現はどうすれば?1と扱って大丈夫なのでしょうか?iにdoパラメターのkを当てるとは?do i=1,kということでしょうか? すいません。話がずれてしまい。再度こたえれるところだけでもかまいませんので、お教えいただけるとありがたいです。すいません、お願いします。

  • A88No8
  • ベストアンサー率52% (834/1602)
回答No.1

こんにちは  考え方としてファイル名をプログラムの中に埋め込まず、特定のイニシャルファイルを作ってその中にテキストデータとしてファイル名を登録しておき、ファイル名を読み込み、そのファイルをオープンしデータを読み込みながら繰返し集計したらいかがかと思います。  質問者さんに貼ったプログラムをメンテナンスできる力があれば、上記は容易だと思いました。

ryoji
質問者

お礼

ありがとうございます。ちょっとまだ未熟者で少しわからないとこがあるのですが、現在1976というファイルに1976.01、1976.02、1977というファイルに1977.01、1977.02という感じでアメダスデータがある状態です。まずそれをひとつにまとめるということでしょうか?バイナリを読むファイルはどうすうればよいでしょう?すいませんが、もう少し教えてもらえないでしょうか?お願いします。

関連するQ&A

  • FORTRANについての質問です。

    FORTRANについての質問です。 現在、二つのファイル(a.csv,b.csv)を読んで,a.csvのファイル内の地点番号とb.csvのファイル内の地点番号が一緒なら抜き出すというプログラムを書きたいのですが、途中で抜け出せなくなってしまいました。下に使用しているファイルの中身を、ごくわずかですが載せておきます。 b.csvのほうは、年別で33個のファイルに分けられています。 ----------------------a.csv------------------------------------------ 30 23226 1977 大野 31 13311 1978 増毛 31 14101 1978 新篠津 31 15251 1978 芦別 31 16281 1978 真狩 31 17076 1978 興部 ----------------------------------------------------------------------- ----------------------b.csv-------------------------------------------2006,1,1,11016,141.678,45.4147,3,稚内,0,33,16,-64,-51,-75,55,1,9 2006,1,1,11151,141.138,45.1767,14,沓形,1,20,1,-52,-36,-68,4,1,6 2006,1,1,11176,141.778,45.1017,12,豊富,0,9,4,-80,-51,-116,59,0,3 2006,1,1,11206,142.362,45.1117,13,浜頓別,1,12,13,-92,-47,-140,66,1,3 2006,1,1,11276,142.28,44.965,25,中頓別,0,5,11,-137,-44,-209,46,0,2 2006,1,1,11291,142.585,44.9397,7,北見枝幸,0,25,13,-70,-47,-94,70,0,6 2006,1,1,11316,142.48,44.84,14,歌登,0,2,1,-115,-49,-170,56,0,1 ------------------------------------------------------------------------ implicit none REAL :: number,code,year,name REAL :: yea,mon,day,id,chiki,nam INTEGER :: lon,lat,pre,wind,winddirection,temp INTEGER :: hightemp,lowtemp,sunlight,maxrain,maxwind open(10,file='a.csv',status='old',iostat=ie) do iwork=1976, 2008 write(yyyy,"(i4.4)") iwork open(50, file='b'//yyyy//'.csv', status='old', & & iostat=io) if (io < 0) cycle do i = 1, 99 read(10,*) number,code,year,name if(ie < 0) exit do ii = 1, 30000 read(50,*) yea,mon,day,id,lon,lat,chiki,nam,pre,wind,winddirection,temp,& & hightemp,lowtemp,sunlight,maxrain,maxwind if(io < 0) exit write(6,*) yea stop close(10) close(50) end エラーメッセージがenddo文が予期されている。プログラムのファイルのendが予期されていない。とでます。enddo文を足したりしても治りませんでした。おそらくどこか書き方が違うのでしょう。どうかアドバイスください。

  • FORTRANのプログラム

    今、実験の解析を行っています。 読み込みたいテキストファイルには -1,0.4 0,0,233 -1,0.9 ・・など左側には-1か0のどちらかがあります。 これを -1,0.4 -1,0.9 を含むファイルと 0,0.0233 を含むファイルの二つに分けたいのです。 今プログラムを作っているのですがどうしてもできません。 どうしたらいいのでしょうか? program dat real x(10), y(10) open(7,file='test.txt') do i=1,10 read(7,*,end=200) x(i),y(i) end do do j=1,10 if(x(j).eq.0.0) then open(8,file='aftest1.txt') write(8,*) y(j) else open(9,file='aftest2.txt') write(9,*) y(j) end do close(8) close(9) 200 close(7) end

  • FORTRANの質問です

    今、実験の解析を行っています。 読み込みたいテキストファイルには -1,0.4 0,0,233 -1,0.9 ・・など左側には-1か0のどちらかがあります。 これを -1,0.4 -1,0.9 を含むファイルと 0,0.0233 を含むファイルの二つに分けたいのです。 今プログラムを作っているのですがどうしてもできません。 どうしたらいいのでしょうか? と質問しました。説明不足気味だったので、追加で説明させていただきます。 データの数はかわります。5個だったり、900個だったりします。 この数はわかりません。 program dat real n(10), y(10) write(*,*)'k=' read(*,*)k open(7,file='test.txt') do i=1,k read(7,*,end=200) n(i),y(i) end do 200 close(7) open(8,file='aftest1.txt') open(9,file='aftest2.txt') do j=1,k if(n(j).eq.0) then write(8,*) y(j) else if(n(j).eq.-1) then write(9,*) y(j) end if end do close(8) close(9) end と書いたのですがデータの数と繰り返しの数が一致しないと、出力されません。 いちいちファイルをみるのは面倒なので、なんとか したいのですが

  • FORTRANのプログラムについて

    program dat real x(100), y(100) s2=0 read(*,*) m,h open(7,file='test2.txt') do i=1,m read(7,*,end=200) x(i),y(i) s1=h/2*(y(1)+y(m)) s2=s2+h*(y(i)) s3=h*y(1) end do 200 close(7) sum=s1+s2-s3 write(*,*) 'sum=',sum end 台形公式を求めるプログラムを書いています。 テキスト形式でまずデータを取り込みます。 刻み幅はhです。ただしデータ数は未知数です。 上のようにプログラムを書いたのですが、うまく働きません。どうすればよろしいでしょうか? ご教授お願いします

  • fortran エラーについて

    fortranで、副プログラムを使ってデータを昇順または降順に並べ替えるプログラムを入力して実行しようとしたところ、 ・Unexpected junk in formal argument list at (1) ・Two main PROGRAMs at (1) and (2) という2つのエラーが出ました。 これらの改善方法を教えて頂きたいです。 初心者ですので簡単なところで間違えている可能性もありますが、ご指摘いただければ幸いです。 以下、実際に入力したプログラムです。 ------------------------------ implicit none integer::i,n real::x(1000),a(1000),b(1000) n=1000 open(10,file='input-data-1.txt') do i=1,n read(10,*) x(i) end do close(10) open(10,file='output-data-1.txt') do i=1,n call koukan(i,x(i),a(i),b(i)) write(10,'(i4,2f10.3)') i,a(i),b(i) end do close(10) stop end subroutine koukan(i,x(i),shoujun,koujun) implicit none integer::i,n,made real::x(1000),w,shoujun,koujun do made=n-1,1,-1 do i=1,made if(x(i)>x(i+1)) then w=x(i) x(i)=x(i+1) x(i+1)=w end if end do end do shoujun=x(i) do made=n-1,1,-1 do i=1,made if(x(i)<x(i+1)) then w=x(i) x(i)=x(i+1) x(i+1)=w end if end do end do koujun=x(i) return end ------------------------------

  • fortran77で複数のファイルの読み込み

    fortran77で複数のファイルの読み込み 現在fortran77のプログラムを勉強しております。 ファイルが複数あり、すべてのファイルを読み込みたいのですが、ファイルの数がたくさんあるため、プログラムの行数が多くなってしまいます。 do ループで次々とファイルを開くプログラムを考えているのですが、思いつきません。 どなたか考え方でもいいので、教えてください。 ちなみに私が考えたプログラムは、 open(10,file='C:\FORTRAN\100.txt',status='old') open(11,file='C:\FORTRAN\121.txt',status='old') open(12,file='C:\FORTRAN\144.txt',status='old') open(13,file='C:\FORTRAN\169.txt',status='old') open(14,file='C:\FORTRAN\196.txt',status='old') open(15,file='C:\FORTRAN\225.txt',status='old') ・・・。 これを do ループで次々に開くことを考えると、 character*3 A(10) do 100 i=1,10 A=i*i open(i,file='C:\FORTRAN\A.txt',status='old') 100 continue ・・・ みたいな感じです。 ' 'の中の一部だけを変えたい場合のcharacter 文の使い方がいまいちよく分かりません。

  • FORTRANのプログラミングについて

    たびたび申し訳ありません。 またFORTRANに関しての質問です。 x y z 0 0 30 1 0 45 2 0 60 3 0 43 4 0 51 5 0 32 0 1 43 1 1 90 2 1 32 3 1 85 4 1 65 5 1 90 0 2 32 1 2 32 と続くファイルがあります。これをFORTRANをで書き換えて、 0 0 30 0 1 43 0 2 32 1 0 45 1 1 90 1 2 32 と続くデータにしたいのです。(これを以下目的のファイルという) 今のところ、次のようなプログラムを書き、特定のXに対しては、結果を吐き出すことに成功しています。 program dat real x1(100),h,y2(100),y1(100),z1(100) integer i,n,j,k,l,m,a(100) open(7,file='test.txt') open(9,file='af-test.dat') do i=1,100 read(7,*,end=200) x1(i),y1(i),z1(i) if(x1(i).eq.90)then write(9,*) x1(i),y1(i),z1(i) end if end do 200 close(7) close(9) end ここまではうまくいくのですが、これでは90以外の場合は出力されません。(あたりまえですが) 特定のXに限らずに例えばXを0から100まで吐き出されるような目的のファイル作るにはをどのようにしてプログラムを書けばいいかご教授ください。

  • fortran

    do I = 1,40 do F = 1,4 do L = 1,100 if (I == 1. .OR. L == 1.) then A (I,F,L) = 3. else A (I,F,L) = 3.* B (I-1,F,L) end if end do end do do F = 1,4 do L = 1,100 do M = 1,100 B (I,F,L) = B (I,F,L) + C (I,F,M,L) end do end do end do end do 簡素化したプログラムなので、わかりにくいと思うのですが、後で計算するB(I,F,L)をA(I,F,L)のDOループに最初に持ってくると、I=1orL=1のときは正しい計算をしてくれるのですが、そのほかのときはB(I-1,F,L)に値が入らないのです。ちなみにC(I,F,M,L)はA(I,F,L)のループの後に計算しましたが、省略しました。 ご回答よろしくお願いします。

  • Fortran90で可変長ファイルを読む

    Fortran90初心者です。 実験でたとえば 時刻 温度 流速 t1   T1  v1 (CR/LF) ... ... ... tn   Tn  vn (CR/LF) のような ascii data file (FILE.dat)を得ています。 実験ごとに n の値、つまり、行数が違っており、このファイル内のデータを 次のようなFortran.90のプログラムで読み取って、その後処理を行っています。 integer :: Nl ! number of lines integer :: i character(180) :: dummy_line ! for void reading real(8), allocatable :: time(:), temp(:), velocity(:) open (5,file='FILE.dat', status='unknown',form='formatted') Nl = 0 do read(5,*, end = 99) dummy_line ! void read is absurd !! Nl = Nl + 1 end do 99 write(*,*)"eof encountered at Nl = ", Nl ! total lines in the file allocate(time(Nl), temp(Nl), velocity(Nl)) ! allocation of variables rewind(5) ! read pointer is set to the beginning of the file do i=1, Nl read(5,*) time(i), temp(i), velocity(i) end do この方法だと、元のファイルを2度読み込むことになりますので、あまり 賢い方法ではないと怒られています。実験データを出力する機器の方でファイルの 先頭にデータ数 n を吐き出させることもできません。 Fortran90だけでデータを読みながら動的配列を増やしてゆく方法があったら ご教示のほどお願いします。 Cならリスト処理やreallocで可能かとも思いますし、Linux上なら wc -lと Cのpopenとでも可能かとは思うのですが、プラットフォームはwindows7 で、intel fortranを使用しています。 (最終手段は入力部はCで、処理部はFortranで、linkするのでしょうか。) よろしくお願いします。

  • fortran90

    fortran90 現在 fortran90 で計算プログラムを作っております。 プログラムはかけたのですが、実行画面にエラーが出ます。 解決方法が分かりません。どなたか分かる方いらっしゃいますか。 プログラム implicit real*8 (a-h,o-z) parameter(n=900) open (1,file='004.txt',status='old') do 10 i=1,n read (1,*,end=11)xx,yy,zz,ww theta=acos(zz) phi1=acos(xx/sqrt(1-zz*zz)) phi2=asin(yy/sqrt(1-zz*zz)) write(*,*)theta,phi1,phi2 10 continue 11 end プログラム内容 あるフォルダーに保存してあるテキストファイルから4×4行列のデータを読み込み、そのデータからθの値とφ1、φ2のアタを求めるプログラムです。 実行分のエラー画面には、 acos: DOMAIN error です。

専門家に質問してみよう