Fortranエラー発生!副プログラムでデータの並べ替えを実行しようとしたら...

このQ&Aのポイント
  • fortranで副プログラムを使ってデータを昇順または降順に並べ替えるプログラムを実行しようとした際、Unexpected junk in formal argument list at (1)とTwo main PROGRAMs at (1)という2つのエラーメッセージが表示されました。
  • 初心者の方が簡単なところで間違えている可能性もあるため、エラーの改善方法についてアドバイスをいただきたいです。
  • 提供されたプログラムの中で副プログラムkoukanにおいて、変数の宣言やループ処理の順番に誤りがある可能性があります。正しい書き方に修正してみてください。
回答を見る
  • ベストアンサー

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 ------------------------------

質問者が選んだベストアンサー

  • ベストアンサー
  • f272
  • ベストアンサー率46% (8026/17154)
回答No.2

エラーメッセージを必ず読むこと。またエラーが起こった場所もかかれているはずです。 今回のエラーは,仮引数にゴミがあるというのだからゴミを取り除きましょう。 誤 subroutine koukan(i,x(i),shoujun,koujun) 正 subroutine koukan(i,x,shoujun,koujun) それに付随して,こちらも修正しましょう。 誤  call koukan(i,x(i),a(i),b(i)) 正  call koukan(i,x,a(i),b(i)) 主プログラムが2つあるというエラーメッセージは,1つ目のエラーによって副プログラムが副プログラムであると認識されていないためです。 で,これらを修正すると,動くようにはなるけど,非常に無駄なことをしているプログラムになります。少し修正するだけで1/1000の計算量になります。

15program22
質問者

補足

ありがとうございます!! そうですね、エラーメッセージの意味をきちんと読み取れるようにしたいと思います。 最後の少しの修正とは、どのようなものでしょうか…。今後に役立てたいため、教えて頂けると幸いです。

その他の回答 (3)

  • f272
  • ベストアンサー率46% (8026/17154)
回答No.4

> アクセスする順番を変えるとはどういうことでしょうか? 例えば配列aが昇順に並んでいるのなら do i=1,n write(10,'(i4,2f10.3)') i,a(n+1-i) end do で書き出されるのは降順になります。

15program22
質問者

お礼

丁寧なご説明のおかげで、理解することができました。 今回は、大変勉強になりました。本当にありがとうございました!

  • f272
  • ベストアンサー率46% (8026/17154)
回答No.3

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 でkoukanを1000回呼び出しています。でもkoukanでは配列xの中身をソートしているようです。つまり1000回ソートしているわけで,無駄ですよね。ループの外で1回呼び出せばよい。 ついでに言うと,koukanではxの中身を書き換えていますが,それとは別にソート後の配列も別に用意しています。ソート後の配列を使うのならソート前の配列を書き換えるべきではないし,ソート前の配列を書き換えるのならソート後の配列は不要です。 それから昇順と降順は,一方があれば他方はアクセスする順番を変えるだけです。2つとも計算するのは無駄でしょう。

15program22
質問者

補足

ループ内での呼び出しは無駄、ソート前の配列を書き換えるならソート後の配列は不要、というのはその通りですね、ありがとうございます。 昇順と降順の2つとも計算するのは無駄だと思っていましたが、効率的な方法が思いつかずにいました。こちらの理解不足で申し訳ありませんが、アクセスする順番を変えるとはどういうことでしょうか?

回答No.1

subroutine koukan(i,x(i),shoujun,koujun) じゃなくて subroutine koukan(i,x,shoujun,koujun) かな

15program22
質問者

お礼

すみません、補足の方は解決しました。 早いご回答ありがとうございました!

15program22
質問者

補足

ありがとうございます!! 無事エラーはなくなり、output-data-1.txtのファイルを作成することができたのですが、このファイルを開いてみても何も入力されていませんでした。このファイルに結果を出力するにはどうすれば良いのでしょうか…。

関連するQ&A

  • fortran errorについて

    fortranを勉強していたのですがエラーがでてしまい、何時間かけても理解できなかったので質問させてください。 以下プログラム program test !ここからメインルーチン !前準備 配列の用意 implicit none integer N integer,dimension(0:N,0:N) :: A integer :: i,j,k read * ,N !初期状態の代入 do i=0,N do j=0,N A(i,j)=0 end do end do do i=N/2,N-1 A(N/2,i)=1 end do do i=N/2,N-1 A(N/2+1,i)=-1 end do !ループ 50回ループさせる do k=0,50 !状態の表示 call visualize !サブルーチン visualize subroutine visualize do i=0,N do j=0,N if(A(i,j)== 1) write(*,'(A1)',advance='NO') "*" if(A(i,j)== 0) write(*,'(A1)',advance='NO') " " if(A(i,j)==-1) write(*,'(A1)',advance='NO') "+" end do write(*,*) end do !end subroutine visualize call insert !サブルーチン insert subroutine insert do i=0,N do j=0,N if(A(i,j)== 1) A(i,j)=-1 if(A(i,j)== 0) A(i,j)=max(0,A(i-1,j),A(i,j-1),A(i,j+1),A(i+1,j)) if(A(i,j)==-1) A(i,j)=0 end do end do !end subroutine insert end do end program test これでコンパイラすると In file test.f90:48 subroutine visualize 1 Error: Unclassifiable statement at (1) In file test.f90:69 subroutine insert 1 Error: Unclassifiable statement at (1) とでます いろいろ調べたのですが全くわかりませんでした できればよろしくお願いします

  • fortran 途中まで考えたのですが。。。。

    エラトステネスのふるい(素数の倍数を除いていって残ったのが素数)で3桁の素数を求めて表示したいです。 私が考えたのは、 1・2~99までの数を素数かどうか調べて、素数を配列に入れていく 2・100~999まで素数の配列の中の数で割って、割り切れたらおしまい。割り切れなかったら表示していく ということです。 しかし下のプログラムではうまく素数配列ができていないようなのです。 ここまでかなり時間がかかったのでこのプログラムに手をいれて これ以外におかしくなるところもどこを直せばいいのか教えてくださるとうれしいです。 C C q223.f C PROGRAM q223 C IMPLICIT NONE C INTEGER N,i,K,s,l REAL a(99),b(99),c(99),X,Y C real M C a(1)=2 a(2)=3 l=2 C DO N=2,99,1 M=N**(0.5) S=M DO i=2,S,1 K=MOD(N,i) IF(K ==0)THEN exit ELSE IF(K /=0)THEN l=l+1 a(l)=N ENDIF ENDDO ENDDO C do N=100,999 do l=1,99 X=a(l) Y=N/X if(Y==0)then exit else if(Y/=0)then write(*,*)N end if end do end do c end よろしくおねがいします

  • fortran おそらく二重解法のエラー

    以下のようなプログラム(速度ベレル法による時間発展)を書いたのですが,エラーがでてしまいます. どこが悪いのかを教えていただけたらと思います. PROGRAM verlet implicit none integer::i,n,p real(8)::dt,k,m,ratio,ti real(8),allocatable::x(:),v(:),f(:) allocate(x(0:n)) allocate(v(0:n)) allocate(f(0:n)) dt=0.01d0 n=1000 k=1.0d0 m=1.0d0 ratio=k/m p=4 ti=0.0d0 x(0)=0.0d0 v(0)=1.0d0 f(0)=-k*(x(0))**(p-1) do i=0,45 x(i+1)=x(i)+dt*v(i)+f(i)/(2.0d0*m)*dt**2.0d0 f(i+1)=-k*(x(i+1))**(p-1) v(i+1)=v(i)+dt*(f(i)+f(i+1))/(2.0d0*m) end do do i=0,n ti=i*dt write(6,*) ti,x(i),v(i) end do deallocate(x) deallocate(v) deallocate(f) END PROGRAM verlet

  • FORTRAN 初心者です

    以下の連立一次方程式をSOR法で解く問題です。 初心者なりにガウスザイデル法を応用してプログラムしたつもりですが、やはり難しいです(答えは違います)。 どこをどうすれば良いのか分かりませんので、よろしければヒントや助言をいただきたいです。 PROGRAM SOR REAL A(10,10),B(10),X(10),X0(10) INTEGER N,I,J,K,Kmax,w N=3 A(1,1)=4 ;A(1,2)=1 ;A(1,3)=2 A(2,1)=1 ;A(2,2)=3 ;A(2,3)=1 A(3,1)=1 ;A(3,2)=2 ;A(3,3)=5 B(1)=16 B(2)=10 B(3)=12 X0(1)=1 ;X0(2)=1 ;X0(3)=2 w=1.2 Kmax=50 EPS=1.D-5 DO I=1,N D=A(I,I) S=B(I) B(I)=B(I)/D END DO DO K=1,Kmax DO I=1,N DO J=1,N if(J<I) X0(J)=X(J) S=S-A(I,J)*X0(J) END DO X(I)=(1-w)*X(I)+w*S END DO DO I=1,N S=S-(X(I)-X0(I))**2 END DO IF(S<EPS) GOTO 10 DO I=1,N X0(I)=X(I) END DO END DO 10 WRITE(*,*) K DO I=1,N WRITE(*,*) 'SOR法で求めた解は' WRITE(*,*) 'X(',I,')=',X(I) END DO END PROGRAM SOR !------------------------------------ ※wは緩和係数です

  • 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のプログラミングについて

    たびたび申し訳ありません。 また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まで吐き出されるような目的のファイル作るにはをどのようにしてプログラムを書けばいいかご教授ください。

  • Fortran90/95の出力方法について

    Fortran90/95の出力方法について Fortran95において,変数の値をwrite文で出力した後に改行しない方法を教えてください. 具体的には次のProgram reiを用いて質問します. program rei implicit none integer i, n read(*,*) n do i = 1, n write(*,*) i end do end このプログラムを実行させnに3を代入すると次のように表示されます. 1 2 3 しかし,私としては次のように改行せずに表示させたいのです. 1 2 3 また,諸事情により配列は使用しません. プログラムをどのように改良すればよいのでしょうか.教えてください.

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

    大学で卒論のためにFortran90でランダムウォークのプログラムを作ってるんですが…2週間悩んでるんですが、できないところがあります。 「1次元のランダムウォークにおいて、ステップ数Nとxの値を与えたときのすべての可能な歩行を数え上げるプログラムを書け」というものです。 直接ステップ数を書き込んだプログラムを基にして任意のステップ数を入力するプログラムを作ってみたんですが、うまくいきません。 integer :: a(100,20), x, i1, i2, i3 x = 0 do i1 = -1, 1, 2;do i2 = -1, 1, 2;do i3 = -1, 1, 2 x = x + 1 a(x, 1) = i1;a(x, 2) = i2;a(x, 3) = i3 end do;end do;end do end が基にしたプログラムです。これはステップ数が'3'なので実行結果は「-1-1-1,-1-11,-11-1,-11-1,-111,1-1-1,11-1,111」というxの変位の仕方が出ます。 integer, allocatable :: a(:,:) integer :: i, n, x, l print *, 'ステップ数を入力:'; read *, n allocate(a(n, 2**n)) do l = 1, n do i = -1, 1, 2 x = x + 1 a(x, l) = i end do end do end という風に作ってみたんですが、'3'を入力しても同じ結果が出ません。わかりにくい文章で申し訳ないですがどなたかご教授お願いします。

  • 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でプログラムを実行するとEnd of fileと表示されてしまいます

    fortran初心者です。 以下のプログラムのコンパイルは出来るのですが、実行すると At line 9 of file ./rennsyu1.f90 Fortran runtime error: End of file というエラーがでてしまいます。 End of fileが何を意味するのか解からず対処が出来ません。 一つ言えることは、open文を使用すると必ずこのエラーが出てしまうということです。 どなたか、End of fileの意味と対処法を教えてください。 プログラム  既存のファイルxx.txtからx1とx2の値を読み取り、画面に出力させる。 program rennsyu1 implicit none real :: x(2) integer :: i open (17 , file = ' xx.txt ' ) do i = 1 , 2 read (17 , *) , x(i) write (6 , *) " x = " , x(i) end do close(17) stop end program rennsyu1

専門家に質問してみよう