需要帮助以了解此功能

时间:2020-03-22 15:19:46

标签: fortran

我必须使用数组,但是一开始我不知道这些数组的大小,我只知道它是有限的。建议我使用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

我在做什么错了?

1 个答案:

答案 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$ 

再次使用真实代码,我会一次添加多行。

相关问题