reading/writing 时避免 Fortran 格式中的 GOTO 范例

Avoiding the GOTO paradigm in Fortran FORMAT when reading/writing

在大学里,教我们 Fortran 的教授给了我们下面的代码:

     program example
     integer year, month, day, inst, kind, ozone
     real time
     open(unit=1,file='C:1.dat')
     read(1,1000) year, month, day, inst, kind, ozone, time
     close(1)  
1000 format(i4,1x,i2,1x,i2,1x,i1,1x,i1,1x,i3,1x,f8.3)
     end

在此代码中,索引为 1000 的行指定了特定的输入格式。这不是像 GOTO 逻辑吗?如果是,在 Fortran 的上下文中,避免它的最合适方法是什么?

您可以通过使用 format strings 来避免使用格式标签,因为

program example
  integer year, month, day, inst, kind, ozone
  real time
  
  open(unit=1,file='C:1.dat')
  read(1,'(i4,1x,i2,1x,i2,1x,i1,1x,i1,1x,i3,1x,f8.3)') year, month, day, inst, kind, ozone, time
  close(1)
end

您可以将格式字符串视为常规 character 变量,如

program example
  integer year, month, day, inst, kind, ozone
  real time
  character(42) :: format
  
  open(unit=1,file='C:1.dat')
  format = '(i4,1x,i2,1x,i2,1x,i1,1x,i1,1x,i3,1x,f8.3)'
  read(1,format) year, month, day, inst, kind, ozone, time
  close(1)
end

这允许您像任何其他变量一样在代码周围传递格式,还允许您在运行时生成和修改格式。

在格式化数据传输语句中,可以通过三种方式指定要使用的格式(Fortran 2018 R1215):

  • 引用带标签的 FORMAT 语句
  • 使用(默认)字符表达式
  • 带有 *(针对列表格式)

例如(为清楚起见,使用 PRINT 语句):

1000 FORMAT (I0)

print 1000, 1     ! Pointing to a FORMAT statement
print '(I0)', 1   ! Literal constant: one form of a character expression
print *, 1        ! List-directed formatting

end

其中 none 是格式规范,其功能类似于 GO TO 语句。

GO TO 语句改变了执行流程,而在格式规范中,执行保留在数据传输语句处,然后继续到下一条语句。

为格式指定标签不会将执行控制转移到该语句,它只是说“使用语句 1000 给出的格式”。这在概念上就像

character(*), parameter :: CHAR_FMT='(I0)'
print CHAR_FMT, 1
end

表示“使用字符对象 CHAR_FMT(在其他地方是 declared/defined)”作为格式。

您会发现可能会反对 FORMAT 语句和(合理的)替代建议,但没有人反对使用 FORMAT 语句是基于“像一个 GO TO”。 (当然,GO TO 语句本身并不是邪恶的。)


格式规范可以与 err=end= 以及 eor= 说明符进行对比:这些在功能上类似于 GO TO 语句:


1 read(unit, fmt, err=10, end=20, eor=20) x
...
! COME FROM 1
20 continue
...

return
! COME FROM 1
10 ERROR STOP "Error in the read"

这种跳跃式的流程也可以通过 IOSTAT 控制来管理:

read(unit, fmt, iostat=iostat) x
if (iostat...) ...