File io 使用Fortran 90正确读取输入文件中的注释行

File io 使用Fortran 90正确读取输入文件中的注释行,file-io,comments,fortran,gfortran,File Io,Comments,Fortran,Gfortran,据我所知,Fortran在从文件中读取数据时,会跳过以和星号(*)开头的行,假设它们是注释。嗯,我似乎在用我创建的一个非常简单的程序实现这种行为时遇到了问题。这是我的简单Fortran程序: 1 program test 2 3 integer dat1 4 5 open(unit=1,file="file.inp") 6 7 read(1,*) dat1 8 9 10 end progr

据我所知,Fortran在从文件中读取数据时,会跳过以和星号(*)开头的行,假设它们是注释。嗯,我似乎在用我创建的一个非常简单的程序实现这种行为时遇到了问题。这是我的简单Fortran程序:

  1       program test
  2 
  3       integer dat1
  4 
  5       open(unit=1,file="file.inp")
  6 
  7       read(1,*) dat1
  8 
  9 
 10       end program test
这是“file.inp”:

我用

gfortran -g -o test test.f90
当我运行时,我得到一个错误:

At line 7 of file test.f90 (unit = 1, file = 'file.inp')
Fortran runtime error: Bad integer for item 1 in list input
当我在删除注释行的情况下运行输入文件时,即:

1 1

代码运行良好。因此,Fortran正确解释注释行似乎有问题。这肯定是我在这里遗漏的非常简单的东西,但我在google上找不到任何东西。

Fortran不会自动跳过输入文件中的注释行。通过首先将该行读入字符串,检查注释符号的第一个字符或搜索该符号的字符串,然后如果该行不是注释,则对该字符串进行“内部读取”以获得数值,可以非常轻松地完成此操作

比如:

use, intrinsic :: iso_fortran_env

character (len=200) :: line
integer :: dat1, RetCode

read_loop: do
   read (1, '(A)', isostat=RetCode)  line
    if ( RetCode == iostat_end)  exit ReadLoop
    if ( RetCode /= 0 ) then
      ... read error
      exit read_loop
    end if
    if ( index (line, "*") /= 0 )  cycle read_loop
    read (line, *) dat1
end do read_loop

Fortran默认情况下不会忽略任何内容,除非您使用的是名称列表,在这种情况下,注释以感叹号开头。

我发现使用该语句比建议的解决方案更直观。当在行首遇到注释字符“#”时,以下子例程跳过该行

subroutine skip_comments(fileUnit)
  integer, intent(in) :: fileUnit
  character(len=1) :: firstChar

  firstChar = '#'
  do while (firstChar .eq. '#')
    read(fileUnit, '(A)') firstChar
  enddo
  backspace(fileUnit)

end subroutine skip_comments
此子例程可在
read
语句之前的程序中使用,如下所示:

open(unit=10, file=filename)
call skip_comments(10)
read(10, *) a, b, c
call skip_comments(10)
read(10, *) d, e
close(10)
上述实施的限制:

  • 如果注释放在跨越多行的变量(例如数组)的值之间,则它将不起作用
  • 对于大型输入文件,这是非常低效的,因为在遇到backspace语句时,整个文件从开始到前一个字符都会被重新读取
  • 只能用于
    顺序
    访问文件,即典型的ASCII文本文件。使用
    direct
    append
    访问类型打开的文件将不起作用

  • 然而,我发现它非常适合用于提供用户参数的短文件。

    是的,我刚刚发现了这一点,实际上,我正在回来发布我的解决方案。但是,您的代码比我提出的解决方案要聪明一点(我在read语句中使用了“end=”选项)。但有一件事我不明白,那就是使用“iso_fortran_env”有什么必要?很抱歉,我已经编写了一些大型Fortran程序并使其正常工作,但对于内部模块以及它们给表带来的内容,我有点不知所措。除此之外,iso_Fortran_env提供了值“isostat_end”,以测试非零返回代码是否是文件的结尾。这允许使用“exit”构造而不是语句标签,就像“end=LineNumber”一样。我们不要忘记迷人的“禁止对使用列表定向或名称列表格式编写的记录进行退格”
    open(unit=10, file=filename)
    call skip_comments(10)
    read(10, *) a, b, c
    call skip_comments(10)
    read(10, *) d, e
    close(10)