5

多年前,我使用了 FORTRAN,最近我的任务是维护一个旧的 FORTRAN 程序 (F77)。以下代码不熟悉:

      READ(FILE_LOG_UNIT, IOSTAT=FILE_STATUS) NUM_WORDS,  
   .    ( BUFFER(BIX), BIX=1, NUM_WORDS )  

回顾一些在线论坛发现,让我感到困惑的部分,即续行,是一个隐含的循环。由于我的程序在这里给我带来了麻烦,因此我想将其转换为传统的 DO 循环。转换它也可能会帮助下一个在 5 年后冷冷地捡起这个东西的穷人!无论如何,我对 DO 循环等效项的最佳猜测是

  READ(FILE_LOG_UNIT, IOSTAT=FILE_STATUS) NUM_WORDS  
  DO BIX=1, NUM_WORDS  
    READ(FILE_LOG_UNIT, IOSTAT=FILE_STATUS) BUFFER(BIX)  
  ENDDO  

但是当我只做这个改变时,正在工作的测试用例停止工作。我仍然觉得这里发生的是两个不同的 READ(第一个获取 NUM_WORDS,第二个循环遍历数据),所以我尝试了一个不太剧烈的更改,将其转换为两个语句,但保留了隐含的循环:

  READ(FILE_LOG_UNIT, IOSTAT=FILE_STATUS) NUM_WORDS  
  READ(FILE_LOG_UNIT, IOSTAT=FILE_STATUS) ( BUFFER(BIX), BIX=1, NUM_WORDS )  

但是只是这种变化也会导致好的测试用例失败。在我的两个更改中,NUM_WORDS 的值都按预期通过,因此循环似乎是它失败的地方。

那么,原始隐含循环的等效 DO 循环是什么?还是我完全走错了路?
谢谢

4

1 回答 1

3

文件是如何打开的?即它是 ACCESS='sequential'、access='direct' 还是 access='stream'(好吧,最后一个不太可能,因为它是 F2003 的添加)。其次,它是格式化的还是未格式化的?我将假设它是未格式化的顺序,因为在您的读取语句中没有 REC= 说明符或格式说明符。

您尝试失败的原因是每个 read 语句都读取一条单独的记录。在 F2003 中引入 access='stream' 之前,Fortran I/O 完全基于记录,这与我们这些在大多数其他语言中用于流式传输类型文件的人略有不同。

未格式化的顺序文件的记录通常在记录的每一端由“记录标记”分隔,通常用 4 个字节指定记录的长度。所以记录(在磁盘上)可能看起来像

| 长度(4 字节) | num_words(4 个字节?) | 缓冲区(1) | 缓冲区(2) | ... | 长度 |

现在,如果您尝试使用一个 READ 语句读取 num_words ,它将正确地从文件中读取 num_words ,然后它将向前跳到下一条记录的开始。然后,当您尝试使用单独的 READ 语句读取缓冲区时,您已经在文件中遥遥领先。

如果您作弊并使用 F90+ 数组语法,您可能会侥幸逃脱

READ(FILE_LOG_UNIT, IOSTAT=FILE_STATUS) NUM_WORDS, BUFFER(1:NUM_WORDS)

(尽管我不确定您是否可以在写入它的同一语句中引用 num_words )

于 2014-05-08T21:29:17.953 回答