2015-07-11 159 views
1

在写格式化输出到一个变量,我得到的错误不明原因

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 

显然,格式化数据没有问题,否则写入标准输出将失败。我所能想到的是,CRLF'/')导致write()将结果呈现为数组而不是标量。将数组写入标准输出可以正常工作(每行一个条目),但如果它试图将数组写入标量,则会失败。

来自gfortranifort的错误消息有很多不足之处;道歉对已故道格拉斯亚当斯道歉:“Mostly Useless

任何想法?

更新:继续分析,问题在于我对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版本。

+2

是你的人确认后刚:是的,你不能将多个记录写入内部文件? – francescalus

+0

我想我不清楚什么是“记录”。我看到的是一个简单的字符串,但显然'/'是一个记录分隔符,而不仅仅是一个CRLF。这将解释我看到的行为。 – arclight

回答

2

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

只有一个内部文件是允许的,所以在第一个记录后,内部文件的末尾已到达。也就是说,gfortran告诉你。

+0

如果我以前看起来有点脾气暴躁,道歉;我想我们错过了对方说的话。 – arclight

1

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

内部文件(字符变量)是不同的。如果你有一个标量字符变量(A2),它定义了变量长度的单个记录。当你试图向这个变量写入多条记录时,你会看到错误。

但是,可以写入多个记录在内部文件,我们可以在2008年的Fortran 9.4参见:

如果文件的字符数组,它被视为序列字符数组元素。每个数组元素(如果有的话)都是该文件的记录。

你可以的话,声明A2为尺寸(至少)的阵列3

另外,如果你在你的标量变量,你可以考虑单个记录一个新的行之后是真正的内在模块iso_c_binding的内部或命名常量C_NEW_LINEC_CARRIAGE_RETURN

+0

谢谢;因为我试图将我们的代码迁移到F2008,所以我必须查看'new_line'和'iso_c_binding'。我一直自由地使用'adjustl()','trim()'和可分配长度的字符变量来将我们的输出从表格格式移开。写入内部文件对此至关重要,并且很容易忘记Fortran中的文本I/O仍然与其他语言根本不同。 – arclight

0

我有一个非常类似的麻烦之前...当我试图用一个程序一样

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>在数据文件中 像

<DATA> 
100 200 300 
</DATA> 

<DATA> 
100 
< 
At line 7 of file test.f90 (unit = 10, file = 'some.xml') 
Fortran runtime error: End of file 

并且花了很长时间才注意到Fortra n不喜欢斜杠(/)......通过改变读语句

read(10, "(a)") str 

程序得到所需要的结果

<DATA> 
100 200 300 
</DATA> 
tag found! 
+0

这可能是一个稍微不同的问题:'/'作为列表控制输入中的值分隔符终止输入语句。 – francescalus