I / O声明中记录太多的原因不明确"错误

时间:2015-07-11 17:53:15

标签: fortran gfortran intel-fortran

在将格式化输出写入变量时,我收到错误

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可以正常工作(每行一个条目)但如果它试图将数组写入标量则会失败。

gfortranifort的错误消息都有很多不足之处;向已故道格拉斯亚当斯道歉:" 大部分无用"

有什么想法吗?

更新:继续分析,问题在于我对什么构成了记录'在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版本。

3 个答案:

答案 0 :(得分:2)

新行说明符/充当列表导向输入的分隔符。所以你试图将三个记录写入一个内部文件。

只允许一个内部文件,因此在第一个记录之后,到达内部文件的末尾。也就是说,gfortran正在告诉你什么。

答案 1 :(得分:1)

斜杠编辑描述符(/)不直接标记新行(CRLF或适用于系统的任何内容)。它仅表示转移到(在输出的情况下)当前记录的结束。当您的处理器将记录视为一条线时,您会在输出到标准输出时看到此清单作为新行。

内部文件(字符变量)不同。如果您有标量字符变量(A2),则会定义变量长度的单个记录。当您尝试将多个记录写入此变量时,您会看到错误。

但是,可以将多个记录写入内部文件,我们可以在Fortran 2008 9.4中看到:

  

如果文件是字符数组,则将其视为字符数组元素序列。每个数组元素(如果有)都是文件的记录。

然后,您可以将A2声明为大小(至少)3的数组。

或者,如果您真的在标量变量中的新行作为单个记录之后,可以考虑内在的new_line内在函数,或者内在函数的C_NEW_LINEC_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!