0

テキストファイルからレコードを読み取るための古いFortranプログラムがあります。レコードの形式は次のとおりです。

record_type field1 field2 ... fieldN ;

これらのレコードは、文字である複数の行にまたがる場合があります。レコードが終了したことを示します。古いコードは次のとおりです。

2 read(data,"(a130)",end=3)line
  shift=adrec(nbrec)-1
  read(line,*,end=1)typrec(nbrec),(field(shift+i),i=1,65)
1 do
    do j=shift+1,shift+i-1
      k=index(field(j),';')
      if(k .ne. 0)then
        if(k .eq. 1)then
          adrec(nbrec+1)=j
        else
          field(j)(k:)=''
          adrec(nbrec+1)=j+1
        endif
          go to 2
      endif
    endo
    read(data,"(a130)")line
    read(line,*,end=1)(field(shift+i),i=1,65)
  enddo
3 continue

このコードは、インテル®コンパイラー(ifo​​rt)でそのまま動作します。gfortranでは失敗します!最初の問題は、ifortを使用した3行目の暗黙的な読み取りにより、iが実際に読み取られたフィールドの数と等しくなるのに対し、gfortranでは常に65になることです。2番目の問題は、ifortを使用した同じ暗黙的な読み取りでのことです。 、 キャラクター ; 通常のフィールドとして読み取られますが、gfortranではスキップされます。

誰かが私がこれらの2つの問題を解決するのを手伝ってくれる?コードをまとめて置き換えるための他のアイデアも歓迎します。

4

1 に答える 1

1

これは機能しますか?do while(および制御構造...)を除けばexit、これはf77に準拠しています(私は思います)。do whileは、必要に応じてgoto/continueに比較的簡単に置き換えることができます。最終的に文字列をどのタイプにするかわからないので、文字列を返します(フィールドは24文字を超えることはできないと想定しています)...また、「行」は1024を超えることはできないと想定しています。文字。コメントが足りないので申し訳ありませんが、関数名は十分に説明的だと思います。一般的に、プログラミングの際には、コードをはるかに読みやすくするために関数/サブルーチンを使用することをお勧めします...

  program main
  character*1024 line
  integer stat,stat2,i,nf
  character*24 fld
  character*16 fmt

  open(unit=21,file='test.dat',status='old')
  stat=0
  do while(stat.eq.0)
     call readline(21,line,stat)
     stat2=0
     i=1
     do while(.true.)
        call getfield(line,fld,stat2)
        if(stat2.ne.0) exit
        i=i+1
        write(*,*) i,stat2,fld
     enddo
     write(*,*) " "
  enddo


  end

  subroutine getfield(line,field,stat)
  integer l,i,stat
  character*(*) line,field
  !Get first field and shift the line
  l=1
  if(line.eq.' ')then
     stat=1
  else
     stat=0
  endif
  do while (line(l:l).eq.' ')
     l=l+1
  enddo
  i=l
  do while (line(i:i).ne.' ')
     i=i+1
  enddo

  if((line(l:l).eq.'"').or.(line(l:l).eq."'"))then
     do while(line(i:i).ne.line(l:l))
        i=i+1
     enddo
  endif

  field=line(l:i)
  line=line(i+1:)
  return
  end

  subroutine readline(unit,line,stat)
  integer unit
  character*(*) line
  integer stat,i
  !read one "line"  Lines are sequences seperated by ';' (can have newlines in there) 

  stat=0
  i=1
  do while (.true.)
     read(unit,'(A)',end=100) line(i:)
     i=index(line,';')
     if(i.eq.0)then
        i=len_trim(line)+2
     else
        line(i:)=' ' !remove the trailing semicolon.
        exit
     endif
  enddo

  return
 100  continue
  stat=1
  return
  end
于 2012-05-02T05:01:11.357 に答える