【问题标题】:How to add new element to dynamical array in Fortran 90如何在 Fortran 90 中向动态数组添加新元素
【发布时间】:2015-03-18 20:49:59
【问题描述】:

当我最初无法预测数组的确切大小时,我需要在 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

那么有人看看我是否在这里遗漏了什么吗?


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

可以从中填充数组的演示子程序是:

  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

请注意,最好将模块代码保存在单独的文件中,但我也发现当模块代码高于主程序和子程序代码时它可以工作。

【问题讨论】:

  • 你有什么问题/错误?
  • 程序在deallocate(list) 冻结,没有任何进一步运行。没有打印出错误,它只是冻结并且什么都不做。
  • 您可能不是指 Fortran 90,但在 DArray 中,explicit interface 必须可用于 AddToList:它具有可分配的虚拟参数。
  • 我用已实现的接口更新了问题。但它们对我来说仍然无法正常工作......
  • 请不要过多更改问题,也不要使用任何 [已解决] 标签。该问题是供未来读者参考的,并且可以通过其他方式看到它具有可接受的答案。这不是一个讨论论坛。

标签: fortran fortran90 dynamic-arrays intel-fortran


【解决方案1】:

我怀疑,看着一个人工制品,你注意到了这个问题 - 但很快就继续前进。

对我来说可疑的线是:

    allocate(clist(isize+2))

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

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

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

您想说“将所有元素从列表复制到 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.

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

【讨论】:

  • 哦,哇,它现在工作得很好,修正了clist(isize+1) = element(我不知道在fortran中end do之后的最后一个索引变成isize+1)。附言你知道是否可以在每个子程序的开头避免使用 6 行这些接口,我想在哪里使用动态数组?也许有可能以某种方式将它们放在USE 语句和模块上?
  • 一个模块将是我提供显式接口的首选(而不是接口块)方式,示例很容易在此处搜索。随着我们继续进行代码推荐,我还将提出move_alloc 内在函数。甚至可能考虑链接列表而不是动态调整大小。
  • 非常感谢。我刚刚添加了module 更正,现在看起来更好了。还纠正了最初不需要分配数组和move_alloc。我在问题的顶部使用了更改,其他用户可以轻松找到完整的代码。让我们实际上为另一个故事保留链接列表:)
【解决方案2】:

我知道这个问题很老了,但我最近不得不构建这样一个子程序,我发现,从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 生成等效的例程,用于将数组附加到另​​一个...,然后将它们全部包装在一个接口中,以便您始终可以调用相同的子例程,无论您的数据类型如何。

【讨论】:

  • 是的,即使当问题要求 Fortran 90 时,将它放在这里也可能很有用。尽管stackoverflow.com/questions/38758216/… 我们在更通用的问题和答案中确实有
  • 最终这会让那些发现数组的下限在添加元素后发生变化的人感到惊讶。
  • @francescalus 你是什么意思?这个过程不安全吗?
  • @HermanToothrot,该过程是“安全的”,但它可能会以意想不到的方式改变事情。考虑allocate (vec(0:5), source=[1,2,3,4,5,6]); print*, lbound(vec); call append_int(vec, 6); print*, lbound(vec); call append_int(vec, 7); print*, lbound(vec)
猜你喜欢
  • 2017-09-14
  • 2011-02-20
  • 2013-05-28
  • 1970-01-01
  • 2012-04-18
  • 2015-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多