1
Il linguaggio Fortran 90: 3. Procedure e Funzioni
Stefano Leonardi
Dipartimento di Informatica e Sistemistica
2
Procedure
• Il problema da risolvere viene spesso decomposto in tante parti logiche di facile soluzione.
• E’ possibile realizzare le funzionalità di base attraverso unità di programma indipendenti dette procedure
• Le unità di programma possono essere compilate e testate separatamente.
• Le unità di programma possono essere utilizzate in più programmi che necessitano tale funzionalità.
3
Procedure (cont.)
• E’ possibile isolare la comunicazione delle procedure con il programma principale ad un insieme di parametri definiti nell’intestazione.
• Nelle Subroutine i dati di input e di output sono comunicati attraverso i parametri.
• Nelle Funzioni solo i dati di input sono comunicati attraverso i parametri mentre il risultato è indicato dal nome della funzione.
4
Subroutines
• Specifica di una subroutineSUBROUTINE nome_subroutine (lista_argomenti)
sezione dichiarativasezione esecutiva
RETURN END SUBROUTINE [nome_subroutine]
• Invocazione di una subroutine nel proramma principale
CALL nome_subroutine (lista_argomenti)
5
Subroutines (cont.)• I parametri di lista_argomenti nella
dichiarazione sono detti parametri formali (o fittizi)• I parametri di lista_argomenti nella chiamata
sono detti paramentri attuali (o effettivi)• I parametri attuali devono corrispondere ai parametri
formali (o fittizi).• Il controllo torna all’istruzione che segue la CALL
dopo l’istruzione RETURN• Le variabile usate all’interno della Subroutine sono
dette variabili locali
6
Calcolo IpotenusaSUBROUTINE calc_ipotenusa(lato_1, lato_2, ipotenusa)! scopo: calcolare l’ipotenusa di un triangolo rettangolo date le! lunghezza dei due cateti
IMPLICIT NONEREAL, INTENT(IN) :: lato_1 !lunghezza primo catetoREAL, INTENT(IN) :: lato_2 !lunghezza secondo catetoREAL, INTENT(OUT) :: ipotenusa !lunghezza ipotenusa
!Dichiara le variabili localiREAL :: temp
!Calcolo ipotenusatemp = lato_1**2 + lato_2**2ipotenusa = SQRT(temp)RETURN
END SUBROUTINE calc_ipotenusa
7
Calcolo Ipotenusa (cont.)! File prova_ipotenusa.for
Program prova_ipotenusa!Scopo: Programma per provare la Subroutine calc_ipotenusa
IMPLICIT NONEREAL :: c1 !Lunghezza primo catetoREAL :: c2 !Lunghezza secondo catetoREAL :: ipot !Lunghezza ipotenusa
WRITE (*,*) 'Inserisci la lunghezza del primo cateto: 'READ (*,*) c1WRITE (*,*) 'Inserisci la lunghezza del secondo cateto: 'READ (*,*) c2CALL calc_ipotenusa (c1, c2, ipot)WRITE(*,*) 'La lunghezza dell''ipotenusa e'':', ipotSTOP
END PROGRAM prova_ipotenusa
8
Commenti:– I nomi dei parametri attuali non sono necessariamente uguali
ai nomi dei parametri formali– I tipi dei parametri formali devono corrispondere uno ad uno
ai tipi dei parametri attuali– INTENT (IN): Il parametro formale è usato solo per passare i
dati di input alla Subroutine– INTENT (OUT): Il parametro formale è usato solo per
passare i dati di output alla Subroutine – INTENT (IN OUT): Il parametro formale è usato per
passare i dati di input e output alla SubroutineUSARE CON CAUTELA!!
9
Condivisione di Procedure
• Le procedure sono contenute in un modulo che verrà indicato nelle unità di programma che le utilizzano
• Il modulo ed il programma sono compilati separatamenteMODULE mie_subCONTAINS
SUBROUTINE sub1 (a,b,c)………END SUBROUTINE sub1SUBROUTINE sub2 (a,b,c)………END SUBROUTINE sub2
END MODULE mie_sub
10
Condivisione di Procedure (cont.)
PROGRAM prog_main
USE mie_sub
IMPLICITE NONE
CALL sub1 (x,y,z)
END PROGRAM prog_main
11
Stampa di Figure
! File: figure3.for ! Scopo: Definizione ed uso di SUBROUTINE:! - con argomenti (1) ! - con costanti e variabili locali
MODULE modulo_stampe_3 ! Questo modulo contiene la definizione di procedure per la stampa! di figure e messaggi
CONTAINS
SUBROUTINE stampa_triangolo(dim) ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE ! DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, INTENT(IN) :: dim ! lunghezza del lato !DICHIARAZIONE COSTANTI E VARIABILI LOCALI INTEGER, PARAMETER :: max_lung = 25 INTEGER :: i ! indice del ciclo CHARACTER(max_lung) :: linea ! linea da stampare
12
Stampa di Figure (cont.)
! *** SEZIONE ESECUTIVA *** ! DO i = 1, max_lung linea(i:i) = ' ' END DO DO i = 1, dim linea(i:i) = '*' WRITE (*,*) linea END DO RETURN
END SUBROUTINE stampa_triangolo
13
Stampa di Figure (cont.)SUBROUTINE stampa_quadrato(dim) IMPLICIT NONE ! DICHIARAZIONE ARGOMENTI FITTIZI INTEGER, INTENT(IN) :: dim ! lunghezza del lato ! DICHIARAZIONE COSTANTI E VARIABILI LOCALI INTEGER, PARAMETER :: max_lung = 25 INTEGER :: i ! indice del ciclo CHARACTER(max_lung) :: linea ! linea da stampare
DO i = 1, max_lung linea(i:i) = ' ' END DO DO i = 1, dim linea(i:i) = '*' END DO DO i = 1, dim WRITE (*,*) linea END DO RETURN END SUBROUTINE stampa_quadrato
END MODULE modulo_stampe_3
14
Stampa di Figure (cont.)PROGRAM stampa_figure_3 !E' possibile scegliere la forma e la dimensione
! *** SEZIONE DICHIARATIVA *** !USE modulo_stampe_3 IMPLICIT NONE CHARACTER(1) :: ch ! serve per il dialogo con l'utente INTEGER :: dimensione ! serve per l'acquisizione della dimensione
! *** SEZIONE ESECUTIVA *** !DO WRITE (*,*) '*** IMMETTI UN CARATTERE A SCELTA FRA I SEGUENTI ***' WRITE (*,*) '***** T: stampa un triangolo' WRITE (*,*) '***** Q: stampa un quadrato' WRITE (*,*) '***** F: per terminare il programma' WRITE (*,*) READ (*,*) ch IF (ch == 'q' .OR. ch == 'Q' .OR. ch == 't' .OR. ch == 'T') THEN WRITE (*,*) 'Di che dimensione? ' READ (*,*) dimensione END IF
15
Stampa di Figure (cont.)
SELECT CASE (ch) CASE ('T','t') CALL stampa_triangolo(dimensione) CASE ('Q','q') CALL stampa_quadrato(dimensione) END SELECT IF (ch == 'f' .OR. ch == 'F') EXIT END DOSTOP
END PROGRAM stampa_figure_3
16
Funzioni• Procedure che svolgono delle funzioni particolari non presenti
tra le funzioni intrinseche (SIN(x), INT(x), etc…)• I parametri indicano i valori di input su cui calcolare le funzioni.• Occorre dichiarare nella funzione una variabile con stesso nome
della funzione che definisce il tipo del risultato.• Il risultato della funzione è assegnato al nome della variabile • La funzione è utilizzabile in espressioni delle stesso tipo.• E’ preferibile non modificare all’interno di una funzione i
parametri di input che vengono tutti definiti come INTENT (IN)
• Modifiche ai parametri di input sono detti effetti collaterali (side effects)
17
Funzioni (cont.)
FUNCTION nome (lista argomenti)
sezione dichiarativa
tipo :: nome
sezione esecutiva
nome = espressione
RETURN
END FUNCTION nome
18
Calcolo di un polinomio! File: test_quadf.for ! Scopo: Definizione ed uso di FUNCTION
MODULE modulo_quadf ! Questo modulo contiene la function quadf()
CONTAINS
FUNCTION quadf (x,a,b,c)!calcola un polinomio del tipo f(x)= a*x**2+b*x+c
IMPLICIT NONE !Dichiara gli argomenti REAL :: quadf REAL, INTENT(IN) :: x ! Valore della variabile REAL, INTENT(IN) :: a, b, c ! Coefficienti del polinomio
quadf = a*x**2+b*x+c RETURN
END FUNCTION quadf
END MODULE modulo_quadf
19
Calcolo di un polinomio(cont.)PROGRAM test_quadf!Scopo: provare la funzione quadf
! *** SEZIONE DICHIARATIVA *** !USE modulo_quadfIMPLICIT NONEREAL :: a, b, c, x!Dati di input
! *** SEZIONE ESECUTIVA *** !WRITE(*,*) 'Inserisci i coefficienti a, b, c: 'READ(*,*) a, b, cWRITE(*,*) 'Valore in cui valutare il polinomio: 'READ(*,*) xWRITE(*,*) 'quadf(', x, ') =', quadf(x,a,b,c)STOP
END PROGRAM test_quadf
20
Condivisione di dati
• I moduli permettono anche la condivisione di dati tra diverse unità di programma.
• I dati sono accessibili a tutte le unità di programma che usano un determinato modulo ed alle procedure definite nello stesso modulo.
• All’interno di un modulo si possono includere sia dati che procedure che operano sui dati.
• E’ possibile imporre con l’istruzione SAVE che i valori dei dati non siano modificati tra l’esecuzione di due procedure.
21
Modulo Contatore! File: counter.for
MODULE counter_mod ! Questo modulo realizza un MODULO per un contatore intero
IMPLICIT NONE INTEGER :: cont! Variabile condivisa
CONTAINS
SUBROUTINE init() IMPLICIT NONE cont = 0 RETURN END SUBROUTINE init
22
Modulo Contatore (cont.)SUBROUTINE incrementa() IMPLICIT NONE cont = cont + 1 RETURN END SUBROUTINE incrementa
FUNCTION valore() IMPLICIT NONE INTEGER :: valore valore = cont RETURN END FUNCTION valore
END MODULE counter_mod
!================================================================
PROGRAM counter
USE counter_mod IMPLICIT NONE CHARACTER(1) :: ch
23
Modulo Contatore (cont.)DO WRITE (*,*) '*** IMMETTI UN CARATTERE A SCELTA FRA I SEGUENTI ***' WRITE (*,*) '***** A: azzera il contatore' WRITE (*,*) '***** I: incrementa il contatore' WRITE (*,*) '***** V: visualizza il contatore' WRITE (*,*) '***** F: per terminare il programma ' READ (*,*) ch SELECT CASE (ch) CASE ('A','a') CALL init() CASE ('I','i') CALL incrementa() CASE ('V','v') WRITE(*,*) valore() END SELECT IF (ch == 'f' .OR. ch == 'F') EXIT END DO STOP END PROGRAM counter
24
Avvertenze per Elf 90• Subroutine e funzioni devono essere necessariamente
definite all'interno di un MODULE • Una dichiarazione del tipo INTEGER FUNCTION nome_funzione (x)
non viene compilata, e va sostituita con FUNCTION nome_funzione(x) INTEGER :: nome_funzione
• Il tipo di una funzione non deve essere ridichiarata nell'unità di programma che la usa.
• La clausola INTENT è obbligatoria per tutti gli argomenti passati ad un'unità di programma.
25
Compilazione di Procedure e Funzioni
• Compilare semparatamente i file contenenti i Module e il file contenente il Programma principale, es: main.for
• Collegare i file oggetto con l’istruzione: > elf90 main.obj
• Eseguire il programma digitando:> main
Top Related