2017-08-01 376 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增量它。