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...) ...
在大学里,教我们 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...) ...