首页 文章

Fortran读取语句超出了行尾

提问于
浏览
6

你知道以下声明是否可以通过fortran 90/95/2003标准之一保证真实吗? “假设一个字符变量的read语句被赋予一个空行(即只包含空格和换行符号) . 如果格式说明符是星号(*),它继续读取后续行,直到非空白如果格式说明符为'(A)',则将空字符串替换为字符变量 . “

例如,请查看以下最小程序和输入文件 .

程序代码:

PROGRAM chk_read
  INTEGER,         PARAMETER :: MAXLEN=30
  CHARACTER(len=MAXLEN)      :: str1, str2

  str1='minomonta'
  read(*,*)     str1
  write(*,'(3A)')  'str1_start|', str1, '|str1_end'

  str2='minomonta'
  read(*,'(A)') str2
  write(*,'(3A)')  'str2_start|', str2, '|str2_end'

END PROGRAM chk_read

输入文件:

----'input.dat' content is below this line----

yamanakako

kawaguchiko    
----'input.dat' content is above this line----

请注意,'input.dat'中有四行,第一行和第三行是空白的(仅包含空格和换行符) . 如果我运行程序为

$ ../chk_read < input.dat > output.dat

我得到以下输出

----'output.dat' content is below this line----
str1_start|yamanakako                    |str1_end
str2_start|                              |str2_end
----'output.dat' content is above this line----

变量'str1'的第一个读语句似乎是查看'input.dat'的第一行,找到一个空行,移到第二行,找到字符值'yamanakako',并将其存储在'str1'中” .

相反,变量'str2'的第二个read语句似乎给出了第三行,它是空白的,并将空行存储在'str2'中,而不是移到第四行 .

我尝试用英特尔Fortran(ifort 12.0.4)和GNU Fortran(gfortran 4.5.0)编译程序并得到相同的结果 .

稍微讨论一下这个问题的背景:我正在编写一个子程序来读取一个使用空行作为数据块分隔符的数据文件 . 我想确保在读取数据时丢弃空白行,只留下空白行 . 我还需要使其标准符合和便携 .

谢谢你的帮助 .

2 回答

  • 2

    来自Fortran 2008标准草案:

    列表导向输入/输出允许根据列表项的类型而不是格式规范进行数据编辑 . 它还允许数据为自由字段,即用逗号(或分号)或空格分隔 .

    然后:

    一个或多个列表定向记录中的字符构成一系列值和值分隔符 . 记录的结尾与空白字符具有相同的效果,除非它在字符常量内 . 任何两个或多个连续空白的序列都被视为单个空白,除非它在字符常量内 .

    这隐含地表明,在列表导向的输入中,空行被视为空白,直到下一个非空值 .

    在读取时使用fmt ='(A)'格式描述符时,空行被读入str . 另一方面,fmt = *表示自由格式的列表导向I / O,它会跳过空白行,直到找到非空字符串 . 要测试这个,请执行以下操作:

    PROGRAM chk_read
    INTEGER :: cnt
    INTEGER,         PARAMETER :: MAXLEN=30
    CHARACTER(len=MAXLEN)      :: str
    
    cnt=1
    do
      read(*,fmt='(A)',end=100)str
      write(*,'(I1,3A)')cnt,' str_start|', str, '|str_end'
      cnt=cnt+1
    enddo
    100 continue
    
    END PROGRAM chk_read
    
    $ cat input.dat
    
    
    
    yamanakako
    
    kawaguchiko
    

    EOF

    运行程序给出了这个输出:

    $ a.out < input.dat 
    1 str_start|                              |str_end
    2 str_start|                              |str_end
    3 str_start|                              |str_end
    4 str_start|yamanakako                    |str_end
    5 str_start|                              |str_end
    6 str_start|kawaguchiko                   |str_end
    

    另一方面,如果您使用默认输入:

    read(*,fmt=*,end=100)str
    

    你最终得到这个输出:

    $ a.out < input.dat 
    1 str1_start|yamanakako                    |str1_end
    2 str2_start|kawaguchiko                   |str2_end
    
  • 3

    F2008标准草案的这部分内容可能会解决您的问题:

    10.10.3列表导向输入7当下一个有效项属于字符类型时,输入形式由零或多个rep-char的可能分隔的序列组成,其类型参数由有效项的类型隐含 . 字符序列可以从一个记录的末尾继续到下一个记录的开头,但记录的结尾不应出现在撇号分隔的字符序列中的加倍撇号之间,也不应出现在引号分隔字符中的加倍引号之间 . 序列 . 记录的结尾不会导致空白或任何其他字符成为字符序列的一部分 . 可以根据需要在尽可能多的记录上继续字符序列 . 字符空白,逗号,分号和斜杠可能会出现在默认,ASCII或ISO 10646字符序列中 .

相关问题