如何在Fortran中拆分数据块?

时间:2017-10-03 17:31:49

标签: count fortran

我需要计算每个块中的行数并计算块数,以便之后正确读取它。任何人都可以在Fortran中建议一段代码吗?

我的输入文件是这样的:

# Section 1 at 50%    (Name of the block and its number and value)

1 2 3                 (Three numbers in line with random number of lines)

...

1 2 3

# Section 2 at 100% (And then again Name of the block)

1 2 3... 

等等。

代码如下。它可以使用1组数据正常工作,但当它再次遇到“#”时,它只停止提供大约一个部分的数据。无法跳转到另一部分:

  integer IS, NOSEC, count

    double precision SPAN

    character(LEN=100):: NAME, NAME2, AT

    real whatever

 101   read (10,*,iostat=ios) NAME, NAME2, IS, AT, SPAN

       if (ios/=0) go to 200

       write(6,*) IS, SPAN

       count = 0

  102         read(10,*,iostat=ios) whatever

       if (ios/=0) go to 101

       count = count + 1

       write(6,*) whatever

       go to 102

200      write(6,*) 'Section span =', SPAN

因此,第一个循环(101)假设读取块的参数,第二个循环(102)计算块中的行数,并将'ncount'作为唯一需要的参数。但是,当在102之后它假设跳回到101以启动一个新块时,它只会转到200(打印操作的结果),这意味着它无法读取有关第二个块的数据。

1 个答案:

答案 0 :(得分:0)

假设您的文件包含两种有效类型的行:

  • 阻止标头,以'#
  • 开头
  • 数据行以数字09
  • 开头

让我们添加更多条件:

  • 忽略前导空格,
  • 与前两个模式不匹配的行被视为注释并被忽略
  • 注释行不会终止块;只有在找到新块或到达文件末尾时才会终止块,
  • 数据行必须遵循块标题(文件中的第一个非注释行必须是块标题),
  • 块可能为空,
  • 文件可能不包含块

您想知道每个块中的块数和数据行数,但您不知道可能有多少块。简单的动态数据结构将有助于记录保存。可以仅使用整数来计算块的数量,但是具有包含块ID,数据行计数和指向下一节点的指针的节点的单链表将优雅地处理任意大的数据块。创建ID = 0,数据行计数为0,指针nullify()'d的头节点。

Fortran Wiki有一堆关于单链表的参考文献:http://fortranwiki.org/fortran/show/Linked+list

由于解析很简单(例如没有回溯),因此您可以在读取时处理每一行。迭代文件中的行,使用adjustl()处理前导空格,然后检查前两个字符:如果它们是'#,则将块计数器递增1并将新节点添加到列表中并将其ID设置为块计数器(1)的值,并处理下一行。

除此之外:我有一个名为munch()的简单字符函数,它只是trim(adjustl())。非常适合从字符串的两端剥去空白。它不像Perl chop()chomp()那样,而Fortran的trim()更像是rtrim(),所以munch()是下一个最佳名称。

如果该行与块头不匹配,请检查第一个字符是否为数字;如果index('0123456789', line(1:1))的第一个字符是数字,则line大于零,否则返回0.增加链表的头节点中的数据行计数,然后继续处理下一行

请注意,如果块计数为零,则这是一个错误条件;写出友好的“在块头之前看到的数据行”错误消息,最后一行读取和(理想情况下)文件中的行号。它需要更多的努力,但从用户的角度来看它是值得的,特别是如果你是主要用户。

否则,如果该行不是块头或数据行,则处理下一行。

最终你会点击文件的末尾,你将留下块计数器和至少有一个节点的链表。根据以后如何使用此数据,您可以动态分配块计数器长度的整数数组,然后将数据行计数从链表传输到数组。然后,您可以解除分配链接列表并直接访问任何块的数据行计数,因为块索引与数组索引匹配。

我使用类似的技术来读取任意长的数据列表。单链表对代码非常简单,避免了重新分配和扩展动态数组的烦恼。但是一旦知道了数据量,我就会创建一个动态数组,我需要的确切大小,并从链表中复制数据,这样我就可以快速访问数据,而不需要一直遍历列表。

由于Fortran没有值得一提的标准库,我还使用了这种技术的变体和插入排序来同时读取和排序数据。

很抱歉,没有代码,但足以让你入门。定义文件格式是关键;一旦你这样做,解析器几乎写出自己。它还可以让您考虑特殊情况:块头之前的数据,您希望如何处理空白和无法识别的输入等。如果您计划共享数据,那么明确写下这些数据会非常有用; Fortran世界充斥着记录不完整的自定义数据文件格式。请不要添加到残骸......

最后,如果你真的有野心/疯狂,你可以把它写成recursive程序,让你的功能编程朋友的头脑爆炸。 :)