Reputation: 565
So I'm trying to understand some basic fortran IO and having trouble. I've written the following
program RFF
implicit none
! Variables
integer :: ierr
character (:), allocatable :: Filename
character (:), allocatable :: read_in
! Body of RFF
Filename = 'string_test.txt'
open(10, file=Filename, status='old', action='read',iostat=ierr) !What is iostat?
do while (ierr.eq.0) !What is this do loop doing exactly?
read(10,'(A)',iostat = ierr) read_in !What does '(A)' mean? I know it's a format descriptor, but nothing beyond that
print*, read_in !Nothing gets output to the terminal here
enddo
write(*,*) 'Press Enter to Exit'
read(*,*)
!Is deallocating dynamically allocatable strings something I should do?
deallocate(Filename)
end program RFF
Which I've fed the very simple text file containing the word 'arbitrary' and nothing else. When I run the program, nothing crashes but nothing gets output to the terminal, either. Can someone help me understand what is going on? Note I've inserted a number of other questions into the comments of the code I've pasted. I'd like help understanding those as well.
Thanks
Upvotes: 0
Views: 2055
Reputation: 2367
The real problem is that you must allocate read_in
before you assign to it with read
. One other thing: iostat
is used to indicate either completion status or a possible error condition. See the code comments and official docs for other details (for example, here).
Here is a working solution:
program main
implicit none
character(len=20) :: read_in ! fixed-length string
character(len=:), allocatable :: word, filename ! allocatable strings
integer :: iostat_1, iostat_2 ! status indicators
integer :: lun ! file logical unit number
filename = 'read_test.txt' ! allocate on assignment
iostat_1 = 0 ! initialization
iostat_2 = 0
open(newunit=lun, file=filename, status='old', iostat=iostat_1)
if (iostat_1 == 0) then ! no error occurred
do while(iostat_2 == 0) ! continues until error/end of file
read(lun, '(a)', iostat=iostat_2) read_in
if (iostat_2 == 0) then
word = trim(read_in) ! allocate on assignment to trimmed length.
endif
enddo
if (allocated(word)) then
print *, "read_in:", read_in
print *, "len(read_in)", len(read_in)
print *, "Word:", word
print *, "len(word)=", len(word)
else
print *, "Word was not allocated!"
endif
endif
end program main
Example output:
read_in:arbitrary
len(read_in) 20
Word:arbitrary
len(word)= 9
Upvotes: 1
Reputation: 8140
There are two questions in your one code, so let me address them first:
What is iostat
? -- iostat
is an error code relating to the I/O statement. If everything worked fine, it will be set to 0
, if not, it will have a non-zero value. Examples on what could go wrong when trying to open a file:
What is (A)
? -- This is the format string. (A)
refers to a string of arbitrary length. See here for more information
The code looks as if it should work, however the result isn't what you expect. There are two possibilities that spring to my mind:
The file you are trying to read doesn't exist, or doesn't exist in the directory that you are executing the program in, or you don't have the permission to read it. This results in ierr
being set to a non-zero error code (corresponding to 'File not Found'). This results in the do
loop not executing even once since the ierr
isn't zero to start with.
I recommend using the newer iomsg
statement in addition to iostat
. iomsg
is a string that corresponds to a human-readable explanation to what went wrong.
character(len=100) :: iomsg
<snip>
open(10, file=Filename, status='old', action='read',iostat=ierr, iomsg=iomsg)
if (ierr /= 0) then
print*, "Error opening file " // trim(Filename)
print*, iomsg
STOP 1
end if
The file exist, but is empty. This would result in nothing being printed. Just check to be sure nothing has changed in the file.
Hint, both iostat
and iomsg
are available in all file I/O operations, so also for read
, write
, and even close
. It can't hurt to use them.
Upvotes: 0