2011-11-28 40 views
6

您知道以下語句是否通過fortran 90/95/2003標準之一保證爲真? 「假設一個字符變量的read語句被賦予一個空行(即只包含空格和新行字符)。如果格式說明符是星號(*),它將繼續讀取後續行,如果格式說明符是'(A)',則將空字符串替換爲字符變量。「Fortran讀取語句讀取超出行尾

例如,請看下面的最小程序和輸入文件。

程序代碼:

PROGRAM chk_read 
    INTEGER,   PARAMETER :: MAXLEN=30 
    CHARACTER(len=MAXLEN)  :: str1, str2 

    str1='minomonta' 
    read(*,*)  str1 
    write(*,'(3A)') 'str1_start|', str1, '|str1_end' 

    str2='minomonta' 
    read(*,'(A)') str2 
    write(*,'(3A)') 'str2_start|', str2, '|str2_end' 

END PROGRAM chk_read 

輸入文件:

----'input.dat' content is below this line---- 

yamanakako 

kawaguchiko  
----'input.dat' content is above this line---- 

請注意,有四行「input.dat」和第一和第三行是空白的(僅包含空格和新的行字符)。如果我運行該程序的

$ ../chk_read <input.dat> output.dat 

我得到以下輸出

----'output.dat' content is below this line---- 
str1_start|yamanakako     |str1_end 
str2_start|        |str2_end 
----'output.dat' content is above this line---- 

的變量「STR1」第一次讀聲明似乎看「input.dat」的第一行,找到一個空行,移動到第二行,找到字符值'yamanakako',並將其存儲在'str1'中。

相比之下,變量'str2'的第二個讀取語句似乎被賦予第三行,它是空白的,並將空行存儲在'str2'中,而不移動到第四行。

我試着編譯由英特爾Fortran(ifort 12.0.4)和GNU Fortran(gfortran 4.5.0)編寫的程序並得到相同的結果。

關於提問這個問題的背景:我正在寫一個子程序來讀取一個數據文件,它使用空行作爲數據塊的分隔符。我想確保空白行和空白行在讀取數據時被扔掉。我還需要使其符合標準和便攜。

感謝您的幫助。

回答

3

從Fortran的2008標準草案:

列表指向的輸入/輸出允許根據列表項,而不是由一個格式規範的 類型的數據編輯。它還允許 數據爲自由字段,即用逗號(或分號)或空格分隔。

然後:

在一個或多個列表定向記錄的字符構成的值和值的隔板的 序列。記錄的結尾與空白字符具有相同的效果,除非它在字符 常量內。 兩個或多個連續空白的任何序列都被視爲單個空白,除非它在一個字符常量內,否則將被視爲 。

這暗示了在列表控制的輸入中,空白行被視爲空白直到下一個非空值。

當讀取時使用fmt ='(A)'格式描述符時,將空行讀入str。另一方面,fmt = *表示自由格式的列表控制I/O,跳過空行直到找到非空字符串。爲了驗證這一點,這樣做:

PROGRAM chk_read 
INTEGER :: cnt 
INTEGER,   PARAMETER :: MAXLEN=30 
CHARACTER(len=MAXLEN)  :: str 

cnt=1 
do 
    read(*,fmt='(A)',end=100)str 
    write(*,'(I1,3A)')cnt,' str_start|', str, '|str_end' 
    cnt=cnt+1 
enddo 
100 continue 

END PROGRAM chk_read 

$ cat input.dat 



yamanakako 

kawaguchiko 

EOF

運行程序給出的輸出:

$ a.out < input.dat 
1 str_start|        |str_end 
2 str_start|        |str_end 
3 str_start|        |str_end 
4 str_start|yamanakako     |str_end 
5 str_start|        |str_end 
6 str_start|kawaguchiko     |str_end 

在另一方面,如果使用默認的輸入:

read(*,fmt=*,end=100)str 

你最終得到這個輸出:

$ a.out < input.dat 
1 str1_start|yamanakako     |str1_end 
2 str2_start|kawaguchiko     |str2_end 
+0

這是一個非常有用的信息,您從未遇到有關「fmt = *」行爲的特例。謝謝。然而,如果你能證實這裏觀察到的「fmt = *」和「fmt ='(A)」「行爲是標準行爲,例如引用一些文獻,我將非常感激。 – norio

+0

@norio我剛剛編輯了我的答案,您可能正在尋找。另外,在編寫可移植代碼時,可以訪問不同的平臺 - 標準不能保證行爲,只是說明應該是什麼行爲。 – milancurcic

+0

謝謝您引用標準草案。這很清楚。是的,我同意你關於在不同平臺上進行測試的重要性 - 最後,我從實際的機器上得到結果。除此之外,在編寫程序的初始階段,我要注意不要依賴於特定環境的特性而不會注意。 – norio

2

的F2008標準草案的這一部分可能會將您的問題:

10.10.3表式輸入

7如果下一封FF ective產品類型的角色,輸入表單 由可能定界的0或更多的序列 rep-char的類型參數被 有效項的種類暗示。字符序列可從 一條記錄的末尾延續到下一條記錄的開頭,但記錄 的末尾不得出現在撇號分隔的字符序列中的雙撇號之間,也不在撇號分隔字符序列中的加倍引號 以引號分隔的字符序列。記錄末尾確實不會導致空白字符或任何其他字符成爲 字符序列的一部分。字符序列可以根據需要繼續記錄在儘可能多的記錄上。字符空白,逗號,分號和斜槓 可能以默認,ASCII或ISO 10646字符序列顯示。

+0

謝謝你的回答。句子「記錄的結尾不會導致空白或任何其他字符成爲字符序列的一部分。」可能與觀察到的「fmt = *」行爲有關,但我無法確定。你有這個標準草案的URL嗎? – norio

+1

Fortran 2008標準草案位於ftp://ftp.nag.co.uk/sc22wg5/N1801-N1850/N1826.pdf。許多其他文件在http://www.nag.co.uk/sc22wg5/。我認爲這句話與下一句是你正在尋找的。 –

+0

感謝您的鏈接。這是一個非常有用的網站。據我所知,「字符序列可以根據需要繼續記錄多個記錄」。意味着我可以將具有「kawaguchi \ nko」(請將「\ n」解釋爲換行符)的文件傳遞給'read(*,*)str'將值「kawaguchiko」設置爲變量'str'。因此,我認爲這與我所關心的有點不同。 – norio