fortran

Transcript

fortran
UNINA2 – INGEGNERIA MECCANICA/AEROSPAZIALE
ELEMENTI DI PROGRAMMAZIONE
FORTRAN:
LE STRUTTURE DI CONTROLLO
Prof. Andrea Prevete - a.a. 2015/16
IF-THEN
La più semplice struttura di
controllo è lo statement IFTHEN.
Un’espressione logica è
valutata per consentire, se
.TRUE., l’esecuzione di un
definito blocco di istruzioni.
LEXPR
?
THEN (TRUE!)
BLOCK
IF-THEN
Ecco la sintassi Fortran:
IF (lexpr) THEN
block
END IF
Oppure, se block è una singola istruzione, in formato single-line:
IF (lexpr) istr
Segue un segmento di programma che, letti due interi x ed y, immagazzina in una terza
variabile il valore maggiore:
INTEGER :: x, y, m
READ(*,*) x, y
m=x
IF (y>m) THEN
m=y
END IF
WRITE(*,*) m
IF-THEN-ELSE
ELSE (FALSE!)
BLOCK2
LEXPR
?
THEN (TRUE!)
BLOCK1
Un’ immediata estensione della struttura di controllo IFTHEN è la IF-THEN-ELSE.
Il valore di verità dell’espressione valutata seleziona, per
l’esecuzione, uno fra due, alternativi, blocchi di istruzioni.
IF-THEN-ELSE
Ecco il codice Fortran:
IF (lexpr) THEN
block1
ELSE
block2
END IF
Segue la versione IF-THEN-ELSE del precedente segmento di programma:
INTEGER :: x, y, m
READ(*,*) x, y
IF (x > y) THEN
m=x
ELSE
m=y
END IF
WRITE(*,*) m
ELSE-IF
La forma più generale di costrutto IF disponibile in Fortran è la seguente:
IF (lexpr1) THEN
block-i
ELSE IF (lexpr2) THEN
block-1
……
ELSE IF (lexprn) THEN
block-n
ELSE
block-e
END IF
Utilizzando questa forma di controllo si ha la possibilità di selezionare uno fra più
blocchi di istruzioni da eseguire utilizzando una catena di espressioni logiche che
restringono via via la scelta.
ELSE-IF
CHARACTER(10) :: Today, Oggi
READ(*,*) Today
IF (Today == “Monday”) THEN
Oggi=“Lunedi”
ELSEIF (Today == “Tuesday”) THEN
Oggi=“Martedi”
ELSEIF (Today == “Wednesday”) THEN
Oggi=“Mercoledi”
ELSEIF (Today == “Thursday”) THEN
Oggi=“Giovedi”
ELSEIF (Today == “Friday”) THEN
Oggi=“Venedi”
ELSEIF (Today == “Saturday”) THEN
Oggi=“Sabato”
ELSEIF (Today == “Sunday”) THEN
Oggi=“Domenica”
ELSE
Oggi=“Errore!”
ENDIF
WRITE(*,*) Oggi
SELECT-CASE
Nei casi in cui la selezione fra più alternative è indirizzabile dai potenziali valori o
insieme/range di valori che può assumere un’espressione intera/carattere/logica, il
costrutto d’elezione reso disponibile dal Fortran è il SELECT-CASE:
SELECT CASE (expr)
CASE (selector-1)
block-1
……
CASE (selector-n)
block-n
CASE DEFAULT
block
END SELECT
E’ importante ricordare che i vari selettori rappresentano valori o gruppi/range di
valori che devono mutuamente escludersi!
SELECT-CASE
Riscriviamo, ad
esempio, il codice
Fortran per tradurre in
italiano il nome inglese
di un giorno della
settimana.
E’ evidente la maggiore
compattezza e
leggibilità del risultato
ottenuto!
CHARACTER(10) :: Today, Oggi
READ(*,*) Today
SELECT CASE (Today)
CASE (“Monday”)
Oggi=“Lunedi”
CASE (“Tuesday”)
Oggi=“Martedi”
CASE (“Wednesday”)
Oggi=“Mercoledi”
CASE (“Thursday”)
Oggi=“Giovedi”
CASE (“Friday”)
Oggi=“Venedi”
CASE (“Saturday”)
Oggi=“Sabato”
CASE (“Sunday”)
Oggi=“Domenica”
CASE DEFAULT
Oggi=“Errore!”
END SELECT
WRITE(*,*) Oggi
SELECT-CASE
UN’ ALTRA SEMPLICE APPLICAZIONE
PROGRAM calcolatrice
IMPLICIT NONE
!
!
INTEGER :: i,j,k
CHARACTER :: Operatore
DO
WRITE(*,*) “Inserisci due interi: ”
READ(*,*) i,j
WRITE(*,*) “Quale operazione?: ”
READ(*,*) Operatore
SELECT CASE (Operatore)
CASE ('+')
K=I+J
WRITE(*,*) ”La somma è: ”, K
CASE ('-')
K=I-J
WRITE(*,*) “La differenza è: “, K
CASE ('/‘,’:’)
K=I/J
WRITE(*,*) “Il quoziente è: “, K
CASE ('*‘, ‘x’, ‘X’)
K=I*J
WRITE(*,*) “Il prodotto è. “, K
CASE DEFAULT
WRITE(*,*) “Operatore non valido! “
END SELECT
END DO
END PROGRAM calcolatrice
UN’ APPLICAZIONE PIU’ COMPLESSA
PROGRAM equaz2grado
IMPLICIT NONE
REAL :: a, b, c, d ! coefficienti
! dell’equazione e discriminante
COMPLEX :: x1, x2 ! radici
! complesse dell’equazione
! lettura dei coefficienti
WRITE(*,*) "Coefficiente a: "
READ(*,*) a
WRITE(*,*) "Coefficiente b: "
READ(*,*) b
WRITE(*,*) "Coefficiente c: "
READ(*,*) c
! calcolo del discriminante
d = b**2-4.*a*c
IF (d > 0.) THEN
PRINT*, "Radici reali e distinte"
x1 = (-b-SQRT(d))/(2.*a)
x2 = (-b+SQRT(d))/(2.*a)
ELSE IF (d == 0.) THEN
PRINT*, "Radici reali e coincidenti"
x1 = -b/(2.*a)
x2 = x1
ELSE
PRINT*, "Radici complesse coniugate"
x1 = CMPLX(-b,-SQRT(-d))/(2.*a)
x2 = CONJG(x1)
END IF
WRITE(*,*) x1, x2
END PROGRAM equaz2grado
Perché non possiamo usare SELECT CASE per scegliere fra le tre
possibili soluzioni?
CICLO
CON CONTROLLO EX-ANTE
Sintassi Fortran:
DO WHILE (lexpr)
block
END DO
Oppure:
DO
IF (.NOT. lexpr) EXIT
block
END DO
CICLO
CON CONTROLLO EX-ANTE
PROGRAM costruisci_frase
IMPLICIT NONE
CHARACTER :: char
CHARACTER(200)::str
INTEGER :: i=0
WRITE(*,*) ‘Immetti un carattere (. per fine frase, # per spazio) :’
READ (*,*) char
DO WHILE(char /= ’.’)
i=i+1
IF (char == '#') char=' '
str(i:i) = char
WRITE(*,*) ‘Immetti un carattere (. per fine frase, # per spazio) :’
READ (*,*) char
END DO
WRITE(*,*) ‘La frase immessa è: ’, str(1:i)
END PROGRAM
CICLO
CON CONTROLLO EX-POST
Sintassi Fortran:
DO
block
IF (.NOT. lexpr) EXIT
END DO
CICLO
CON CONTROLLO EX-POST
PROGRAM temperatura
! Conversione temperatura fra diverse scale
IMPLICIT NONE
REAL :: T_c ! temperatura in gradi Celsius
REAL :: T_k ! temperatura in Kelvin
REAL :: T_f ! temperatura in gradi Fahrenheit
REAL :: T_r ! temperatura in gradi Reaumur
REAL :: dT ! incremento nella temperatura
REAL, PARAMETER :: Tmin_c=0.0 ! temperatura di congelamento dell’acqua
REAL, PARAMETER :: Tmax_c=100. ! temperatura di ebollizione dell’acqua
REAL, PARAMETER :: cost=1.8 ! fattore 9/5 della convers. Cels->Fahr
WRITE(*,*) "Incremento nella T: "; READ(*,*) dT
WRITE(*,*) "
Celsius
Kelvin
Fahrenheit
Reaumur
"
WRITE(*,*) " ========== ========== =========== ========== "
T_c = Tmin_c
DO
T_f = cost*T_c + 32.
T_k = 273.15 + T_c
T_r = 0.8*T_c
WRITE(*,*) T_c, T_k, T_f, T_r
T_c = T_c+dT
IF (.NOT. (T_c <= Tmax_c)) EXIT
! i
END DO
END PROGRAM temperatura
CICLO
CON CONDIZIONE DI USCITA
In realtà il ciclo DO del Fortran è
un costrutto estremamente
versatile che consente di
implementare molte logiche di
controllo. Per esempio, un ciclo
con condizione di uscita in
itinere, come quello in figura.
Sintassi Fortran:
DO
block1
IF (lexpr) EXIT
block2
END DO
CICLO
CON CONDIZIONE DI USCITA
Riconsideriamo il codice visto per il ciclo con controllo ex-ante, apprezzandone la
maggiore compattezza!
PROGRAM costruisci_frase
IMPLICIT NONE
CHARACTER :: char
CHARACTER(200)::str
INTEGER :: i=0
DO
WRITE(*,*) ‘Immetti un carattere(. per fine frase, # per spazio): ’
READ (*,*) char i=i+1
IF (char == ‘.’) EXIT ! Condizione di uscita
IF (char == '#') char=' '
str(i:i) = char
END DO
WRITE(*,*) ‘La frase immessa è: ’, str(1:i)
END PROGRAM
CICLO
CON CONTATORE
Sintassi Fortran:
DO i = inizio, fine [,passo]
block
END DO
ATTENZIONE:
- i è una variabile contatore di tipo INTEGER
- inizio, fine ed opzionalmente passo (1 per
default) sono espressioni di tipo INTEGER
- Le variabili utilizzate per inizio, fine e passo
non possono essere esplicitamente
modificate dal blocco di istruzioni interne al
ciclo.
- NON si dovrebbe far fede sul valore
assunto dalla variabile contatore a fine ciclo
e, quindi, utilizzarla esplicitamente nel
codice post-ciclo!
CICLO
CON CONTATORE
PROGRAM SOMMA_DI_CUBI
! Stampa tutti i numeri a tre cifre
! pari alla somma dei cubi delle loro cifre
IMPLICIT NONE
INTEGER H, T, U
DO H = 1, 9
! Ciclo 1° livello
DO T = 0, 9
! Ciclo 2° livello
DO U = 0, 9
! Ciclo 3° livello
IF (100*H + 10*T + U == H**3 + T**3 + U**3) THEN
WRITE(*, "(3I1)“) H, T, U
ENDIF
END DO
END DO
END DO
END SOMMA_DI_CUBI
LO STATEMENT CYCLE
PROGRAM DISPARI
! Conta il numero di naturali dispari immessi.
! Un numero negativo arresta la conta.
! Un numero pari forza una nuova iterazione.
IMPLICIT NONE
INTEGER :: numero, n_dispari=0
DO
WRITE(*,*) “Immetti numero: "
READ( *, *) numero
IF (numero < 0) THEN EXIT
IF (MODULO(numero, 2) == 0) CYCLE
n_dispari = n_dispari + 1
END DO
WRITE(*.*) “IL NUMERO DI DISPARI E’:", n_dispari
END PROGRAM DISPARI