5

据我了解,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”:

  1 *Hello
  2 1

我用

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 正确解释该注释行似乎是一个问题。这一定是我在这里想念的非常简单的东西,但我无法在谷歌上找到任何东西。

4

3 回答 3

8

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
于 2012-04-21T15:19:01.920 回答
0

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

于 2012-09-28T06:05:12.687 回答
0

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

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)

上述实现的限制:

  1. 如果注释放在跨越多行的变量的值之间,它将不起作用,例如数组。
  2. 对于大型输入文件,这是非常低效的,因为当遇到退格语句时,会从头开始重新读取整个文件直到前一个字符。
  3. 只能用于sequential访问文件,即典型的 ASCII 文本文件。direct使用或访问类型打开的文件append将不起作用。

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

于 2020-10-12T16:43:14.257 回答