Вот пример функции Fortran, возвращающей массив переменной длины.Это функция Fortran 2003. Также в тестовом драйвере также используется автоматическое распределение при назначении, еще одна функция Fortran 2003.
module my_subs
contains
function select(x) result(y)
implicit none
integer, dimension (:), intent (in) :: x
integer, dimension (:), allocatable :: y
integer :: i, j
j = 0
do i=1, size (x)
if (x(i)/=0) j = j+1
enddo
allocate ( y (1:j) )
j = 0
do i=1, size (x)
if (x(i)/=0) then
j = j+1
y(j) = x(i)
endif
enddo
return
end function select
end module my_subs
program test
use my_subs
implicit none
integer, dimension (6) :: array = [ 5, 0, 3, 0, 6, 1 ]
integer, dimension (:), allocatable :: answer
answer = select (array)
write (*, *) size (array), size (answer)
write (*, *) array
write (*, *) answer
stop
end program test
Вот альтернативное решение, использующее временный массив для «увеличения» выходных данных.массив (возврат функции) по мере необходимости.В то время как два прохода через входной массив исключены, копии массива требуются.Другая функция Fortran 2003, move_alloc, уменьшает количество необходимых копий.move_alloc также заботится о (пере) распределении выходного массива (здесь «y») и освобождении входного массива (здесь «temp»).Возможно, это более элегантно, но, вероятно, менее эффективно, поскольку используется несколько копий.Эта версия, вероятно, более образовательная, чем полезная.Версия @ eryksun использует один проход и одну копию за счет создания полного размера временного массива.
function select(x) result(y)
implicit none
integer, dimension (:), intent (in) :: x
integer, dimension (:), allocatable :: y, temp
integer :: i, j
j = 0
do i=1, size (x)
if (x(i)/=0) then
j = j+1
allocate (temp (1:j))
if ( allocated (y) ) temp (1:j-1) = y
call move_alloc (temp, y)
y(j) = x(i)
endif
enddo
return
end function select