5
votes

It is my understanding that Fortran, when reading data from file, will skip lines starting with and asterisk (*) assuming that they are a comment. Well, I seem to be having a problem with achieving this behavior with a very simple program I created. This is my simple Fortran program:

  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

This is "file.inp":

  1 *Hello
  2 1

I built my simple program with

gfortran -g -o test test.f90

When I run, I get the error:

At line 7 of file test.f90 (unit = 1, file = 'file.inp')
Fortran runtime error: Bad integer for item 1 in list input

When I run the input file with the comment line deleted, i.e.:

1 1

The code runs fine. So it seems to be a problem with Fortran correctly interpreting that comment line. It must be something exceedingly simple I'm missing here, but I can't turn up anything on google.

3

3 Answers

8
votes

Fortran doesn't automatically skip comments lines in input files. You can do this easily enough by first reading the line into a string, checking the first character for your comment symbol or search the string for that symbol, then if the line is not a comment, doing an "internal read" of the string to obtain the numeric value.

Something like:

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
0
votes

Fortran does not ignore anything by default, unless you are using namelists and in that case comments start with an exclamation mark.

0
votes

I found the use of the backspace statement to be a lot more intuitive than the proposed solutions. The following subroutine skips the line when a comment character, "#" is encountered at the beginning of the line.

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

This subroutine may be used in programs before the read statement like so:

open(unit=10, file=filename)
call skip_comments(10)
read(10, *) a, b, c
call skip_comments(10)
read(10, *) d, e
close(10)

Limitations for the above implementation:

  1. It will not work if the comment is placed between the values of a variable spanning multiple lines, say an array.
  2. It is very inefficient for large input files since the entire file is re-read from the beginning till the previous character when the backspace statement is encountered.
  3. Can only be used for sequential access files, i.e. typical ASCII text files. Files opened with the direct or append access types will not work.

However, I find it a perfect fit for short files used for providing user-parameters.