2012-05-01 44 views
0

我有一个旧的Fortran程序用于从文本文件读取记录。这些记录的格式如下: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 

此代码与英特尔编译器(ifort)原样工作。随着gfortran它失败!第一个问题是,第三行的隐式读取使用ifort时,我等于实际读取的字段数,而在gfortran中它总是给出65。第二个问题是,在相同的隐式读取中,使用ifort , 人物 ;阅读为正常字段,但gfortran被忽略。

任何人都可以帮我解决这两个问题吗?任何其他想法都可以用来代替所有的代码也是受欢迎的。

+0

更换码好想法依靠什么类型的数据更清楚地了解你正在阅读。我猜record_type是某种代码(整数?字符?),这些字段是否为真?整数?混合物 ? record_type确定记录中的字段类型和字段数量吗? –

+0

record_type和字段都是字符(character * 20 typrec(mxrecord),field(mxfield))。根据记录的种类,通过阅读(字段(i),*)var来处理它们。所以,var是实数,整数或char,这取决于我是什么类型的记录。 – electrique

回答

1

这是行吗?除了do while(和exit控制结构...),这是符合f77(我认为)。如果需要,do while可以相对容易地被goto/continue所取代。我不知道你最终想要什么类型的字符串,所以我返回字符串(并假定一个字段不能超过24个字符)...我也假设一个“行”不能超过1024字符。 对于缺乏评论感到抱歉,但函数名称足够描述我的想法。一般情况下,我认为这是用编程时为使代码更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 
+0

readline子例程看起来非常好!只有一个问题。为了获得这些字段,使用了read,因为有些字段里面有空格,并且标记为''。例如'1013 1014'应该被理解为一个字段。 read语句处理这个问题。我会尝试将您的建议纳入代码中,并以某种方式更改getfield以关注“'中的字段。如果您有任何想法,欢迎! – electrique

+0

@ p3tris - 他们保证是''还是他们可以'“? – mgilson

+0

@ p3tris - 我编辑过。试试上面的代码(我没有测试过)。基本上我只是测试第一个字符是'or“,然后在getfield中查找结尾'或'。另外,我说代码大部分是符合f77标准的,但是我忘了我也使用了名称超过6个字符的子程序......噢。 – mgilson