Question

I have an old Fortran program for reading records from text files. The records are of the form:

record_type field1 field2 ... fieldN ;

These records might spread over several lines, the character ; shows that the record has finished. The old code is:

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

This code works with Intel Compiler (ifort) as it is. With gfortran it fails! The first problem is that the implicit read on the third line, with ifort, gives i to be equal to the number of fields actually read, while in gfortran it always gives 65. The second problem is that in the same implicit read, with ifort, the character ; is read as a normal field but with gfortran is skipped.

Anyone can help me solve these two problems? Any other ideas for replacing the code all together are also welcome.

Was it helpful?

Solution

Does this work? Aside from do while (and exit control structures...), this is f77 compliant (I think). The do whiles could relatively easily be replaced by goto/continue if necessary. I don't know what type you ultimately want the strings to be, so I return strings (and assume a field can't be longer than 24 characters)...I also assume a "line" can't be longer than 1024 characters. Sorry about the lack of comments, but the function names are descriptive enough I think. Generally, I think it is a good idea to use functions/subroutines when programming as that makes the code much more readible...

  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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top