Search code examples
fortrangfortranfortran90

Filling an array with unknown size in fortran90


I want to fill an array with unknown size in fortran90. This is the equivalent code in MATLAB :

for i=1:10
 A[i] = i
end

I know that i can pass the size, but How can i do this in fortran90 without passing the size of the array. I read that we can use pointers, but i really dont know how to deal with pointers


Solution

  • I understand you want to start adding elements to an array before you know the final size of the array.

    As an example, you want to read values from a file until you reach the end of the file, not knowing how many values there are.

    There are three ways I can think of:

    1. Create an array of sufficient size, and remember the final value.

       integer :: a(200), n
       n = 1
       do
           a(n) = <value>
           if (<finished>) exit
           n = n + 1
       end do
      
       <use a(1:n)>
      
    2. Create two allocatable arrays, when you reach the end of one, make the other bigger, and swap them:

       integer, allocatable :: a(:), tmp(:)
       integer :: i, n
       n = 8
       allocate(a(n))
       i = 1
       do
           if (i > n) then 
               allocate(tmp(2*n))
               tmp(1:n) = a(:)
               call move_alloc(tmp, a)
               n = n * 2
           end if
           a(i) = <value>
           if (<finished>) exit
           i = i + 1
       end do
       allocate(tmp(i))
       tmp(:) = a(1:i)
       call move_alloc(tmp, a)
      
    3. I do no longer recommend this. Pointers can be confusing and create weird and hard-to-debug bugs. But I leave it in for posterity: Create a linked list (here using a stack)

       type t_node
           integer :: value
           type(t_node), pointer :: next => NULL()
       end type t_node
      
       type(t_node), pointer :: list, tmp
       integer, allocatable :: a(:), i, n
      
       nullify(list)
       nullify(tmp)
      
       do
            allocate(tmp)
            tmp % value = <value>
            tmp % next => list
            list => tmp
            nullify(tmp)
            if (<finished>) exit
            n = n + 1
       end do
       allocate(a(n))
       do i = n, 1, -1
           a(i) = list % value
           tmp => list
           list => list % next
           deallocate(tmp)
       end do