我写了一个简单的演示代码,以快速的方式呈现我的问题。这是代码,无法成功构建。
main.f90时
PROGRAM test
IMPLICIT NONE
INTEGER :: a
a = 1
CALL sub(a)
END PROGRAM
sub.f90
SUBROUTINE sub(a)
IMPLICIT NONE
INTEGER :: a
SELECT CASE(a)
CASE(1)
INTEGER :: b,c
b = a
c = a*2
CASE(2)
INTEGER :: b(4),c(4)
b(:) = a
c(:) = a*2
END SELECT
END SUBROUTINE
我尝试编译,但错误显示子例程文件中出现“意外的数据声明语句”。这是否意味着我无法在SELECT CASE结构中声明参数类型?问题是我想在主程序中定义a的值并将其传递给子程序sub(a)。 b和c的参数类型应由a决定,因此我无法事先确定。我还想将b和c的值传递回主程序,我不知道该怎么做。那我该怎么做呢?谢谢。
答案 0 :(得分:3)
因此,您实际上是在询问如何从某个子例程返回标量或数组,而不是如何声明构造局部变量。在这种情况下,请考虑使用两个单独的子例程。一个版本用于标量,一个用于数组。如果需要,可以在一个名称下将它们作为通用过程重载。
还要考虑ELEMENTAL
,但如果使用标量a
,它将不适用于数组。
如果您仍想知道如何声明局部变量:
变量只能在过程的开头或块的开头声明。这是最新版本的最常见编译器支持的Fortran 2008功能(来自至少GNU和Intel的PC编译器)。
SELECT CASE(a)
CASE(1)
BLOCK
INTEGER :: b,c
b = a
c = a*2
END BLOCK
答案 1 :(得分:2)
您发现的代码是非法的,正如您所发现的那样。现在有些人已经指出了BLOCK
陈述的2008特征,如果这是你需要的,你可以试试。但是我想了解更多关于你想要做什么的事情。
你给他们同名的这个事实告诉我你以后想以同样的方式对待他们,这让事情变得非常棘手。
以下是一些替代方案:
1)使用单独的变量:
INTEGER :: b_scalar, c_scalar, b_array(4), c_array(4)
select case(a)
case(1)
b_scalar = a
c_scalar = 2*b_scalar
case(2)
b_array = a
c_array = 2*b_array
end select
2)使用可分配的数组:
integer, dimension(:), allocatable :: b, c
select case(a)
case(1)
allocate(b(1), c(1))
case(2)
allocate(b(4), c(4))
end select
b = a
c = 2 * b
现在你必须记住b
和c
是数组,可能是长度为1.你必须这样对待它们。
所有这些都有优点和缺点。不知道你为什么要做你正在做的事情,我真的不知道如何最好地为你提供建议。
关于你的第二个问题:返回它们的简单方法是INTENT(OUT)
伪参数。这是一个有效的例子:
module mod_allocatable
contains
subroutine my_sub(a, b, c)
implicit none
integer, intent(in) :: a
integer, dimension(:), allocatable, intent(out) :: b, c
if (allocated(b)) deallocate(b)
if (allocated(c)) deallocate(c)
select case(a)
case(1)
allocate(b(1), c(1))
case(2)
allocate(b(4), c(4))
end select
b = a
c = 2 * b
end subroutine my_sub
end module mod_allocatable
program test_alloc
use mod_allocatable
implicit none
integer :: a
integer, allocatable, dimension(:) :: b, c
a = 1
call my_sub(a, b, c)
print *, "b is ", b
print *, "c is ", c
end program test_alloc
答案 2 :(得分:0)
这不是太优雅......
SUBROUTINE sub(a)
IMPLICIT NONE
INTEGER, INTENT(IN) :: a
INTEGER, DIMENSION(:), ALLOCATABLE :: b, c
SELECT CASE(a)
CASE(1)
IF(ALLOCATED(B)) THEN
IF(UBOUND(B)) .NE. 1) THEN
DEALLOCATE(B)
ALLOCATE(B(1))
ENDIF
ELSE
ALLOCATE(B(1))
ENDIF
IF(ALLOCATED(C)) THEN
IF(UBOUND(C)) .NE. 1) THEN
DEALLOCATE(c)
ALLOCATE(C(1))
ENDIF
ELSE
ALLOCATE(C(1))
ENDIF
b = a
c = a*2
CASE(2)
IF(ALLOCATED(B)) THEN
IF(UBOUND(B)) .NE. 4) THEN
DEALLOCATE(B)
ALLOCATE(B(4))
ENDIF
ELSE
ALLOCATE(B(4))
ENDIF
IF(ALLOCATED(C)) THEN
IF(UBOUND(C)) .NE. 4) THEN
DEALLOCATE(C)
ALLOCATE(C(4))
ENDIF
ELSE
ALLOCATE(C(4))
ENDIF
b(:) = a
c(:) = a*2
CASE(DEFAULT)
WRITE(*,*)'how did we get here?... a=',a
END SELECT
END SUBROUTINE Sub