I am trying to write a function that extracts a specified line from a given file. My function to do so takes two arguments:
I have wrapped this function inside a module (routines.f95), as shown:
module routines
contains
function getLine(fUnit, fLine)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Get the nth line of a file. It is assumed that the file is !
! numerical only. The first argument is the unit number of the !
! file, and the second number is the line number. If -1 is !
! passed to the second argument, then the program returns the !
! final line of the program. It is further assumed that each !
! line of the file contains two elements. !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
implicit none
integer, intent(in) :: fUnit, fLine
integer :: i
real, dimension(2) :: tmp, getLine
if (fline .eq. -1) then
do
read(fUnit, *, end=10) tmp
end do
else
do i = 1, fLine
read(fUnit, *, end=10) tmp
end do
end if
10 getLine = tmp
end function getLine
end module routines
To test this function, I set up the following main program (test.f95):
program test
use routines
implicit none
integer :: i
real, dimension(2) :: line
open(21, file = 'data.dat')
do i = 1, 5
line = getLine(21, i)
write(*, *) i, line
end do
close(21)
end program test
The file data.dat contains the following information:
1.0 1.00
2.0 0.50
3.0 0.33
4.0 0.25
5.0 0.20
This code is a simplified version of the one I've written, but it reflects all the errors I obtain in my primary code. When I compile the above code with the commands
gfortran -c routines.f95
gfortran -c test.f95
gfortran -o test test.o routines.o
I do not obtain any syntax errors. The output of the program gives the following:
1 1.00000000 1.00000000
2 3.00000000 0.330000013
3 5.00000000 0.200000003
At line 28 of file routines.f95 (unit = 21, file = 'data.dat')
Fortran runtime error: Sequential READ or WRITE not allowed after EOF marker, possibly use REWIND or BACKSPACE
Error termination. Backtrace:
#0 0x7f2425ea15cd in ???
#1 0x7f2425ea2115 in ???
#2 0x7f2425ea287a in ???
#3 0x7f242601294b in ???
#4 0x400ccb in ???
#5 0x4009f0 in ???
#6 0x400b32 in ???
#7 0x7f2425347f49 in ???
#8 0x400869 in ???
at ../sysdeps/x86_64/start.S:120
#9 0xffffffffffffffff in ???
I understand that the error is being thrown because the program tries to extract a line that is past the EOF marker. The reason for this is because the program is skipping every other line, and thus skipping over the last line in the program.
Could someone please help me to understand why my program is skipping every other line of the input file? I am unable to find the issue in my code.
The position of a connected external file is a global state. In this case, the function getline
changes the position of the file after it has searched. The next time the function is called, searching commences from the position it was left.
What you see, then, is not so much "skipping" of lines, but:
However, the third line in the third iteration (the sixth of the file) is after an end-of-file condition. You see the result of reading the fifth line.
To enable seeking as you desire it, ensure that you position the file at its initial point before skipping lines. The rewind
statement places a connected file at its initial position.
Instead of rewinding, you may close the file and re-open with position='rewind'
to ensure it is positioned at its initial point, but the rewind
statement is a better way to reposition. If you re-open without a position=
specifier you see an effect similar to position='asis'
. This leaves the position in the file unspecified by the Fortran standard.