回 帖 发 新 帖 刷新版面

主题:向各位大侠求助关于subroutine使用动态数组的问题

就是我想将一个可变大小数组传递到subroutine中去,数组的大小只能在这个subroutine里才能确定,不知道我该怎么做呢?
我写的代码如下:
program main
implicit none
integer(kind=4), dimension(:), allocatable:: a
call test(a)
stop
end

subroutine test(b)
implicit none
integer(kind=4), dimension(:),allocatable::b
integer(kind=4):: i, n=5
allocate(b(n))
open(1,file='input.txt')
do i=1,5
   read(1,*) b(i)
end do
close(1)
write(*,*) b
return
end subroutine test

出现的错误是:
Error: A dummy argument name is invalid in this context.   [B]
integer(kind=4), allocatable::b(:)
------------------------------^
Error executing df.exe.

请各位大侠给予指导和帮助,万分感谢!![em59][em59]~~

回复列表 (共8个回复)

沙发

按新标准f2003里面是可以这样做的, 个人由于还经常用cvf, 所以一直没有试用过这种用法.

板凳


那请问您,在cvf中该怎么做才能实现传递这中可变大小的数组呀?

多谢多谢![em4]

3 楼

把子程序中b的allocatable属性去掉
在主程序中增加test的interface

4 楼

我按照您说的试了试,改成如下:
program main
implicit none
integer(kind=4), dimension(:), allocatable:: a
interface 
subroutine test(a) 
implicit none 
integer(kind=4), dimension(:), allocatable:: a
end subroutine test
end interface

call test(a)
stop
end

subroutine test(b)
implicit none
integer(kind=4)::b(:)
integer(kind=4):: i, n=5
allocate(b(n))
open(1,file='input.txt')
do i=1,5
   read(1,*) b(i)
end do
close(1)
write(*,*) b
return
end subroutine test

但是还是出错了,错误如下:
Compiling Fortran...
C:\Program Files\Microsoft Visual Studio\COMMON\MSDEV98\My Projects\temp\testfunc.f90
C:\Program Files\Microsoft Visual Studio\COMMON\MSDEV98\My Projects\temp\testfunc.f90(8) : Error: A dummy argument name is invalid in this context.   [A]
integer(kind=4), dimension(:), allocatable:: a
---------------------------------------------^
C:\Program Files\Microsoft Visual Studio\COMMON\MSDEV98\My Projects\temp\test.f90
C:\Program Files\Microsoft Visual Studio\COMMON\MSDEV98\My Projects\temp\test.f90(9) : Error: An allocate/deallocate object must have the ALLOCATABLE or POINTER attribute.   [B]
allocate(b(n))
---------^

不知道是哪里出了问题呢?因为我是希望数组a的大小在子程序中确定。

非常感谢大侠们的指点!

5 楼

按照fortran90/95标准以及97年的一个TR (技术报告?),可分配数组可以作为参数传递,但是必须是在allocate了之后。也就是说必须是这样:
real, allocatable :: a(:)
allocate(a(10))
call sub(a)
不能够传递未经分配的可分配数组,让它在子程序中进行分配,这是不允许的。

但是这明显不能满足楼主的要求。F90对此也有办法,就是使用指针,指针的分配/回收是可以跨越程序单元的。我提供一个例子。
module ptrmod
contains
subroutine length(x, i)
   implicit none
   real, pointer :: x(:)
   integer :: i
   allocate(x(i))
   x=i
end subroutine
end module

program main
  use ptrmod
  implicit none
  real, pointer :: x(:)=>null()
  integer :: i
  do i=1, 5
     call length(x, i)
     print *, size(x), x
     if(associated(x)) deallocate(x)
  enddo
end program

值得注意的是,此类调用一定要显式接口,否则肯定要有内存读写错误。
要么在主程序中为子程序写接口块,要么把子程序包到某个模块里,模块里的过程都是显式接口的。

6 楼


非常感谢!谢谢以上各位的指点![em4]

7 楼

The following example show how to use allocatable dummy argument in Fortran 2003 Standard.

program main
  implicit none
  integer, allocatable:: a(:)
  integer:: i_stat
  character(len = 50):: Err_Msg
interface 
  subroutine test(a)  
    integer, intent(inout), allocatable:: a(:)
  end subroutine test
end interface

  call test(a)
  deallocate(a, stat = i_stat, ErrMsg = Err_Msg)
  write(*, *) "stat = ", i_stat
  ! what happen?
  deallocate(a, stat = i_stat, ErrMsg = Err_Msg)
  write(*, *) "stat = ", i_stat 
  deallocate(a)
  write(*, *) "stat = ", i_stat 
  stop
end program main

subroutine test(b)
  implicit none
  integer, intent(inout), allocatable:: b(:)
  integer:: i, n = 5
  allocate( b(n) )
  forall ( i = 1 : n : 1 )
    b(i) = i
  end forall
  write(*, *) b
  
  return
end subroutine test

8 楼

我习惯的做法是在module里定义这个可变数组,注意加上save属性。
当然,以上几楼的办法也令我受教了。

module vararray
implicit none
integer,dimension(:),allocatable,save::a
end module vararray

program test
use vararray
implicit none
call sub()
pause
end program test

subroutine sub()
use vararray
implicit none
integer::n
n=10 ! any code to generate the length of the variable array
allocate(a(n))
a=1 ! any code to set array a
end subroutine sub

我来回复

您尚未登录,请登录后再回复。点此登录或注册