我的程序正在运行 3D 数组,标记它找到的“簇”,然后进行一些检查以查看是否有任何相邻簇的标签高于当前簇。还有第二个数组包含“正确的”集群标签。如果它发现第 n 个相邻集群被正确标记,则将该元素分配给 0,否则将其分配给正确的标签(例如,如果第 n 个站点的标签为 2,并且邻居的标签为 3,则该元素的第 3 个元素
labelArray
设置为 2)。老实说,我有充分的理由这样做!
我想要的只是能够动态分配
labelArray
的第n个元素。我看过可分配的数组并将事物声明为labelArray(*)
但我并不真正理解这些,尽管搜索了网络和StackOverflow。
所以在这方面的任何帮助都会很棒。
这里是一个 Stack Overflow 问题,其中包含一些代码示例,展示了使用 Fortran 可分配数组的几种方法:新的 move_alloc 和分配分配。未显示显式释放,因为示例使用 move_alloc 并在过程退出时自动释放。 附言如果你想重复添加一个元素,你应该考虑你的数据结构方法。通过增长数组一次添加一个元素不是一种有效的方法。要在 Fortran 中将数组从 N 个元素增长到 N+1,可能意味着创建一个新数组并复制所有现有元素。更合适的数据结构可能是链表。您可以通过创建用户定义类型和使用指针在 Fortran 中创建链表。您将成员链接在一起,从一个指向下一个。添加另一个成员的开销很小。缺点是按顺序访问列表的成员最容易。你没有数组的简单能力,使用索引,以任何顺序访问成员。
我在网上找到的有关 Fortran 链表的信息:
http://www-uxsup.csx.cam.ac.uk/courses/Fortran/paper_12.pdf和 http://www.iag.uni -stuttgart.de/IAG/institut/abteilungen/numerik/images/4/4c/Pointer_Introduction.pdf
allocatable :: labelArray(:,:)
或
real,dimension(:,:),allocatable :: labelArray
双冒号的数量表示数组的等级(索引的数量)。
如果数组未分配你使用
allocate(labelarray(shapeyouwant))
具有正确数量的索引。例如
allocate(labelarray(2:3,-1:5))
对于维度 1 中索引为 2 到 3 和维度 2 中索引为 -1 到 5 的数组。
要更改维度,您必须先使用 释放数组
deallocate(labelArray)
要将分配的数组重新分配给新形状,您首先需要使用新形状分配一个新数组,将现有数组复制到新数组,然后使用
move_alloc()
将旧数组的引用移动到新数组。
call allocate(tmp(size_old+n_enlarge))
tmp(1:size_old) = array(1:size_old)
call move_alloc(tmp, array)
当新数组引用移动
move_alloc()
时,旧数组会自动释放。
Fortran 95 自动释放数组,如果它们超出范围(例如它们的子例程结束)。
Fortran 2008 有一个很好的自动分配分配功能。如果你说
array1=array2
并且 array1 没有分配,它会自动分配为具有正确的形状。
它也可以用于重新分配(另见Fortran array automatically growing when adding a value
和How to add new element to dynamic array in Fortran 90)
labelArray = [labelArray, new_element]
函数接收旧数组和所需大小,并返回指向新调整大小的数组的指针。
如果可能,请使用 Fortran 95 或 2003。如果 2003 是不可能的,那么 95 是一个很好的折衷方案。它提供了更好的指针语法。
allocate(tmp(size_old+n_enlarge))
tmp(1:size_old) = array(1:size_old) !copy the data
call move_alloc(tmp, array) !rename
注意
move_alloc
只涉及复制内部描述符(不是数组中的实际数据),因此指向的存储是相同的。
总而言之,move_alloc
提供了一种有效的方法来将数组重新分配到更大的大小,而无需复制数据两次(您只需复制一次数据)。也就是说,你需要抄入,但不需要抄出。