如何在 Fortran 90 中向动态数组添加新元素

cha*_*ort 5 fortran dynamic-arrays fortran90 intel-fortran

当我最初无法预测数组的确切大小时,我需要在 Fortran 90 中使用动态数组。所以我编写了一段代码,每次将新元素添加到数组末尾时,该代码都应该扩展可分配数组:

  subroutine DArray()

  double precision, dimension(:), allocatable :: list

  allocate(list(1))

  list(1) = 1.1

  call AddToList(list, 2.2)
  call AddToList(list, 3.2)
  call AddToList(list, 4.2)
  call AddToList(list, 5.2)

  print *, list(1)
  print *, list(2)
  print *, list(3)
  print *, list(4)
  print *, list(5)


  end



  subroutine AddToList(list, element)

  double precision :: element
  double precision, dimension(:), allocatable :: list
  double precision, dimension(:), allocatable :: clist

  if(allocated(list)) then
    isize = size(list)
    allocate(clist(isize+1))
    do i=1,isize
        clist(i) = list(i)
    end do
    clist(i+1) = element

    deallocate(list)
    allocate(list(isize+1))

    do i=1,isize+1
        list(i) = clist(i)
    end do

    deallocate(clist)

  end if


  end
Run Code Online (Sandbox Code Playgroud)

那么有人看到我在这里是否遗漏了一些东西吗?


由francescalus解决。

双精度动态数组的工作代码是:

  module DynamicalArrays

  contains

      subroutine AddToList(list, element)

          IMPLICIT NONE

          integer :: i, isize
          double precision, intent(in) :: element
          double precision, dimension(:), allocatable, intent(inout) :: list
          double precision, dimension(:), allocatable :: clist


          if(allocated(list)) then
              isize = size(list)
              allocate(clist(isize+1))
              do i=1,isize          
              clist(i) = list(i)
              end do
              clist(isize+1) = element

              deallocate(list)
              call move_alloc(clist, list)

          else
              allocate(list(1))
              list(1) = element
          end if


      end subroutine AddToList


  end module DynamicalArrays
Run Code Online (Sandbox Code Playgroud)

可以填充数组的演示子例程是:

  subroutine UserDArrayTest()

  use DynamicalArrays


  integer :: i
  double precision, dimension(:), allocatable :: list
  double precision :: temp

  temp = 0.1
  do i=1,10
    temp = temp+1
    call AddToList(list, temp)
  end do

  do i=1,10
    print *, i, list(i)
  end do


  end
Run Code Online (Sandbox Code Playgroud)

请注意,最好将模块代码保存在单独的文件中,但我还发现当模块代码位于主程序和子例程代码之上时它会起作用。

fra*_*lus 6

我怀疑,当你看着一件文物时,你注意到了这个问题——但很快就转移了注意力。

对我来说可疑的行是:

    allocate(clist(isize+2))
Run Code Online (Sandbox Code Playgroud)

为什么不是新尺寸isize+1?我猜你已经尝试过了,但是程序失败了。

了解程序失败(可能崩溃)的原因是您无法获得正确结果的关键。仔细观察循环(为了清楚起见,删除了 print 语句)。

do i=1,isize
    clist(i) = list(i)
end do
clist(i+1) = element
Run Code Online (Sandbox Code Playgroud)

您想说“将列表中的所有元素复制到 clist,然后追加元素”。哪个是对的。然而

do i=1,isize
    clist(i) = list(i)
end do
! Here, i=isize+1
clist(i+1) = element
! Which means
! clist(isize+2) = element.
Run Code Online (Sandbox Code Playgroud)

总之,在循环之后,循环索引变量不再具有最终迭代中的值。