Fortran read()读取最后一行两次?

时间:2017-08-01 22:57:28

标签: file-io fortran

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

以下是我编写的(相关位)代码:

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 

然后从print语句输出到终端将是

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 

请记住以下内容:此处的主要目的是能够读取具有任意行数的文件。我对涉及首先读取行数的解决方案不感兴趣。

感谢您的帮助!

更新好的我刚解决了这个问题。话虽如此,我想知道是否有一个比我更笨拙的解决方案。以下是我为解决问题所做的工作

! 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 个答案:

答案 0 :(得分: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

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

1)我的意思就像这个C片段i++ < 10,它们都针对i 和10 >递增它。