Fortran - 过程

过程是一组执行明确定义的任务并且可以从程序中调用的语句。 信息(或数据)被传递给调用程序,作为参数传递给过程。

有两种类型的程序 −

  • 函数
  • 子例程

函数

函数是返回单个数量的过程。 函数不应修改其参数。

返回的数量称为函数值,由函数名称表示。

语法

函数的语法如下 −

function name(arg1, arg2, ....)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

以下示例演示了一个名为area_of_circle 的函数。 它计算半径为 r 的圆的面积。

program calling_func

   real :: a
   a = area_of_circle(2.0) 
   
   Print *, "The area of a circle with radius 2.0 is"
   Print *, a
   
end program calling_func


! 该函数计算半径为 r 的圆的面积  
function area_of_circle (r)  

! 函数结果
implicit none      

   ! dummy arguments        
   real :: area_of_circle   
   
   ! local variables 
   real :: r     
   real :: pi
   
   pi = 4 * atan (1.0)     
   area_of_circle = pi * r**2  
   
end function area_of_circle

当你编译并执行上面的程序时,它会产生以下结果 −

The area of a circle with radius 2.0 is
   12.5663710   

请注意 −

  • 您必须在主程序和过程中指定implicit none

  • 被调用函数中的参数 r 称为虚拟参数

result 选项

如果您希望返回值以函数名称以外的其他名称存储,可以使用result选项。

您可以将返回变量名称指定为 −

function name(arg1, arg2, ....) result (return_var_name)  
   [declarations, including those for the arguments]   
   [executable statements] 
end function [name]

子程序

子例程不返回值,但可以修改其参数。

语法

subroutine name(arg1, arg2, ....)    
   [declarations, including those for the arguments]    
   [executable statements]  
end subroutine [name]

调用子程序

您需要使用call语句调用子例程。

以下示例演示了子例程交换的定义和使用,该子例程交换更改了其参数的值。

program calling_func
implicit none

   real :: a, b
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
end program calling_func


subroutine swap(x, y) 
implicit none

   real :: x, y, temp   
   
   temp = x  
   x = y 
   y = temp  
   
end subroutine swap

当你编译并执行上面的程序时,它会产生以下结果 −

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000   

指定参数的意图

intent 属性允许您指定在过程中使用参数的意图。 下表提供了意图属性的值 −

用作 说明
in intent(in) 用作输入值,在函数中不改变
out intent(out) 用作输出值,它们被覆盖
inout intent(inout) 参数被使用和覆盖

以下示例演示了这个概念 −

program calling_func
implicit none

   real :: x, y, z, disc
   
   x = 1.0
   y = 5.0
   z = 2.0
   
   call intent_example(x, y, z, disc)
   
   Print *, "The value of the discriminant is"
   Print *, disc
   
end program calling_func


subroutine intent_example (a, b, c, d)     
implicit none     

   ! 虚拟参数
   real, intent (in) :: a     
   real, intent (in) :: b      
   real, intent (in) :: c    
   real, intent (out) :: d   
   
   d = b * b - 4.0 * a * c 
   
end subroutine intent_example

当你编译并执行上面的程序时,它会产生以下结果 −

The value of the discriminant is
   17.0000000    

递归过程

当编程语言允许您在同一函数内调用函数时,就会发生递归。 这称为函数的递归调用。

当过程直接或间接调用自身时,称为递归过程。 您应该在声明之前添加recursive 一词来声明此类过程。

当递归使用函数时,必须使用result选项。

下面是一个示例,它使用递归过程计算给定数字的阶乘 −

program calling_func
implicit none

   integer :: i, f
   i = 15
   
   Print *, "The value of factorial 15 is"
   f = myfactorial(15)
   Print *, f
   
end program calling_func

! 计算 n (n!) 的阶乘
recursive function myfactorial (n) result (fac)  
! 函数结果
implicit none     

   ! 虚拟参数
   integer :: fac     
   integer, intent (in) :: n     
   
   select case (n)         
      case (0:1)         
         fac = 1         
      case default    
         fac = n * myfactorial (n-1)  
   end select 
   
end function myfactorial

内部过程

当一个过程包含在一个程序中时,它被称为该程序的内部过程。 包含内部过程的语法如下 −

program program_name     
   implicit none         
   ! 类型声明语句
   ! 可执行语句
   . . .     
   contains         
   ! 内部过程
   . . .  
end program program_name

以下示例演示了这个概念 −

program mainprog  
implicit none 

   real :: a, b 
   a = 2.0
   b = 3.0
   
   Print *, "Before calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
   
   call swap(a, b)
   
   Print *, "After calling swap"
   Print *, "a = ", a
   Print *, "b = ", b
 
contains   
   subroutine swap(x, y)     
      real :: x, y, temp      
      temp = x 
      x = y  
      y = temp   
   end subroutine swap 
   
end program mainprog   

当你编译并执行上面的程序时,它会产生以下结果 −

Before calling swap
a = 2.00000000    
b = 3.00000000    
After calling swap
a = 3.00000000    
b = 2.00000000