1 Il linguaggio Fortran 90: 3. Procedure e Funzioni Stefano Leonardi Dipartimento di Informatica e...

Preview:

Citation preview

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