主题:向各位大侠求助关于subroutine使用动态数组的问题
nnm308
[专家分:0] 发布于 2010-08-20 09:57:00
就是我想将一个可变大小数组传递到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]~~
最后更新于:2010-08-20 10:16:00
回复列表 (共8个回复)
沙发
yeg001 [专家分:14390] 发布于 2010-08-20 10:14:00
按新标准f2003里面是可以这样做的, 个人由于还经常用cvf, 所以一直没有试用过这种用法.
板凳
nnm308 [专家分:0] 发布于 2010-08-20 10:18:00
那请问您,在cvf中该怎么做才能实现传递这中可变大小的数组呀?
多谢多谢![em4]
3 楼
adda [专家分:1520] 发布于 2010-08-20 11:33:00
把子程序中b的allocatable属性去掉
在主程序中增加test的interface
4 楼
nnm308 [专家分:0] 发布于 2010-08-20 14:17:00
我按照您说的试了试,改成如下:
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 楼
f2003 [专家分:7960] 发布于 2010-08-20 15:17:00
按照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 楼
nnm308 [专家分:0] 发布于 2010-08-20 15:55:00
非常感谢!谢谢以上各位的指点![em4]
7 楼
asymptotic [专家分:16630] 发布于 2010-08-20 21:55:00
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 楼
BiCGSTAB [专家分:780] 发布于 2010-08-21 08:10:00
我习惯的做法是在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
我来回复