Fortran - Procedure

UN procedureè un gruppo di istruzioni che eseguono un'attività ben definita e possono essere richiamate dal programma. Le informazioni (o dati) vengono passate al programma chiamante, alla procedura come argomenti.

Esistono due tipi di procedure:

  • Functions
  • Subroutines

Funzione

Una funzione è una procedura che restituisce una singola quantità. Una funzione non dovrebbe modificare i suoi argomenti.

La quantità restituita è nota come function value, ed è indicato dal nome della funzione.

Syntax

La sintassi di una funzione è la seguente:

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

L'esempio seguente mostra una funzione denominata area_of_circle. Calcola l'area di un cerchio con raggio 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


! this function computes the area of a circle with radius r  
function area_of_circle (r)  

! function result     
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

Quando compili ed esegui il programma sopra, produce il seguente risultato:

The area of a circle with radius 2.0 is
   12.5663710

Si prega di notare che -

  • Devi specificare implicit none sia nel programma principale che nella procedura.

  • Viene chiamato l'argomento r nella funzione chiamata dummy argument.

L'opzione risultato

Se si desidera che il valore restituito venga memorizzato con un nome diverso dal nome della funzione, è possibile utilizzare l'estensione result opzione.

È possibile specificare il nome della variabile di ritorno come -

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

Sottoprogramma

Una subroutine non restituisce un valore, tuttavia può modificare i suoi argomenti.

Syntax

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

Chiamare una subroutine

È necessario richiamare una subroutine utilizzando il call dichiarazione.

L'esempio seguente mostra la definizione e l'uso di uno scambio di subroutine, che modifica i valori dei suoi argomenti.

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

Quando compili ed esegui il programma sopra, produce il seguente risultato:

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

Specificare l'intento degli argomenti

L'attributo intent consente di specificare l'intenzione con cui vengono utilizzati gli argomenti nella procedura. La tabella seguente fornisce i valori dell'attributo intent:

Valore Usato come Spiegazione
in intento (in) Utilizzato come valori di input, non modificato nella funzione
su intento (fuori) Utilizzati come valore di output, vengono sovrascritti
dentro fuori intent (inout) Gli argomenti vengono utilizzati e sovrascritti

Il seguente esempio dimostra il concetto:

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     

   ! dummy arguments      
   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

Quando compili ed esegui il programma sopra, produce il seguente risultato:

The value of the discriminant is
   17.0000000

Procedure ricorsive

La ricorsione si verifica quando un linguaggio di programmazione consente di chiamare una funzione all'interno della stessa funzione. Si chiama chiamata ricorsiva della funzione.

Quando una procedura chiama se stessa, direttamente o indirettamente, viene chiamata procedura ricorsiva. È necessario dichiarare questo tipo di procedure precedendo la parolarecursive prima della sua dichiarazione.

Quando una funzione viene utilizzata in modo ricorsivo, il result deve essere utilizzata l'opzione.

Di seguito è riportato un esempio, che calcola fattoriale per un dato numero utilizzando una procedura ricorsiva -

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

! computes the factorial of n (n!)      
recursive function myfactorial (n) result (fac)  
! function result     
implicit none     

   ! dummy arguments     
   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

Procedure interne

Quando una procedura è contenuta all'interno di un programma, viene chiamata procedura interna del programma. La sintassi per contenere una procedura interna è la seguente:

program program_name     
   implicit none         
   ! type declaration statements         
   ! executable statements    
   . . .     
   contains         
   ! internal procedures      
   . . .  
end program program_name

Il seguente esempio dimostra il concetto:

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

Quando compili ed esegui il programma sopra, produce il seguente risultato:

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