2012-07-30 54 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语句之前的项目数量,那么您将需要自己分析该线路。