Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Fortran中将子例程名称作为参数传递?_Fortran_Subroutine - Fatal编程技术网

如何在Fortran中将子例程名称作为参数传递?

如何在Fortran中将子例程名称作为参数传递?,fortran,subroutine,Fortran,Subroutine,作为参数传递子例程名称的语法是什么?示意图: . . call action ( mySubX ( argA, argB ) ) . . subroutine action ( whichSub ( argA, argB ) ) ... call subroutine whichSub ( argA, argB ) ... end subroutine action 目标是使调用子例程sub argA,argB充当调用子例程mySubX argA,argB。 我的首选

作为参数传递子例程名称的语法是什么?示意图:

  .
  .
call action ( mySubX ( argA, argB ) )
  .
  .

subroutine action ( whichSub ( argA, argB ) )
  ...
call subroutine whichSub ( argA, argB )
  ...
end subroutine action
目标是使调用子例程sub argA,argB充当调用子例程mySubX argA,argB。 我的首选是避免传递开关参数,然后使用SELECT CASE。

确实如此

call action(mySubX)
如果操作看起来像

subroutine action(sub)
  !either - not recommmended, it is old FORTRAN77 style
  external sub
  !or - recommended
  interface
    subroutine sub(aA, aB)
      integer,intent(...) :: aA, aB
    end subroutine
  end interface
  ! NOT BOTH!!

  call sub(argA, argB)
假设动作知道将什么放在那里作为argA,argB来代表aA,aB

否则,如果要同时传递参数

call action(mySubX, argA, argB)

subroutine action(sub, argA, argB)
  !either - not recommmended, it is old FORTRAN77 style
  external sub
  !or - recommended
  interface
    subroutine sub(aA, aB)
      integer,intent(...) :: aA, aB
    end subroutine
  end interface

  integer, intent(...) :: argA, argB

  call sub(argA, argB)
我不认为在这里使用函数指针是好的,当你不得不改变它指向的子例程的指针值时,它们是好的。正常过程参数在FORTRAN77中有效,即使到现在仍然有效

因此,根据注释中的要求,如果您在一个模块中,并且可以从该模块(可能在同一个模块中)访问具有正确接口的过程,则可以使用procedure语句获取接口块的rod:

module subs_mod
contains
  subroutine example_sub(aA, aB)
    integer,intent(...) :: aA, aB
    !the real example code
  end subroutine
end module

module action_mod
contains

  subroutine action(sub)
    use subs_mod
    procedure(example_sub) :: sub

    call sub(argA, argB)
  end subroutine
end module
但更可能的是,您将创建一个抽象接口,而不是一个真正的子例程,您将使用过程语句引用该接口,因此最终所有内容都将与以前类似:

module action_mod

  abstract interface
    subroutine sub_interface(aA, aB)
      integer,intent(...) :: aA, aB
    end subroutine
  end interface

contains

  subroutine action(sub)
    procedure(sub_interface) :: sub

    call sub(argA, argB)
  end subroutine
end module

我认为使用模块来避免接口是一个很好的现代Fortran实践,因为它提供了一个更干净的接口

以下是实现以下目标的理想方法:

模块部分:

module foo
contains

subroutine callsub(sub,arg1,arg2)
!This subroutine is used to call other subroutines
external::sub !Use external to tell compiler this is indeed a subroutine
call sub(arg1,arg2)
end subroutine

subroutine sub(arg1,arg2)
!The subroutine to be called.
!do something
end sub

end module
下面是主要程序:

program main
use foo !Use module automatically avoids using interface.
implicit none
!Declare about args
call callsub(sub,arg1,arg2)
end program

下面将详细说明如何实现这一点。

哪种风格和版本的Fortran?很好的解释。感谢您提供有关语言和函数指针现代用法的提示。我们可以使用模块来消除接口吗?如果可以从某个模块访问某个兼容的过程,您可以使用proceduremySubX::sub。您也可以在模块中为其创建一个抽象接口,并使用相同的procedurenameOfTheInterface。也许我错了,但我的印象是,只有调用方(使用过程参数调用的函数)才需要external关键字,而不是被调用方。否则,根据12.4.2 Fortran 2008,它有一个隐式接口。在5.3.92中:如果外部过程或伪过程用作实际参数或是过程指针赋值的目标,则应声明其具有外部属性。只有在特殊情况下被调用方才必须使用F90+功能。但是,我同意在这种情况下使用抽象接口和模块更好。虽然这在理论上可以回答这个问题,但它会在这里,并提供链接供参考。谢谢纠正我。我是这里的新手,我还在学习礼仪。我添加了更多与问题相关的内容。做得好,这是一个更好的答案,欢迎来到Stackoverflow!这个设计确实消除了对接口块的需要,但是子例程传递的要点是你可以传递任何子例程。现在您在主程序中有了指向sub的显式接口,但在callsub中没有。在现代Fortran中使用proceduresub而不是外部程序会更好。然后你可以在模块中有一个抽象接口,而不是整个子模块。然后你意识到你又在一个接口块上。。。