I need to pass arrays of variables to a subroutine that should change their values according to an external file. The problem is that this should be as generic as possible so if the file has n values I should be able to pass n generic integers.
Here is an example of my code:
program dummy
use checkpt
implicit none
integer :: i1=0, i2=0, k=1, n, cpt
integer*8 :: lastTime
call load_checkpoint(ints=[k,i1,i2])
--some code happening--
end program dummy
And the subroutine called is the following:
subroutine load_checkpoint(ints)
implicit none
integer, intent(inout) :: ints(:)
integer :: stat
open(8989, file='temp.txt', status='old', action='READ', iostat=stat)
if (stat .eq. 0) then
read (8989,*,iostat=stat) ints
end if
close(8989)
end subroutine load_checkpoint
What I get is Error: Non-variable expression in variable definition context (actual argument to INTENT = OUT/INOUT) at (1)
and I can't understand why. I also tried with non initialized variables but I get the same error. Can anybody help me, please?
CodePudding user response:
If a dummy argument is intent(out)
or intent(inout)
, then the actual argument shall not be an expression. Your actual argument [k,i1,i2]
is an expression (that forms a rank one array from 3 scalar variables), this is why you get an error here.
If you want your variables k
, i1
and i2
to be updated at the end you have to write more lines (and in the called subroutine you should attribute only intent(out)
to ints, as you don't use at all the input values):
integer :: ints(3)
call load_checkpoint(ints=ints)
k = ints(1)
i1 = ints(2)
i2 = ints(3)
CodePudding user response:
You can even return an allocatable array from a function.
Checking datafiles with arbitrary number of lines, arbitrary number of integers per line is a bit messy.
module checkpt
implicit none
contains
function load_checkpoint()
integer, allocatable :: load_checkpoint(:)
integer nvars, i
integer stat
character(len=1000) line
open( 10, file="temp.txt", status="old", action="read", iostat=stat )
if ( stat == 0 ) then
! First pass - count variables (arbitrary number per line, arbitrary number of lines)
nvars = 0
do
read( 10, "( a )", iostat=stat ) line
if ( stat /= 0 ) exit
do i = 1, len_trim( line )
if ( isdigit( line(i:i) ) .and. ( i == 1 .or. ( i > 1 .and. .not. isdigit( line(i-1:i-1) ) ) ) ) nvars = nvars 1
end do
end do
! Second pass - store variables
allocate( load_checkpoint( nvars ) )
rewind( 10 )
read( 10, *, iostat=stat ) load_checkpoint
else
write( *, * ) "Unable to read file"
stop
end if
close( 10 )
end function load_checkpoint
logical function isdigit( c )
character, intent(in) :: c
isdigit = c >= '0' .and. c <= '9'
end function isdigit
end module checkpt
!========================================================================
program dummy
use checkpt
implicit none
integer, allocatable :: intvars(:)
intvars = load_checkpoint()
write( *, "( *( i0, 1x ) )" ) intvars
end program dummy