fortran - 需要帮助来理解这个功能
问题描述
我必须使用数组,但一开始我不知道这些数组的大小,我只知道它是有限的。有人建议我使用这个问题中描述的动态数组。我不确定如何使用它。我需要做的是这样的:
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
我究竟做错了什么?
解决方案
在 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$
再次在实际代码中,我将一次附加多行。
推荐阅读
- oozie - 如何在 oozie Web 控制台中按工作流 ID 和名称进行过滤?
- oauth - Dynamics CRM Oauth 令牌快速过期
- python - Pycharm检测python橡胶而不是python测试模板
- swift - iPhone7(12.4.0) 中字符 0 周围的值无效
- aws-lambda - Alexa 技能不执行意图
- vue.js - 将日期对象作为道具传递的默认值是什么?
- wordpress - 无法在 IIS 服务器上的 WordPress 媒体中上传大于 20MB 的文件
- python - 如何获取网页的所有链接,无论是使用python直接还是间接链接到网页?
- node.js - 在 Express.JS 中验证失败时如何返回参数值
- python - aws ssm create_activation api 因正则表达式错误而失败