2012-07-30 55 views
1

我的數據看起來像這樣帶*的數據讀出的Fortran以表示類似的數據

-3442.77 -16749.64 893.08 -3442.77 -16749.64 1487.35 -3231.45 -16622.36 902.29 

.....

159*2539.87 10*0.00 162*2539.87 10*0.00 

這意味着我開始,每行7次或8的實數和然後(接近尾聲)有159個2539.87的值,接着是10個值0,接着是2539.87的162個等等。這似乎是一種節省空間的方法,因爲此文件格式的以前版本每行是常規的6個實數。

我已經將數據讀入字符串,因爲不知道每行是否有7或8個數字。因此,我可以輕鬆找到包含*的行。但是呢?我想我必須確定每個*的位置,然後在分配給數組之前識別之前的整數和實際值。我錯過了什麼?

回答

3

閱讀該行。將其分割成由空格(s)分隔的令牌。以空格替換標記中的*。然後從字符串中讀取一個或兩個值,具體取決於是否存在星號。示例代碼如下:

REAL, DIMENSION(big) :: data 
CHARACTER(LEN=40) :: token 
INTEGER :: iptr, count, idx 
REAL :: val 

iptr = 1 
DO WHILE (there_are_tokens_left) 
    ... ! Get the next token into "token" 
    idx = INDEX(token, "*") 
    IF (idx == 0) THEN 
    READ(token, *) val 
    count = 1 
    ELSE 
    ! Replace "*" with space and read two values from the string 
    token(idx:idx) = " " 
    READ(token, *) count, val 
    END IF 
    data(iptr:iptr+count-1) = val ! Add "val" "count" times to the list of values 
    iptr = iptr + count 
END DO 

這裏我已經任意設置了令牌的長度爲40個字符。根據您希望在輸入文件中找到的內容對其進行調整。

爲了完整起見,這種通過用值/重複計數對替換重複值來壓縮某些東西的方法稱爲遊程編碼(RLE)。

1

您的輸入數據可能已寫入適合列表定向輸入的格式(其中READ語句中的格式規範僅爲'*'')。列表定向輸入支持您看到的r * c格式,其中r是重複計數,c是要重複的常量。

如果輸入項的總數在預先已知的(可能是固定的該程序,也許它是由前面的條目的文件中定義的),則在讀取文件很簡單,只要:

REAL :: data(size_of_data) 
READ (unit, *) data 

例如,對於您自己的示例中顯示的最後一行,「size_of_data」將需要爲341,從159 + 10 + 162 + 10。

使用列表定向輸入,數據可以跨越多條記錄(多行) - 您無需事先知道每條線上有多少項 - 只有多少項出現在下一個「數據塊」中。

列表定向輸入有一些像這樣的其他「特徵」,這就是爲什麼使用它來解析沒有用它編寫的「任意」輸入通常不是個好主意 - 使用顯式而不是格式規範(如果事先不知道,可能需要動態創建格式規範以匹配輸入字段的寬度)。

如果您不知道(或無法計算)READ語句之前的項目數量,那麼您將需要自己分析該線路。