2015-07-11 177 views
1

在寫格式化輸出到一個變量,我得到的錯誤不明原因

forrtl: severe (27): too many records in I/O statement 

我檢查了明顯的事情 - 數據是否超過了格式和長度反之亦然,變量的數量和類型與格式說明符兼容 - 我看不出爲什麼應該拋出錯誤。

的最小示例性實例是:

program TXTERR27 
    use iso_fortran_env, only: OUTPUT_UNIT  
    implicit none 

    double precision :: F1, F2 
    integer :: I1 
    character (len=25), parameter :: A1 = 'AaaaaAaaaaAaaaaAaaaaAaaaa' 

    character (len=250) :: A2 

10 format(/, 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ', I3, 'ZZZZZZZZZZZ',  & 
    F10.3, 1X, A25, /, 'ZZZZZZZZZZZZZZZZZ', F6.3, 'ZZZZZZZZ') 
20 format('Result :[', A250, ']') 

    continue 

    I1 = 1 
    F1 = 1.0D0 
    F2 = 1.0D-3 

    write(OUTPUT_UNIT, *) "This works:" 
    write(OUTPUT_UNIT, 10) I1, F1, A1, F2 
    write(OUTPUT_UNIT, *) 

    write(OUTPUT_UNIT, *) "This doesn't:" 
    write(A2, 10) I1, F1, A1, F2 
    write(OUTPUT_UNIT, 20) A2 

    stop 
end program TXTERR27 

這是通過使用編譯:和沒有警告或錯誤導致

ifort -warn all -check all -traceback -o txterr27 txterr27.f90 

。輸出如下:

This works: 

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1ZZZZZZZZZZZ  1.000 AaaaaAaaaaAaaaaAaaaaAaaaa 
ZZZZZZZZZZZZZZZZZ 0.001ZZZZZZZZ 

This doesn't: 
forrtl: severe (27): too many records in I/O statement, unit -5, file Internal Formatted Write 
Image    PC    Routine   Line  Source    
txterr27   000000000046EEBE Unknown    Unknown Unknown 
txterr27   000000000046D956 Unknown    Unknown Unknown 
txterr27   00000000004266A2 Unknown    Unknown Unknown 
txterr27   0000000000403BBB Unknown    Unknown Unknown 
txterr27   0000000000403122 Unknown    Unknown Unknown 
txterr27   0000000000419A44 Unknown    Unknown Unknown 
txterr27   0000000000417BFC Unknown    Unknown Unknown 
txterr27   0000000000402586 MAIN__      26 txterr27.f90 
txterr27   00000000004021DC Unknown    Unknown Unknown 
libc.so.6   00007F083D474EC5 Unknown    Unknown Unknown 
txterr27   00000000004020D9 Unknown    Unknown Unknown 

要檢查是否這是一個特定編譯器的問題,我重建示例代碼下gfortran用:

gfortran -pedantic -Wall -fbacktrace -o txterr27 txterr27.f90                

並得到了類似的結果:

This works: 

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1ZZZZZZZZZZZ  1.000 AaaaaAaaaaAaaaaAaaaaAaaaa 
ZZZZZZZZZZZZZZZZZ 0.001ZZZZZZZZ 

This doesn't: 
At line 26 of file txterr27.f90 
Fortran runtime error: End of file 

顯然,格式化數據沒有問題,否則寫入標準輸出將失敗。我所能想到的是,CRLF'/')導致write()將結果呈現爲數組而不是標量。將數組寫入標準輸出可以正常工作(每行一個條目),但如果它試圖將數組寫入標量,則會失敗。

來自gfortranifort的錯誤消息有很多不足之處;道歉對已故道格拉斯亞當斯道歉:「Mostly Useless

任何想法?

更新:繼續分析,問題在於我對Fortran中「記錄」的構成有何理解。下面是一個更新的說明圖:

program TXTERR27A 
    use iso_fortran_env, only: OUTPUT_UNIT  
    implicit none 

    double precision :: F1, F2 
    integer :: I1 
    character (len=25), parameter :: A1 = 'AaaaaAaaaaAaaaaAaaaaAaaaa' 

    character (len=250) :: A2 
    character (len=250), dimension(5) :: A3 

10 format(/, 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ', I3, 'ZZZZZZZZZZZ',  & 
    F10.3, 1X, A25, /, 'ZZZZZZZZZZZZZZZZZ', F6.3, 'ZZZZZZZZ') 
20 format('Result: [', A250, ']') 
30 format('Result:', /, '[', *(A250, ']', /, '[')) 

    continue 

    I1 = 1 
    F1 = 1.0D0 
    F2 = 1.0D-3 
    A2 = '' 
    A3 = '' 

    write(OUTPUT_UNIT, *) "This works:" 
    write(OUTPUT_UNIT, 10) I1, F1, A1, F2 
    write(OUTPUT_UNIT, *) 

    write(OUTPUT_UNIT, *) "Does this?" 
    write(A3, 10) I1, F1, A1, F2 
    write(OUTPUT_UNIT, 30) A3 

    write(OUTPUT_UNIT, *) "This doesn't:" 
    write(A2, 10) I1, F1, A1, F2 
    write(OUTPUT_UNIT, 20) A2 

    stop 
end program TXTERR27A 

這個例子表明,多個記錄/串寫入一個內部變量,而這個問題(爲疑似)時被髮射的是,write()是試圖把一個數組爲標量。這是有道理的,如果你認爲'/'作爲記錄分隔符,而不是一個簡單的CRLF

This works: 

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1ZZZZZZZZZZZ  1.000 AaaaaAaaaaAaaaaAaaaaAaaaa 
ZZZZZZZZZZZZZZZZZ 0.001ZZZZZZZZ 

Does this? 
Result: 
[                                                               ] 
[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1ZZZZZZZZZZZ  1.000 AaaaaAaaaaAaaaaAaaaaAaaaa                                           ] 
[ZZZZZZZZZZZZZZZZZ 0.001ZZZZZZZZ                                                       ] 
[                                                               ] 
[                                                               ] 
[ 
This doesn't: 
At line 34 of file txterr27.f90 
Fortran runtime error: End of file 

這個問題是顯而易見的,如果你牢記的Fortran I/O的古老面向記錄的性質。在1969年之後開發出具有文本I/O設施的語言的長時間使用經驗之後,這很容易被遺忘。對於沒有看到這種情況的道歉,我們很抱歉。

無論如何,重要的一點是記住'/'是一個記錄分隔符,不要將它看作Fortran的\n版本。

+2

是你的人確認後剛:是的,你不能將多個記錄寫入內部文件? – francescalus

+0

我想我不清楚什麼是「記錄」。我看到的是一個簡單的字符串,但顯然'/'是一個記錄分隔符,而不僅僅是一個CRLF。這將解釋我看到的行爲。 – arclight

回答

2

新行說明符/充當列表控制輸入的分隔符。所以你正試圖將三個記錄寫入一個內部文件。

只有一個內部文件是允許的,所以在第一個記錄後,內部文件的末尾已到達。也就是說,gfortran告訴你。

+0

如果我以前看起來有點脾氣暴躁,道歉;我想我們錯過了對方說的話。 – arclight

1

斜槓編輯描述符(/)不會直接標記新行(CRLF或任何適用於系統的行)。它僅僅表示轉移到(在輸出的情況下)當前記錄的結束。由於您的處理器將記錄視爲一條線,因此您將此輸出顯示爲標準輸出。

內部文件(字符變量)是不同的。如果你有一個標量字符變量(A2),它定義了變量長度的單個記錄。當你試圖向這個變量寫入多條記錄時,你會看到錯誤。

但是,可以寫入多個記錄在內部文件,我們可以在2008年的Fortran 9.4參見:

如果文件的字符數組,它被視爲序列字符數組元素。每個數組元素(如果有的話)都是該文件的記錄。

你可以的話,聲明A2爲尺寸(至少)的陣列3

另外,如果你在你的標量變量,你可以考慮單個記錄一個新的行之後是真正的內在模塊iso_c_binding的內部或命名常量C_NEW_LINEC_CARRIAGE_RETURN

+0

謝謝;因爲我試圖將我們的代碼遷移到F2008,所以我必須查看'new_line'和'iso_c_binding'。我一直自由地使用'adjustl()','trim()'和可分配長度的字符變量來將我們的輸出從表格格式移開。寫入內部文件對此至關重要,並且很容易忘記Fortran中的文本I/O仍然與其他語言根本不同。 – arclight

0

我有一個非常類似的麻煩之前...當我試圖用一個程序一樣

program main 
    character(50) :: str 
    open(10, file="some.xml", status="old") 
    do 
     read(10, *) str 
     print *, trim(str) 
     if (str == "</DATA>") then 
      print *, "tag found!" 
      exit 
     endif 
    enddo 
    close(10) 
end 

我遇到了一個錯誤找一個標籤</DATA>在數據文件中 像

<DATA> 
100 200 300 
</DATA> 

<DATA> 
100 
< 
At line 7 of file test.f90 (unit = 10, file = 'some.xml') 
Fortran runtime error: End of file 

並且花了很長時間才注意到Fortra n不喜歡斜槓(/)......通過改變讀語句

read(10, "(a)") str 

程序得到所需要的結果

<DATA> 
100 200 300 
</DATA> 
tag found! 
+0

這可能是一個稍微不同的問題:'/'作爲列表控制輸入中的值分隔符終止輸入語句。 – francescalus