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

问题描述 投票:2回答:2

我需要在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

所以有人知道我是否遗漏了什么吗?


解决者 .

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

  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

演示的子程序,可以从它那里填充数组。

  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

注意最好把模块代码放在单独的文件中 但我发现当模块代码在主程序和子程序代码之上时就可以使用了

fortran fortran90 dynamic-arrays intel-fortran
2个回答
4
投票

我怀疑,在看一个工件时,你注意到了这个问题--但很快就转移了。

在我看来,可疑的一行是:

    allocate(clist(isize+2))

为什么新的大小 isize+1? 我猜你试过了,但后来程序失败了。

查看程序为什么失败(可能是崩溃)是你为什么没有得到正确结果的关键。 仔细观察循环(为了清楚起见,打印语句被删除)。

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

你想说 "将所有元素从list复制到clist,然后追加元素"。 这是对的。 但是......您想说 "将所有元素从list复制到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.

综上所述,在循环之后,循环索引变量没有在最后迭代时的值。


0
投票

我知道这个问题很老了,但我最近要建立这样一个子程序,我发现,从Fortran2003开始,有一个漂亮的单行程序。

    SUBROUTINE append_int(vec, val)
    !***********************************************************************
    !> \brief Appends val in vec if not already present
    !> \date 05 2020
    !***********************************************************************
    INTEGER, DIMENSION(:), ALLOCATABLE, INTENT(INOUT)    :: vec
    INTEGER, INTENT(IN)                                  :: val

    ! Remove this test if you don't mind not having unique values
    IF (.NOT. ANY(vec .EQ. val)) THEN
        vec = [vec, val]
    END IF

    END SUBROUTINE

你的数组将以适当的大小自动重新分配.另外,你可以为Reals生成等价的例程,用于将一个数组追加到另一个数组上... 然后将它们全部包在一个接口中,这样无论你的数据类型如何,你总是可以调用同一个子例程。

© www.soinside.com 2019 - 2024. All rights reserved.