1

我的数据看起来像这样

-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 值,然后是 162 个 2539.87 等。这似乎是一种节省空间的方法,就像以前的版本一样这种文件格式是常规的每行 6 个实数。

由于不知道每行是 7 个还是 8 个数字,我已经将数据读入一个字符串。因此,我可以很容易地发现包含 *. 但那又如何呢?我想我必须确定每个 * 的位置,然后在分配给数组之前确定之前的整数和之后的实数值。我错过了什么吗?

4

2 回答 2

3

阅读该行。将其拆分为由空格分隔的标记。*将具有它的 in 标记替换为空格。然后从字符串中读取一个或两个值,这取决于是否有星号。示例代码如下:

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

这里我任意设置了token的长度为40个字符。根据您希望在输入文件中找到的内容进行调整。

顺便说一句,为了完整起见,这种通过用值/重复计数对替换重复值来压缩某些内容的方法称为游程编码(RLE)。

于 2012-07-30T14:46:22.950 回答
1

您的输入数据可能已以适合列表定向输入的形式写入(其中 READ 语句中的格式规范只是“*”)。列表定向输入支持您看到的 r*c 形式,其中 r 是重复计数,c 是要重复的常数。

如果输入项的总数是预先知道的(也许它对于该程序是固定的,也许它是由文件中较早的条目定义的),那么读取文件就像这样简单:

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

例如,对于示例中显示的最后一行,它自己的“size_of_data”需要为 341,从 159+10+162+10 开始。

使用列表定向输入,数据可以跨越多条记录(多行)——您不需要提前知道每行有多少项目——只需知道有多少项目出现在下一个数据“块”中。

列表定向输入还有一些其他类似的“功能”,这就是为什么使用它来解析没有考虑到它的“任意”输入通常不是一个好主意 - 改用显式格式规范(如果事先不知道,这可能需要动态创建格式规范以匹配输入字段的宽度)。

如果您在 READ 语句之前不知道(或无法计算)项目数,那么您将需要自己解析行。

于 2012-07-30T21:34:52.213 回答