在将格式化输出写入变量时,我收到错误
forrtl: severe (27): too many records in I/O statement
我已检查过明显的事情 - 数据是否超出格式长度,反之亦然,变量的数量和类型与格式说明符兼容 - 我无法理解为什么应该抛出错误。
最小的说明性示例是:
program TXTERR27
use iso_fortran_env, only: OUTPUT_UNIT
implicit none
double precision :: F1, F2
integer :: I1
character (len=25), parameter :: A1 = 'AaaaaAaaaaAaaaaAaaaaAaaaa'
character (len=250) :: A2
10 format(/, 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ', I3, 'ZZZZZZZZZZZ', &
F10.3, 1X, A25, /, 'ZZZZZZZZZZZZZZZZZ', F6.3, 'ZZZZZZZZ')
20 format('Result :[', A250, ']')
continue
I1 = 1
F1 = 1.0D0
F2 = 1.0D-3
write(OUTPUT_UNIT, *) "This works:"
write(OUTPUT_UNIT, 10) I1, F1, A1, F2
write(OUTPUT_UNIT, *)
write(OUTPUT_UNIT, *) "This doesn't:"
write(A2, 10) I1, F1, A1, F2
write(OUTPUT_UNIT, 20) A2
stop
end program TXTERR27
这是通过使用:
编译的ifort -warn all -check all -traceback -o txterr27 txterr27.f90
并且不会产生警告或错误。输出如下:
This works:
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1ZZZZZZZZZZZ 1.000 AaaaaAaaaaAaaaaAaaaaAaaaa
ZZZZZZZZZZZZZZZZZ 0.001ZZZZZZZZ
This doesn't:
forrtl: severe (27): too many records in I/O statement, unit -5, file Internal Formatted Write
Image PC Routine Line Source
txterr27 000000000046EEBE Unknown Unknown Unknown
txterr27 000000000046D956 Unknown Unknown Unknown
txterr27 00000000004266A2 Unknown Unknown Unknown
txterr27 0000000000403BBB Unknown Unknown Unknown
txterr27 0000000000403122 Unknown Unknown Unknown
txterr27 0000000000419A44 Unknown Unknown Unknown
txterr27 0000000000417BFC Unknown Unknown Unknown
txterr27 0000000000402586 MAIN__ 26 txterr27.f90
txterr27 00000000004021DC Unknown Unknown Unknown
libc.so.6 00007F083D474EC5 Unknown Unknown Unknown
txterr27 00000000004020D9 Unknown Unknown Unknown
要检查这是否是特定于编译器的问题,我在gfortran下重建了示例代码:
gfortran -pedantic -Wall -fbacktrace -o txterr27 txterr27.f90
得到了类似的结果:
This works:
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1ZZZZZZZZZZZ 1.000 AaaaaAaaaaAaaaaAaaaaAaaaa
ZZZZZZZZZZZZZZZZZ 0.001ZZZZZZZZ
This doesn't:
At line 26 of file txterr27.f90
Fortran runtime error: End of file
显然,格式化数据没有问题,否则写入stdout会失败。我只能想到CRLF
s('/'
)导致write()
将结果呈现为数组而不是标量。将数组写入stdout可以正常工作(每行一个条目)但如果它试图将数组写入标量则会失败。
gfortran
和ifort
的错误消息都有很多不足之处;向已故道格拉斯亚当斯道歉:" 大部分无用"
有什么想法吗?
更新:继续分析,问题在于我对什么构成了记录'在Fortran。这是一个更新的插图:
program TXTERR27A
use iso_fortran_env, only: OUTPUT_UNIT
implicit none
double precision :: F1, F2
integer :: I1
character (len=25), parameter :: A1 = 'AaaaaAaaaaAaaaaAaaaaAaaaa'
character (len=250) :: A2
character (len=250), dimension(5) :: A3
10 format(/, 'ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ', I3, 'ZZZZZZZZZZZ', &
F10.3, 1X, A25, /, 'ZZZZZZZZZZZZZZZZZ', F6.3, 'ZZZZZZZZ')
20 format('Result: [', A250, ']')
30 format('Result:', /, '[', *(A250, ']', /, '['))
continue
I1 = 1
F1 = 1.0D0
F2 = 1.0D-3
A2 = ''
A3 = ''
write(OUTPUT_UNIT, *) "This works:"
write(OUTPUT_UNIT, 10) I1, F1, A1, F2
write(OUTPUT_UNIT, *)
write(OUTPUT_UNIT, *) "Does this?"
write(A3, 10) I1, F1, A1, F2
write(OUTPUT_UNIT, 30) A3
write(OUTPUT_UNIT, *) "This doesn't:"
write(A2, 10) I1, F1, A1, F2
write(OUTPUT_UNIT, 20) A2
stop
end program TXTERR27A
此示例显示在写入内部变量时会发出多个记录/字符串,并且问题(如可疑)是write()
试图将数组放入标量中。如果您将'/'
视为记录分隔符,而不是简单的CRLF
,则这是有意义的:
This works:
ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1ZZZZZZZZZZZ 1.000 AaaaaAaaaaAaaaaAaaaaAaaaa
ZZZZZZZZZZZZZZZZZ 0.001ZZZZZZZZ
Does this?
Result:
[ ]
[ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 1ZZZZZZZZZZZ 1.000 AaaaaAaaaaAaaaaAaaaaAaaaa ]
[ZZZZZZZZZZZZZZZZZ 0.001ZZZZZZZZ ]
[ ]
[ ]
[
This doesn't:
At line 34 of file txterr27.f90
Fortran runtime error: End of file
如果你记住Fortran I / O的古老的面向记录的特性,这个问题是显而易见的。经过1969年之后开发的具有文本I / O功能的语言的长期经验,这很容易忘记。抱歉没有看到这一点。
无论如何,重要的一点是要记住'/'
是一个记录分隔符,而不是将其视为Fortran的\n
版本。
答案 0 :(得分:2)
新行说明符/
充当列表导向输入的分隔符。所以你试图将三个记录写入一个内部文件。
只允许一个内部文件,因此在第一个记录之后,到达内部文件的末尾。也就是说,gfortran
正在告诉你什么。
答案 1 :(得分:1)
斜杠编辑描述符(/
)不直接标记新行(CRLF或适用于系统的任何内容)。它仅表示转移到(在输出的情况下)当前记录的结束。当您的处理器将记录视为一条线时,您会在输出到标准输出时看到此清单作为新行。
内部文件(字符变量)不同。如果您有标量字符变量(A2
),则会定义变量长度的单个记录。当您尝试将多个记录写入此变量时,您会看到错误。
但是,可以将多个记录写入内部文件,我们可以在Fortran 2008 9.4中看到:
如果文件是字符数组,则将其视为字符数组元素序列。每个数组元素(如果有)都是文件的记录。
然后,您可以将A2
声明为大小(至少)3的数组。
或者,如果您真的在标量变量中的新行作为单个记录之后,可以考虑内在的new_line
内在函数,或者内在函数的C_NEW_LINE
和C_CARRIAGE_RETURN
模块iso_c_binding
。
答案 2 :(得分:0)
之前我遇到过类似的麻烦...当我试图在数据文件中找到标记</DATA>
时
像
<DATA>
100 200 300
</DATA>
使用像
这样的程序program main
character(50) :: str
open( 10, file="some.xml", status="old" )
do
read( 10, * ) str
print *, trim( str )
if ( str == "</DATA>" ) then
print *, "tag found!"
exit
endif
enddo
close(10)
end
我遇到了错误
<DATA>
100
<
At line 7 of file test.f90 (unit = 10, file = 'some.xml')
Fortran runtime error: End of file
并且花了很长时间才注意到Fortran不喜欢斜杠(/)......通过将读取语句更改为
read( 10, "(a)" ) str
该计划给出了预期的结果
<DATA>
100 200 300
</DATA>
tag found!