0

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

outlaw
  • 241
  • 4
  • 16

2 Answers2

5

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
    
chw21
  • 7,970
  • 1
  • 16
  • 31
  • And let's not forget `a=[a,i]`. – francescalus Jul 11 '17 at 07:39
  • wait, what? Are you pulling my leg? – chw21 Jul 11 '17 at 07:56
  • For `a` an allocated allocatable integer array, it's perhaps closest to the MATLAB of the question. My fragment's just an array constructor with automatic reallocation on intrinsic assignment (not F90, naturally but neither is `move_alloc`). – francescalus Jul 11 '17 at 08:36
  • Thanks for the answer, i dont know what is allocation but i will try to figure it out – outlaw Jul 11 '17 at 15:58
  • If you've never used allocatable arrays before, check out this info: http://www.pcc.qub.ac.uk/tec/courses/f90/stu-notes/F90_notesMIF_11.html -- oh, and don't use pointers (as in my 3rd option) until you know exactly what you're doing. Pointers can be very confusing. – chw21 Jul 12 '17 at 00:42
2

The way I read your question, you have a subroutine that needs to fill an array, but that array is of unknown size, and you do not want to pass in the size. So you do NOT want this:

SUBROUTINE FILL( A, N )
    INTEGER N
    INTEGER A(N)
    INTEGER I
    DO I=1,N
        A(I) = I
    END DO
END SUBROUTINE FILL

Instead, you want to get the SIZE of the array:

SUBROUTINE FILL( A )
  INTEGER A(:)
  INTEGER I
  DO I=1,SIZE(A)
     A(I) = I
  END DO
END SUBROUTINE FILL
Jack
  • 5,801
  • 1
  • 15
  • 20