我必须使用数组,但是一开始我不知道这些数组的大小,我只知道它是有限的。建议我使用this问题中描述的动态数组。我不确定如何使用它。我需要做的是这样的:
REAL,pointer,dimension(:,:)array
do i=1, max
array(i)=value
end do
当我使用以下代码时,在我的脑海中应该将2加到我的数组中
PROGRAM dynamic_array
IMPLICIT NONE
INTEGER,pointer,dimension(:)::vettore
integer i,val
allocate(vettore(1))
vettore(1)=1
do i=1,10
array(i)=append(i,vettore,2)
end do
do i=1, 20
write(*,*) array(i)
end do
deallocate(array)
Contains
(...)
end program
我得到以下输出:
1
2
-1216226408
4
0
6
0
8
48
10
81
0
1836017711
1634545509
1634301044
1919111983
1851881065
1160733033
1414808908
1229868882
我在做什么错了?
答案 0 :(得分:3)
在Fortran中,不要使用指针-可分配数组是执行此操作以及几乎所有动态内存管理的方法。可分配数组更易于使用和更安全,它们不可能有很多错误,而这些错误使指针很容易引入代码中。这样的错误之一就是内存泄漏-不可能有可分配数组的内存泄漏,因为一旦超出范围,它们就会自动释放。显式地取消分配数组并没有错,有时您可能想节省内存,甚至有人认为它是好的样式,但更多的情况不仅仅是击中(子)程序的末尾并依靠自动释放。足够。
另一方面,指针可能导致内存泄漏,这是可分配数组根本不会遭受的许多其他问题。指向数据的指针仅应在极少数情况下使用,如果仅学习语言,则可以忽略这些情况。实际上,如果您正在学习该语言,那么说不应该使用指针是非常接近事实的方法,可分配数组是您的最佳选择。
好,这表示您如何在现代Fortran中编写代码。好吧,这是一维案例的简单版本-可以提高效率,但这是应做的事情的基础
ian@eris:~/work/stack$ cat append.f90
Program append
Implicit None
Integer, Dimension( : ), Allocatable :: vettore
Integer :: i
! Allocate vettore to size zero
Allocate( vettore( 1:0 ) )
! Repeatedly append to the vector
! The alloctable array will automatically resize appropriately
Do i = 1, 20
vettore = [ vettore, 2 * i ]
End Do
! Print out the vector
Do i = 1, 20
Write( *, * ) i, vettore( i )
End Do
End Program append
ian@eris:~/work/stack$ gfortran-8 -fcheck=all -Wall -Wextra -pedantic -std=f2008 append.f90
ian@eris:~/work/stack$ ./a.out
1 2
2 4
3 6
4 8
5 10
6 12
7 14
8 16
9 18
10 20
11 22
12 24
13 26
14 28
15 30
16 32
17 34
18 36
19 38
20 40
ian@eris:~/work/stack$
实际上,生产代码中,我会通过将新数据存储在临时缓冲区中来避免某些副本和内存分配,并且一旦缓冲区已满,便一次性将所有数据追加到其中
多维情况比较困难,因为在Fortran数组构造函数中([]东西)只能是一维的。您可以使用RESHAPE内在函数来“巧妙”地解决此问题,但是我认为生成的代码不仅难看,而且非常令人困惑。因此,在这种情况下,我宁愿使用子程序。下面是一个简单的版本
ian@eris:~/work/stack$ cat append_2d.f90
Module append_module
Implicit None
Public :: append_2d
Private
Contains
Subroutine append_2d( existing, new )
Implicit None
Integer, Dimension( :, : ), Allocatable, Intent( InOut ) :: existing
Integer, Dimension( : ), Intent( In ) :: new
Integer, Dimension( :, : ), Allocatable :: tmp
Integer :: n1, n2
! Get size of the EXISTING data
n1 = Size( existing, Dim = 1 )
n2 = Size( existing, Dim = 2 )
! Allocate the temporary to the new size
Allocate( tmp( 1:n1, 1:n2 + 1 ) )
! Copy over the exisiting data
tmp( 1:n1, 1:n2 ) = existing
! Add the new data
tmp( :, n2 + 1 ) = new
! Move the allocation back
Call Move_alloc( tmp, existing )
End Subroutine append_2d
End Module append_module
Program test_append_2d
Use append_module, Only : append_2d
Implicit None
Integer, Dimension( :, : ), Allocatable :: vettore
Integer :: i
! Allocate vettore to size zero
Allocate( vettore( 1:2, 1:0 ) )
! Repeatedly append to the vector
Do i = 1, 20
Call append_2d( vettore, [ i, 2 * i ] )
End Do
! Print out the vector
Do i = 1, 20
Write( *, * ) i, vettore( :, i )
End Do
End Program test_append_2d
ian@eris:~/work/stack$ gfortran-8 -fcheck=all -Wall -Wextra -pedantic -std=f2008 append_2d.f90
ian@eris:~/work/stack$ ./a.out
1 1 2
2 2 4
3 3 6
4 4 8
5 5 10
6 6 12
7 7 14
8 8 16
9 9 18
10 10 20
11 11 22
12 12 24
13 13 26
14 14 28
15 15 30
16 16 32
17 17 34
18 18 36
19 19 38
20 20 40
ian@eris:~/work/stack$
再次使用真实代码,我会一次添加多行。