2017-08-01 383 views
1

所以,假设我正在尝试在文件中读取我之前不知道的长度。我们可以在需要时使用iostat和while循环来中断,但是我遇到了一个问题。也就是说,我写的代码读取最后一行两次。我确信有一个明显的解决方案,但我似乎无法弄清楚。我不太了解read()或iostat函数是如何完全工作的(我在fortran中很新颖),但是我不能从文档中收集很多内容,所以我希望这里有人能够提供帮助。Fortran read()读取最后一行两次?

这里是(相关位)的代码,我已经写了:

filename = 'test.txt' 
iostat_1 = 0 
iostat_2 = 0 
open(newunit = lun, file = filename, status = 'old', iostat = iostat_1) 
if (iostat_1 == 0) then 
    do while(iostat_2 == 0)    
     if(iostat_2 == 0) then 
      read(lun,*,iostat = iostat_2) dum, real_1,real_2,int_1     
      print *, dum, real_1,real_2,int_1     
     endif 
    enddo 
endif 

所以,假如我的输入文件是

1 1.0 1.0 1 
2 2.0 2.0 1 
3 3.0 3.0 1 
4 4.0 4.0 4 

然后输出从打印语句中的终端会是

1 1.0 1.0 1 
2 2.0 2.0 1 
3 3.0 3.0 1 
4 4.0 4.0 4 
4 4.0 4.0 4 

请记住以下几点:这里的主要目的是能够读取一个文件e与任意数量的行。我对首先读取行数的解决方案不感兴趣。

感谢您的帮助!

更新好的我刚解决了这个问题。话虽如此,我想知道是否有一个解决方案比我的笨拙。这是我做过什么来解决这个问题

! Body of ReInsert 
filename = 'rpriov3.dat' 
iostat_1 = 0 
iostat_2 = 0 
open(newunit = lun, file = filename, status = 'old', iostat = iostat_1) 
if (iostat_1 == 0) then 
    do while(iostat_2 == 0)    
     if(iostat_2 == 0) then 
      read(lun,*,iostat = iostat_2) dum, real_1,real_2,int_1 
      if(iostat_2 == 0) then !<---- Added this nested if statement 
       print *, dum, real_1,real_2,int_1 
      endif     
      print *, iostat_2     
     endif 
    enddo 
endif 

回答

1

当你发现了,当你设置一个iostat参数,则read命令不会覆盖它要求的变量。

正如您已经注意到的,您的解决方案有点令人费解。

首先:

do while (condition) 
    if (condition) then 
     ... 
    end if 
end do 

在这种情况下,内if说法是完全多余的。除非condition为真,否则循环不会运行,因此除非condition本身的求值不会改变结果1),否则将始终执行if子句。

我想看的第二件事是:如果open失败会发生什么?在大多数情况下,我想打印错误并退出:

open(..., iostat=ios) 

if (ios /= 0) then 
    print*, "Error opening file" 
    STOP 1 
end if 

do while (...) 
    ... 
end do 

即使你不想在open错误的情况下退出程序,通常有办法让代码比更具可读性永恒的嵌套。例如,您可以反复询问用户文件名(在其自己的循环中),直到文件打开或用户输入一些退出消息。

ios = 1 
do while (ios /= 0) 
    write(*, *, advance='no') "Enter filename (or 'quit') :" 
    read(*, *) filename 

    if (trim(filename) == "quit") STOP 

    open(newunit=lun, file=filename, ..., iostat=ios) 
end do 

最后是最内部的if块。既然你仍要退出循环,当你达到一个错误,你可以使用exit语句一个循环中立即退出它不执行循环块的其余部分:

do 
    read(..., iostat=ios) ... 
    if (ios /= 0) exit 
    print *, .... 
end do 

这是一个无限循环一旦遇到读取错误(通常但不一定是EOF),则显式地exit。由于print语句位于exit之后,因此在出现此类错误时不会执行。

1)我的意思是像这款C段i++ < 10,这两个测试i10增量它。