introduzione al fortranhome.deib.polimi.it/romanoni/docs/infocivili2012-2013/f… ·  ·...

39
1 Introduzione al Fortran FORTRAN = FORmula TRANslation nasce per programmare equazioni scientifiche Prima versione (IBM): anni 50 fu il primo linguaggio ad introdurre il concetto di compilatore Versioni successive: FORTRAN II (1958) FORTRAN IV (1962) FORTRAN 77 (1977) Fino al FORTRAN 77 il linguaggio assomiglia poco ai moderni linguaggi di programmazione molti costrutti “arcaici”, sintassi delle istruzioni antiquata e rigida Dal Fortran 90 il linguaggio assume un aspetto più “moderno”, più simile a quello dei linguaggi di programmazione di alto livello moderni e cambia nome: FORTRAN, tutto maiuscolo, si chiamano i linguaggi pre-1990; Fortran, con solo la F maiuscola, quelli post- 1990 Ulteriore versione: Fortran 95 non grosse differenze tra Fortan 90 e Fortran 95, si tende ad accomunarli nella dicitura Fortran 90/95 Fortran è in continua evoluzione una nuova versione sta venendo studiata in questi anni le ultime versioni sono studiate per facilitare la programmazione di algoritmi di calcolo paralleli in cui pezzi diversi dell'algoritmo sono eseguiti da macchine/processori diversi in parallelo

Upload: phamnhu

Post on 13-Apr-2018

227 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

1

Introduzione al Fortran

• FORTRAN = FORmula TRANslation– nasce per programmare equazioni scientifiche

• Prima versione (IBM): anni 50– fu il primo linguaggio ad introdurre il concetto di compilatore

• Versioni successive:– FORTRAN II (1958)– FORTRAN IV (1962)– FORTRAN 77 (1977)

• Fino al FORTRAN 77 il linguaggio assomiglia poco ai moderni linguaggi di programmazione

– molti costrutti “arcaici”, sintassi delle istruzioni antiquata e rigida

• Dal Fortran 90 il linguaggio assume un aspetto più “moderno”, più simile a quello dei linguaggi di programmazione di alto livello moderni

– e cambia nome: FORTRAN, tutto maiuscolo, si chiamano i linguaggi pre-1990; Fortran, con solo la F maiuscola, quelli post-1990

• Ulteriore versione: Fortran 95– non grosse differenze tra Fortan 90 e Fortran 95, si tende ad

accomunarli nella dicitura Fortran 90/95

• Fortran è in continua evoluzione– una nuova versione sta venendo studiata in questi anni– le ultime versioni sono studiate per facilitare la programmazione

di algoritmi di calcolo paralleli• in cui pezzi diversi dell'algoritmo sono eseguiti da

macchine/processori diversi in parallelo

Page 2: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

2

Il Fortran in questo corso

• Noi studiamo il Fortran 90/95, trascurando i retaggi del passato (ormai obsoleti), e concentrandoci sui concetti più moderni

– però il FORTRAN 77 non è sparito del tutto (anzi...)

• Libro di riferimento consigliato:Stephen J. ChapmanFortran 90/95 guida alla programmazione (2a ed.)McGraw-Hill, 2004

• Noi studiamo il Fortran 90/95 per differenza con il C– abbiamo già visto in C i concetti fondamentali della

programmazione (variabili, tipi, istruzioni, sottoprogrammi, ecc.)– ora vediamo come le stesse cose si fanno in Fortran

• Concetti fondamentali di programmazione:– definizione di programmi– dichiarazioni di variabili e tipi predefiniti– istruzioni

• assegnamento, istruzione condizionale, istruzione iterativa• I/O con Standard Input, Standard Output, file

– tipi definiti dall'utente• array e record

– sottoprogrammi• funzioni e procedure• passaggio parametri (per valore/per indirizzo)

– la visibilità degli elementi• il concetto di modulo

Page 3: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

3

Cominciamo con un esempio

• Scriviamo un programma che calcola l'età di un oggetto a partire dalla percentuale rimasta di carbonio 14

• L'età si calcola mediante la seguente equazione:

laddove tdecay

è l'età desiderata, λ è la costante di decadimento,

e Q/Q0 la percentuale di carbonio 14 rimasta

• Il programma Fortran desiderato è il seguente:

PROGRAM c14_dateIMPLICIT NONE

! Costante di decadimento radiattivo del C-14! la costante e' di tipo realeREAL, PARAMETER :: LAMBDA = 0.00012097

! Dichiariamo le variabili (tutte di tipo reale)REAL :: age ! eta' del campione in anniREAL :: percent ! percentuale di carbonio 14 ! rimastoREAL :: ratio ! rapporto tra C-14 rimasto e ! quantita' originale

! Chiede all'utente la % di carbonio 14 rimastoWRITE (*,*) & 'Digita la percentuale di carbonio rimasto: 'READ (*,*) percent

! Svolge i calcoli.ratio = percent / 100.age = (-1.0 / LAMBDA)*log(ratio)

! Stampa l'eta' del campioneWRITE (*,*) "l'eta' del campione e' ", age, 'anni'

! Fine del programmaEND PROGRAM c14_date

t decay=−1log

QQ0

Page 4: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

4

Alcune osservazioni

• Il programma principale inizia con la keyword PROGRAM– il programma principale non si chiama più per forza main, ma ha

un nome definito dall'utente• nel nostro caso PROGRAM c14_date

– il nome di un programma non può essere più lungo di 31 caratteri

• Il corpo del programma non è più racchiuso tra {}, ma va dalla keyword PROGRAM fino alla keyword END PROGRAM

– il nome del programma dopo END PROGRAM è facoltativo

• Un programma si compone, come in C, di:– una prima parte dichiarativa– una seconda parte esecutiva

• I commenti iniziano con '!' e finiscono alla fine della riga– se voglio mettere un commento su più righe devo ripetere '!'

• Il Fortran è case-insensitive: non fa differenza tra maiuscole e minuscole

– scrivere PROGRAM c14_date oppure PRogrAm C14_dAtE è la stessa identica cosa

• Il tipo REAL è il corrispondente di float e double in C– ci sono vari modi per specificare quale è la precisione di un

REAL, ma noi non li vediamo

• Per dichiarare una variabile var di tipo NomeTipo, la sintassi è NomeTipo :: var

– per esempio REAL :: age

• L'istruzione IMPLICIT NONE serve per obbligare il programmatore a dichiarare tutte le variabili che usa

– altrimenti il Fortran, per le variabili che non conosce, assume una dichiarazione implicita secondo regole che non vediamo

– Usate sempre IMPLICIT NONE!

– IMPLICIT NONE va scritta dopo PROGRAM, prima di qualunque altra istruzione

Page 5: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

5

Osservazioni (cont.)

• Se invece di una variabile voglio dichiarare una costante devo usare l'attributo PARAMETER nella dichiarazione, e poi indicare il valore della costante

– per esempio REAL, PARAMETER :: LAMBDA = 0.00012097

• L'istruzione di assegnamento è come in C, solo non c'è il ';' finale

– anche in Fortran si usa il simbolo = per l'assegnamento, ed il simbolo == per l'uguaglianza!

• Le istruzioni di I/O sono READ e WRITE– le istruzioni READ(*,*) e WRITE(*,*) indicano

rispettivamente l'input da Standard Input e l'output su Standard Output non formattato

– si arrangia il Fortran a capire il formato in cui deve leggere/scrivere in base al tipo delle variabili indicate nelle istruzioni

– fare I/O formattato in Fortran è abastanza macchinoso, c'è tutta una serie di codici da imparare... sono dettagli che noi non vedremo!

• Su una riga ci può stare al massimo una istruzione– non c'è il separatore ';' che mi può dire quando una istruzione

finisce ed inizia l'altra

• Ogni istruzione deve stare su una riga– se una istruzione deve andare a capo, alla fine di ogni riga

dell'istruzione va messo il carattere '&' per fare da collegamento

• log è una cosiddetta funzione intrinseca– di fatto è una funzione di libreria automaticamente inclusa e nota

al compilatore– il Fortran ha una ricca libreria di funzioni intrinseche, che

permettono di fare una grande quantità di calcoli matematici• sin, cos, exp, ecc.

Page 6: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

6

Altri tipi predefiniti

• Il tipo INTEGER– può avere diverse precisioni

• non vedremo questo dettaglio, lo dichiareremo in una sola maniera

– Esempio di dichiarazione di variabile INTEGER:INTEGER :: varint

– In Fortran tra INTEGER e REAL valgono le regole di conversione automatica che ci sono in C tra float/double e int

• Il tipo CHARACTER– a dispetto del nome, il tipo CHARACTER indica sequenze (cioè

stringhe) di caratteri– un carattere singolo è una sequenza di un solo carattere– La lunghezza massima della stringa viene dichiarata con

un'apposita sintassi CHARACTER(len=<lungh>)

– Esempi di dichiarazioni di variabili di tipo carattere:CHARACTER :: c ! lunghezza 1CHARACTER(len=1) :: inizialeCHARACTER(len=10) :: nomeCHARACTER(10) :: cognomeCHARACTER(10) :: titolo = 'Ing.'

– Esempi di assegnamenti a variabili di tipo carattere:nome = "Giacomo"cognome = 'Ferri'iniziale = "B"

• In Fortran le stringhe di caratteri possono essere racchiuse o tra doppi apici ("), o tra apici singoli ('), per cui è indifferente scrivere "Giacomo" o 'Giacomo'

• Se devo mettere un ' in una stringa, posso racchiuderla tra ""– "Questa e' un'altra storia"

• Il tipo LOGICAL– è il classico tipo boolean

– può assumere i valori .TRUE. o .FALSE.

– Esempio di dichiarazione di variabile logica:LOGICAL :: trovato

– Esempio di assegnamento:trovato = .FALSE.

Page 7: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

7

Un nuovo esempio

• Calcolo di una funzione a 2 variabili fatta in questo modo:f(x,y) = x + y se x ≥ 0 e y ≥ 0

x + y2 se x ≥ 0 e y < 0x2 + y se x < 0 e y ≥ 0x2 + y2 se x < 0 e y < 0

• Un programma Fortran che calcola la funzione è il seguente:

PROGRAM funxyIMPLICIT NONE

REAL :: xREAL :: yREAL :: fun

! Chiede all'utente di inserire x ed yWRITE (*,*) 'Digitare i coefficienti X ed Y: 'READ (*,*) x, y

! Ripete i coefficienti all'utenteWRITE (*,*) 'I coefficienti immessi sono', x, y

! Calcola il valore della funzione in base! ai segni di x ed yIF ( (x>=0) .AND. (y>=0) ) THEN fun = x+yELSE IF ( (x>=0) .AND. (y<0) ) THEN fun = x + y**2ELSE IF ( (x<0) .AND. (y>=0) ) THEN fun = x**2 + yELSE fun = x**2 + y**2END IF

!Visualizza il risultatoWRITE (*,*) "Il valore della funzione e': ", fun

END PROGRAM funxy

Page 8: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

8

L'istruzione IF

• La sintassi dell'istruzione IF è:IF ( <condizione 1> ) THEN <istruzioni 1>ELSE IF ( <condizione 2>) THEN <istruzioni 1>...ELSE <istruzioni ELSE>END IF

– i blocchi ELSE IF ed ELSE possono anche non esserci

– le istruzioni ELSE IF ed ELSE devono stare su righe singole

• Gli operatori logici per combinare le condizioni sono:.AND..OR..NOT.

– In più ci sono gli operatori .EQV. e .NEQV.• c1 .EQV. c2 dà .TRUE. se e solo se c1 e c2 sono o

entrambe .TRUE. o entrambe .FALSE. (.NEQV. è la negazione di .EQV.)

• Si noti che il Fortran ha un operatore predefinito per l'elevamento a potenza: ab si scrive a**b

Page 9: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

9

Un esempio con ciclo while

• Si vuole scrivere un programma che calcola media e deviazione standard di una sequenza di numeri:

• Il programma:

PROGRAM statsIMPLICIT NONE

INTEGER :: n = 0REAL :: std_dev = 0, sum_x = 0, sum_x2 = 0REAL :: x = 0, x_bar

WRITE (*,*) 'Digita il prossimo numero: 'READ (*,*) x! Ciclo per leggere i dati di inputDO WHILE (x >= 0) n = n + 1 sum_x = sum_x + x sum_x2 = sum_x2 + x**2

! leggo il prossimo numero WRITE (*,*) 'Digita il prossimo numero: ' READ (*,*) xEND DO

! Controllo che siano stati inseriti almeno 2 valoriIF ( n < 2 ) THEN WRITE (*,*) 'Bisogna inserire almeno 2 valori!'ELSE ! calcola la media x_bar = sum_x / n ! calcola la deviazione standard std_dev = SQRT((n*sum_x2 - sum_x**2)/n*(n-1))

! stampa a video i risultati WRITE (*,*) "La media dei valori letti e': ", x_bar WRITE (*,*) "La deviazione standard e': ", std_dev WRITE (*,*) "Il numero dei valori elaborati e': ", nEND IF

END PROGRAM stats

media=1n∑i=1

n

si

stdev= n∑i=1

n

si2−∑

i=1

n

si2

nn−1

Page 10: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

10

Il ciclo DO WHILE

• Sintassi:DO WHILE ( <condizione> ) <istruzioni>END DO

– la semantica è la stessa del ciclo while in C

– le istruzioni DO WHILE e END DO vanno su righe singole

• Si noti che nel programma vengono lasciate molte conversioni implicite tra INTEGER e REAL

– per esempio in x_bar = sum_x / nn viene converitito in REAL per fare la divisione

– se volessi esplicitare la conversione dovrei scrivere:x_bar = sum_x / real(n)

• In Fortran c'è anche l'equivalente del ciclo for

• Sintassi del "ciclo iterativo" (l'equivalente del for):DO <indice> = <inizio>, <fine>, <incremento> <istruzioni>END DO

– indice è il nome di una variabile intera usata come contatore– incremento è opzionale: se non è specificato, di default viene

preso uguale ad 1– all'inizio del ciclo ad indice viene assegnato il valore inizio, e ad

ogni iterazione esso viene incrementato di incremento; il ciclo termina quando il valore di indice supera fine

– di fatto, la semantica del ciclo iterativo in Fortran è la stessa del seguente ciclo for in C:for(indice = inizio; indice <= fine; indice = indice+incremento){ ... istruzioni ...}

– una importante differenza tra il ciclo iterativo in Fortran ed in C: in Fortran, il valore dell'indice alla fine del ciclo è indefinito!

• in C, invece, è l'ultimo valore assunto dall'indice

Page 11: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

11

Il programma stats rivisto

• Questa volta, prima di leggere la sequenza di valori di cui calcolare media e deviazione standard, chiediamo all'utente quanti numeri vuole inserire, e poi usiamo un ciclo iterativo per leggerli:

PROGRAM stats_2IMPLICIT NONE

INTEGER :: n = 0INTEGER :: i ! i sara' l'indice del cicloREAL :: std_dev = 0, sum_x = 0, sum_x2 = 0REAL :: x = 0, x_bar

! Acquisisce il numero di dati da leggereWRITE (*,*) 'Digita il numero di dati da leggere: 'READ (*,*) n! Controllo il numero di dati da leggere sia almeno 2IF ( n < 2 ) THEN WRITE (*,*) 'Bisogna inserire almeno 2 valori!'ELSE ! Ciclo per leggere i dati di input DO i = 1, n ! leggo il prossimo numero WRITE (*,*) 'Digita il prossimo numero: ' READ (*,*) x

sum_x = sum_x + x sum_x2 = sum_x2 + x**2

END DO

! calcola la media x_bar = sum_x / n ! calcola la deviazione standard std_dev = SQRT((n*sum_x2 - sum_x**2)/n*(n-1))

! stampa a video i risultati WRITE (*,*) "La media dei valori letti e': ", x_bar WRITE (*,*) "La deviazione standard e': ", std_dev WRITE (*,*) "Il numero dei valori elaborati e': ", nEND IF

END PROGRAM stats_2

Page 12: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

12

Un esempio di manipolazione di caratteri

• Scriviamo un programma che legge 2 stringhe e le confronta in modo case-insensitive (ignorando cioè la differenza tra maiuscole e minuscole)

PROGRAM confrontoIMPLICIT NONE

INTEGER :: iCHARACTER(len=20) :: str1, str1aCHARACTER(len=20) :: str2, str2aINTEGER, PARAMETER :: diffAa = IACHAR('a')-IACHAR('A')

! Legge la prima stringa e la mette in str1WRITE (*,*) 'Immettere la prima stringa'READ (*,*) str1! Legge la seconda stringa e la mette in str2WRITE (*,*) 'Immettere la seconda stringa'READ (*,*) str2

! Crea copie delle stringhe per non modificare! quelle originalistr1a = str1str2a = str2

! Rende le lettere nella prima stringa tutte maiuscoleDO i = 1, LEN(str1a) IF (str1a(i:i) >= 'a' .AND. str1a(i:i) <= 'z') THEN str1a(i:i) = ACHAR( IACHAR(str1a(i:i)) - diffAa ) END IFEND DO! Rende le lettere nella prima stringa tutte maiuscoleDO i = 1, LEN(str2a) IF (str2a(i:i) >= 'a' .AND. str2a(i:i) <= 'z') THEN str2a(i:i) = ACHAR( IACHAR(str2a(i:i)) - diffAa ) END IFEND DO

! Confronta le stringhe e visualizza il risultatoIF ( str1a == str2a ) THEN WRITE (*,*) "'", str1, "' = '", str2, "'"ELSE WRITE (*,*) "'", str1, "' /= '", str2, "'"END IF

END PROGRAM confronto

Page 13: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

13

Osservazioni

• IACHAR prende in ingresso un carattere singolo e ritorna il codice ASCII corrispondente

• ACHAR prende in ingresso un intero rappresentante un codice ASCII e ritorna il carattere corrispondente

• Una nota sulle stringhe di caratteri:– se una stringa è dichiarata di lunghezza L, e le assegno una

sequenza più corta di L caratteri, Fortran riempie la stringa con spazi

– una stringa è quindi sempre della lunghezza dichiarata con l'attributo len

• LEN è una funzione intrinseca che ritorna la lunghezza della stringa passata come parametro

– per quanto detto sopra, ritorna la lunghezza dichiarata con l'attributo len

– la funzione intrinseca che ritorna la lunghezza senza gli spazi "riempitivi" finali è LEN_TRIM

• Posso assegnare stringhe di caratteri in un colpo solo– per esempio posso scrivere str1a = str1

– in C questo non l'avrei potuto fare, perchè str1 e str1a sarebbero stati identificatori di array

– del resto, vedremo che in Fortran posso assegnare array in un colpo solo

• Posso confrontare stringhe di caratteri con i soliti operatori– Posso scrivere IF (str1a == str2a) THEN...

– Potrei anche scrivere IF(str1a < str2a) THEN ...• confronto in ordine stabilito dalla sequenza ASCII

• ATTENZIONE!!Come in C, == indica l'uguaglianza, mentre = indica l'assegnamento!

Page 14: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

14

Osservazioni (cont.)

• Posso indicare sottostringhe di caratteri– per esempio str1a(i:i) è la sottostringa che va dall'i-esimo

carattere all'i-esimo carattere, cioè è la sottostringa fatta di un solo carattere, l'i-esimo

– se scrivessi str1a(1:3) avrei la sottostringa con i primi 3 caratteri di str1a

– Notate che il primo carattere è quello di indice 1!!• in C sarebbe quello di indice 0• vedremo in effetti che negli array in Fortran il primo carattere ha

indice 1

• Tutto ciò che posso fare con le stringhe di caratteri, lo posso fare con le sottostringhe!

– le posso assegnare• per esempio str1a(i:i) = ACHAR(...) assegna alla

sottostringa i:i il carattere ritornato dalla funzione ACHAR

– le posso confrontare• potrei scrivere

IF(str1a(1:3) < str1a(6:8) ) THEN ...

• Posso anche concatenare stringhe, eliminarne gli spazi vuoti...– non vedremo, i dettagli li trovate sui libri di riferimento se vi

servono

Page 15: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

15

Esempio di programma con array

• Scriviamo un programma che legge una sequenza di numeri, li memorizza in un array, e ne trova il minimo ed il massimo

PROGRAM estremiIMPLICIT NONE! Dichiariamo in una costante la dimensione! massima dell'arrayINTEGER, PARAMETER :: MAX_SIZE = 10

! Dichiariamo l'array di elementiINTEGER, DIMENSION(MAX_SIZE) :: inputINTEGER :: imax, imin ! indici di massimo e minimoINTEGER :: nvals ! numero di elementi lettiINTEGER :: j, temp

! Acquisisce il numero di elementi da leggereWRITE (*,*) "Digita il numero di valori da leggere: "READ (*,*) nvals

IF (nvals <= MAX_SIZE) THEN ! legge i valori DO j = 1, nvals WRITE (*,*) 'Immetti il valore ', j READ (*,*) input(j) END DO

! trova il massimo temp = input(1) imax = 1; DO j = 2, nvals IF ( input(j) > temp ) THEN temp = input(j) imax = j END IF END DO

Page 16: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

16

Esempio (cont.)

! trova il minimo temp = input(1) imin = 1; DO j = 2, nvals IF ( input(j) < temp ) THEN temp = input(j) imin = j END IF END DO

! Visualizza i valori WRITE (*,*) 'I valori sono: ' DO j = 1, nvals IF (j == imax ) THEN WRITE (*,*) input(j), 'MASSIMO' ELSE IF (j == imin) THEN WRITE (*,*) input(j), 'MINIMO' ELSE WRITE (*,*) input(j) END IF END DOELSE WRITE (*,*) 'Troppi valori di input!'END IF

END PROGRAM estremi

Page 17: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

17

Osservazioni sugli array

• La dichiarazione di una variabile di tipo array viene fatta specificando la dimensione dell'array mediante l'attributo DIMENSION

– per esempioINTEGER, DIMENSION(MAX_SIZE) :: input

– Altri esempi di dichiarazioni di array:REAL, DIMENSION(12) :: piogge87, piogge88CHARACTER (len=20), DIMENSION(20) :: nomi

• nomi è un array di stringhe!

• Per accedere ad un elemento di un array si usa la notazionearray(indice)

– si noti che si usano le parentesi tonde, non le quadre come in C!– per esempio

temp = input(1)piogge(4) = 2.92nomi(2) = "Giovanni"nomi(4)(5:8) = "Joe"

• Gli indici degli array in Fortran iniziano da 1!!– A differenza del C, dove iniziavano da 0

– input(1) è il primo elemento dell'array, non il secondo!

• Al solito, devo fare attenzione a non andare oltre i limiti dell'array, o il comportamento del programma diventa imprevedibile (dipende dal compilatore)

• Fin qui è tutto molto simile al C...

Page 18: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

18

Array in Fortran: caratteristiche peculiari

• Posso scegliere da dove fare partire gli indici di un array:tipo, DIMENSION(ind_iniz:ind_fin) :: nome_var

• Per esempio:REAL, DIMENSION(-2:5) :: ar

– in questo caso gli elementi sonoar(-2), ar(-1), ar(0), ... ar(5)

• sono 8 elementi in tutto

– il primo elemento stavolta ha indice -2!

• Posso sommare, moltiplicare, ecc. gli elementi corrispondenti di 2 array in un colpo solo!

PROGRAM somma_arrayIMPLICIT NONE

REAL, DIMENSION(4) :: a = (/ 1., 2., 3., 4. /) ! Questa e' la sintassi per inizializzare un ! array in fase di dichiarazioneREAL, DIMENSION(3:6) :: b = (/ 5., 6., 7., 8. /)REAL, DIMENSION(4) :: cREAL, DIMENSION(40:43) :: d

! Somma globalec = a + bd = a * b

WRITE (*,*) 'c = ', cWRITE (*,*) 'd = ', d

END PROGRAM somma_array

Page 19: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

19

Array in Fortran (cont.)

• Posso anche sommare, moltiplicare, ecc. un array con uno "scalare" (un elemento singolo):c = a * 2

– esegue l'operazione elemento per elemento: se a contiene{ 1, 2, 3, 4 }, c contiene {2, 4, 6, 8}

• Posso anche applicare la maggior parte delle funzioni intrinseche ad un array:c = SQRT(a)

– esegue l'operazione elemento per elemento

• Posso manipolare sottoarray di un array: se dichiaroREAL, DIMENSION(20) :: arar(3:5) è il sottoarray fatto degli elementiar(3), ar(4), ar(5)

• Se ho un array a, a(ind1 : ind2 : p) è il sottoarray che comincia dall'elemento di indice ind1 ed arriva all'elemento di indice ind2 saltando di p elementi in p elementi

– per esempio, ar(1:10:2) è il sottoarray fatto degli elementiar(1), ar(3), ar(5), ar(7), ar(9)

– per esempio, potrei avere le seguenti dichiarazioni:REAL,DIMENSION(20) :: arREAL,DIMENSION(5) :: vals=(/ 1.5,2.2,-6.3,9.,4. /)ar(1:10:2) = vals

Page 20: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

20

Array multidimensionali

• In Fortran posso dichiarare array multidimensionali specificando il numero di elementi per ogni dimensione

• Per esempio, se voglio dichiarare una matrice di 5×18 elementi reali:REAL, DIMENSION(5,18) :: mat

• Se invece voglio dichiarare un array cube di interi a 3 dimensioni, tutte di lunghezza 11:INTEGER, DIMENSION(11,11,11) :: cube

• Gli array in Fortran possono avere al massimo 7 dimensioni!– in C invece non c'era limite al numero di dimensioni

• Valgono anche per gli array multidimensionali i discorsi sugli indici e sui sottoarray che sono stati fatti per gli array monodimensionali:

– esempio di matrice (array bidimensionale) di reali in cui gli indici della prima dimensione vanno da -10 a -5, e gli indici della seconda vanno da -1 a 7:REAL, DIMENSION(-10:-5, -1:7) :: mat2

– Esempi di sottoarray dell'array mat dichiarato sopra:mat(3:5, 2:13:3)mat(4,:)

• questo è il sottoarray fatto della intera quarta riga di mat

• Il costrutto array in Fortran è molto potente e flessibile– essendo Fortran nato per programmare operazioni matematiche,

ed essendo il concetto di sequenza, matrice, ecc. molto comune in matematica, il linguaggio è stato dotato di operazioni potenti per gestire questi elementi

• Queste non sono le sole proprietà ed operazioni degli array in Fortran, ma si rimanda al libro di testo per ulteriori spiegazioni

Page 21: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

21

I record in Fortran

• Vediamo un banale esempio di programma che fa uso di record:

PROGRAM esempio_recordIMPLICIT NONE

! Dichiara il tipo strutturato personTYPE :: person CHARACTER(len=14) :: nome CHARACTER :: iniziale_intermedia CHARACTER(len=14) :: cognome CHARACTER(len=14) :: telefono INTEGER :: eta CHARACTER :: sesso CHARACTER(len=11) :: previdenza_socialeEND TYPE person

! Dichiara una variabile di tipo personTYPE (person) :: john

! Inizializza la variabilejohn%nome = 'John'john%iniziale_intermedia = 'R'john%cognome = "Jones"john%telefono = "323-6439"john%eta = 21john%sesso = "M"john%previdenza_sociale = "123-45-6789"

! Stampa a video il contenuto del recordWRITE (*,*) john

END PROGRAM esempio_record

Page 22: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

22

Osservazioni

• La dichiarazione di un tipo record in Fortran ha la seguente sintassi:TYPE :: nome_tipo tipo_campo1 :: nome_campo1 tipo_campo2 :: nome_campo2 ...END TYPE nome_tipo

• La dichiarazione di una variabile di tipo record ha la seguente sintassi:TYPE (nome_tipo) :: nome_var

• Per accedere ad un campo di un record si usa il simbolo di %– invece del simbolo . usato in C!

– per esempio john%nome

• Rivediamo il programma fatture in Fortran:

PROGRAM fattureIMPLICIT NONE

! Dichiarazione del tipo strutturato dataTYPE :: data INTEGER :: giorno INTEGER :: mese INTEGER :: annoEND TYPE

! Dichiarazione del tipo strutturato fatturaTYPE :: fattura CHARACTER(len=30) :: indirizzo INTEGER :: ammontare TYPE (data) :: data_fattEND TYPE

Page 23: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

23

Il programma fatture in Fortran (cont.)

INTEGER, PARAMETER :: MaxNumFatture = 1000! Dichiarazione dell'elenco di fattureTYPE (fattura), DIMENSION(MaxNumFatture) :: arch

INTEGER :: nfattINTEGER :: iINTEGER :: totale = 0

WRITE (*,*) "Inserisci numero fatture"READ (*,*) nfatt

IF (nfatt <= MaxNumFatture) THEN DO i = 1,nfatt WRITE (*,*) "Fattura numero ", i WRITE (*,*) & "Inserisci indirizzo e ammontare" READ (*,*) arch(i)%indirizzo, arch(i)%ammontare

WRITE (*,*) "Inserisci giorno, mese, ed anno" READ (*,*) arch(i)%data_fatt%giorno, & arch(i)%data_fatt%mese, & arch(i)%data_fatt%anno END DO

DO i = 1,nfatt totale = totale + arch(i)%ammontare END DO

WRITE (*,*) "Il fatturato totale e': ", totale

ELSE WRITE (*,*) & "il numero di fatture immesso e' maggiore di ", & MaxNumFatture

END IF

END PROGRAM fatture

Page 24: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

24

Sottoprogrammi in Fortran

• Il Fortran distingue tra funzioni e procedure, usando 2 keyword diverse per i 2 tipi di sottoprogrammi

• Il concetto di sottoprogramma non c'era nelle primissime versioni del linguaggio, è stato aggiunto dopo, con il meccanismo delle subroutine (procedure); questo fa sì che il meccanismo dei sottoprogrammi in Fortran non sia "unitario", ma abbia tutta una serie di eccezioni e distinguo

– in particolar modo, il concetto di procedura è "privilegiato" rispetto a quello di funzione, cioè in Fortran si tende a pensare più in termini di procedura (subroutine) che non di funzione

• mentre in C è un po' il contrario: si tende a pensare tutto in termini di funzione, e le procedure sono un caso particolare

• Cerchiamo comunque di mettere un po' di ordine...• Cominciamo con un esempio di procedura che prende in

ingresso le misure dei cateti di un triangolo rettangolo e ne calcola l'ipotenusa:

SUBROUTINE calc_ipotenusa ( lato_1, lato_2, ipotenusa )IMPLICIT NONE

! Dichiariamo i parametri formaliREAL, INTENT(IN) :: lato_1 ! lungh. primo catetoREAL, INTENT(IN) :: lato_2 ! lungh. secondo catetoREAL, INTENT(OUT) :: ipotenusa ! lungh. ipotenusa

! Dichiariamo le variabili localiREAL :: temp

temp = lato_1**2 + lato_2**2ipotenusa = SQRT(temp)

RETURN

END SUBROUTINE calc_ipotenusa

Page 25: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

25

Esempio di procedura (cont.)

• Scriviamo un programma che invoca la procedura calc_ipotenusa

PROGRAM prova_ipotenusaIMPLICIT NONE

! variabili localiREAL :: c1REAL :: c2REAL :: ipot

! Acquisisce le lunghezze dei latiWRITE (*,*) & 'Inserisci la lunghezza del primo cateto'READ (*,*) c1WRITE (*,*) & 'Inserisci la lunghezza del secondo cateto'READ (*,*) c2

! Invoca la procedura calc_ipotenusaCALL calc_ipotenusa( c1, c2, ipot )

! Visualizza il risultatoWRITE (*,*) "La lunghezza dell'ipotenusa e' ", ipot

END PROGRAM prova_ipotenusa

Page 26: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

26

Osservazioni sulle procedure

• Definite con la sintassi:SUBROUTINE nome_proc ( lista nomi par. formali )...END SUBROUTINE nome_proc

• Sulla prima riga della definizione mettiamo solo i nomi dei parametri formali, le dichiarazioni complete le mettiamo nel corpo della procedura

– per esempioREAL, INTENT(IN) :: lato_1

• Di ogni parametro formale dichiariamo l'intento, cioè se questo è un parametro in ingresso (IN), in uscita (OUT), o sia in ingresso che in uscita (INOUT)

– nel nostro esempio abbiamo 2 parametri in ingresso, lato_1 e lato_2, ed un parametro in uscita, ipotenusa

– se un parametro ha intento IN, nel corpo della procedura non gli posso assegnare un valore (se ci provo, il compilatore mi segnala un errore)

– se un parametro ha intento o OUT o INOUT, nel corpo della procedura gli posso assegnare un valore (ed il valore assegnato è visibile da parte del chiamante)

• L'esecuzione della procedura termina o quando arrivo a END SUBROUTINE, oppure quando incontro l'istruzione RETURN

– RETURN in Fortran non ha mai a fianco nessuna espressione, a differenza del C

• non c'è mai RETURN espressione, ma sempre e solo RETURN

• La chiamata di una procedura avviene mediante l'istruzioneCALL nome_proc (lista parametri attuali)

– Al solito, la corrispondenza tra parametri attuali e parametri formali è posizionale

• Notate che il Fortran non prevede che il prototipo di una procedura venga dichiarato nel corpo di un programma

– il programma invoca la procedura senza averne da nessuna parte dichiarato il prototipo

Page 27: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

27

Passaggio parametri in Fortran

• Abbiamo visto che in Fortran dichiaro l'intento di ogni parametro

– IN, OUT, o INOUT

• Ma come viene effettuato il passaggio parametri in Fortran, per valore o per indirizzo?

– abbiamo visto che in C c'era in realtà solo il passaggio per valore, e per avere l'effetto del passaggio per indirizzo dovevo ricorrere ai puntatori

• In realtà in Fortran c'è solo il passaggio per indirizzo– in Fortran, tutti i parametri sono sempre e solo passati per indirizzo– non c'è bisogno di passare indirizzi e dereferenziare in modo

esplicito come in C: in Fortran, sempre, automaticamente, quando passo un parametro in realtà ne passo l'indirizzo, e quando uso il parametro nel corpo del sottoprogramma, uso il parametro attuale (c'è una dereferenziazione implicita)!

• Questo vuole dire che quando scrivoipotenusa = tempsto in effetti andando a modificare il parametro attuale (nel caso del programma prova_ipotenusa, vado a modificare ipot!)

– in C avrei dovuto scrivere una cosa del tipo *ipotenusa = temp, ma qui la dereferenziazione è automatica

• Le dichiarzioni INTENT mi dicono solo quale è l'uso inteso del parametro, ma ciò non toglie che questo sia passato comunque per indirizzo

• E se volessi ottenere l'effetto del passaggio parametri per valore?– Il massimo che riesco a fare è dichiarare un parametro che voglio

passare per valore come INTENT(IN). In questo modo il parametro è ancora passato per indirizzo, ma il compilatore mi segnala un errore se provo ad assegnare un valore a quel parametro

Page 28: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

28

Funzioni

• Vediamo un semplice esempio di funzione che calcola il valore del polinomio ax2+bx+c per un certo valore di x passato come argomento, ed un programma che la usa

REAL FUNCTION quadf (x, a, b, c)IMPLICIT NONE

REAL, INTENT(IN) :: xREAL, INTENT(IN) :: aREAL, INTENT(IN) :: bREAL, INTENT(IN) :: c

! calcola il risultatoquadf = a * (x**2) + b*x + c

END FUNCTION quadf

PROGRAM test_quadfIMPLICIT NONE

! Dichiaro la funzione quadf! (in effetti ne dichiaro il risultato)REAL :: quadfREAL :: a, b, c, x

WRITE (*,*) 'Inserisci i coefficienti a, b, c: 'READ (*,*) a, b, cWRITE (*,*) & "Inserisci la x in cui valutare l'equazione: "READ (*,*) x

WRITE (*,*) "ax^2 + bx +c = ", quadf(x, a, b, c)

END PROGRAM test_quadf

Page 29: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

29

Osservazioni sulle funzioni

• Dichiarazione mediante la sintassi:tipo_rit FUNCTION nome_fun ( nomi par. formali )...END FUNCTION nome_fun

• Per i parametri formali vale lo stesso identico discorso che per le procedure

– passati per indirizzo, ne dichiaro l'intento, ecc...– tipicamente, i parametri di una funzione sono tutti dichiarati con

INTENT(IN), a meno che non voglia effetti collaterali, o a meno che la funzione non debba ritornare 2 risultati

• Di fatto, una funzione ha una variabile automaticamente dichiarata, che si chiama come la funzione stessa ed ha il tipo del valore ritornato, nella quale devo mettere il risultato della funzione perchè possa essere mandato indietro al chiamante

– per esempio, nella variabile quadf (di tipo REAL) devo mettere il risultato della funzione omonima

• L'esecuzione di una funzione termina quando:– si incontra l'istruzione END FUNCTION

– oppure quando si incontra l'istruzione RETURN

• Il valore ritornato dalla funzione è il contenuto della variabile omonima della funzione quando l'esecuzione termina

– nel nostro esempio, è il valore della variabile quadf quando l'esecuzione della funzione omonima termina

Page 30: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

30

Osservazioni sulle funzioni (cont.)

• Nel chiamante, devo dichiarare il nome della funzione, ed associargli il tipo del valore ritornato

– per esempio, nel programma test_quadf c'è la dichiarazioneREAL :: quadf

• Per chiamare una funzione la sintassi è simile al C: non si usa l'istruzione CALL come per le procedure, ma semplicemente si scrivenome_fun( lista parametri attuali )

– l'invocazione deve essere messa dentro una qualche espressione, non è una istruzione in sé come è per le procedure

• o del tipo var = nome_fun( lista parametri attuali )

• oppure per esempio in una WRITE, ecc.

Page 31: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

31

Passsaggio di parametri di tipo array

• Anche in Fortran, occorre fare attenzione al passaggio di parametri di tipo array

• Come in C, quando passo un array, questo viene passato per indirizzo (tutto in Fortran viene passato per indirizzo)

• Cosa è l'indirizzo di un array? E' l'indirizzo del suo primo elemento

• Come in C, anche in Fortran, quando passo un array, tutto ciò che il sottoprogramma conosce dell'array è l'indirizzo del suo primo elemento

– non ne conosce la dimensione!

• Come in C, anche in Fortran, la dimensione dell'array passato deve essere comunicata al sottoprogramma mediante un apposito parametro

– questo parametro può poi essere usato per dichiarare il parametro di tipo array

• Vediamo un esempio di procedura che prende in ingresso 2 array di reali (di dimensione n, indicata in un parametro apposito), e mette nei primi nvals elementi del secondo array i valori dei primi nvals elementi del primo moltiplicati per 3

SUBROUTINE array_per_3 (dato1, dato2, n, nvals)IMPLICIT NONE! Dichiaro i parametri n e nvalsINTEGER, INTENT(IN) :: n, nvals

! Dichiaro anche la dimensione degli arrayREAL, INTENT(IN), DIMENSION(n) :: dato1REAL, INTENT(OUT), DIMENSION(n) :: dato2dato2(1:nvals) = 3. * dato1(1:nvals)

END SUBROUTINE array_per_3

Page 32: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

32

Ambienti condivisi e moduli

• Abbiamo visto che il Fortran ha molti (quasi tutti) concetti in comune con il C

• Tuttavia, notiamo che in Fortran non c'è in realtà il concetto di ambiente globale che c'era in C

• Dove dichiariamo allora quegli elementi che devono essere condivisi tra vari sottoprogrammi?

– meglio ancora, dove mettiamo le dichiarazioni che in C sarebbero dichiarazioni globali (tra cui anche le dichiarazioni dei sottoprogrammi)?

• In Fortran c'è il concetto di modulo:– un modulo di fatto definisce un ambiente nel quale noi mettiamo

delle dichiarazioni/definizioni che devono essere condivise– i vari sottoprogrammi che devono utilizzare gli elementi

dichiarati in un modulo devono dichiarare di usare quel modulo mediante una apposita istruzione

– sottoprogrammi/programmi diversi possono dichiarare di usare uno o più moduli

– diversi sottoprogrammi/programmi possono usare diversi moduli• di fatto l'ambiente globale è frazionato in moduli, ed ogni

sottoprogramma/programma sceglie quale parte di ambiente globale utilizzare dichiarando quali moduli usa

• Notiamo che in C il concetto di modulo c'è, ma non lo abbiamo visto per questioni di tempo

– per la verità lo abbiamo "intravisto": un modulo in C è un file .h da includere nel programma

Page 33: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

33

Un esempio di modulo

• Cominciamo con un semplicissimo esempio di dichiarazione di un modulo che contiene una variabile, ed un programma ed una procedura che usano quella variabile:

MODULE dati_condivisiIMPLICIT NONESAVE

INTEGER, PARAMETER :: NUM_VALORI = 5REAL, DIMENSION(NUM_VALORI) :: valori

END MODULE dati_condivisi

PROGRAM test_moduloUSE dati_condivisiIMPLICIT NONE

REAL, PARAMETER :: pi = 3.141592valori = pi * (/ 1., 2., 3., 4., 5. /)

CALL sub1

END PROGRAM test_modulo

SUBROUTINE sub1USE dati_condivisiIMPLICIT NONE

WRITE (*,*) valori

END SUBROUTINE sub1

Page 34: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

34

Osservazioni sui moduli

• Sintassi di un modulo:MODULE nome_modulo...END MODULE nome_modulo

• Cosa posso mettere dentro a un modulo?– dichiarazioni di variabili– dichiarazioni di costanti– dichiarazioni di tipi strutturati– definizioni di sottoprogrammi (procedure e/o funzioni)

• per queste ci vuole una dichiarazione aggiuntiva che vediamo tra un attimo

• Se voglio che il valore di una variabile condivisa rimanga inalterato tra 2 chiamate di procedure diverse, devo mettere dentro al modulo la dichiarazione SAVE

• Perchè un programma/sottoprogramma possa usare gli elementi di un modulo, appena dopo l'inizio del programma/sottoprogramma (cioè appena dopo la dichiarazione PROGRAM/SUBROUTINE/FUNCTION) devo mettere l'istruzioneUSE nome_modulo

– l'istruzione USE va messa prima della IMPLICIT NONE

Page 35: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

35

Moduli e sottoprogrammi

• Dentro ad un modulo posso mettere la definizione di un sottoprogramma

• La definizione del sottoprogramma deve essere messa dopo una dichiarazione CONTAINS

• Vediamo un esempio: un modulo con delle procedure che fanno calcoli statistici

– vediamo solo la procedura che, dato un array di reali, trova il valore massimo e l'indice corrispondente

– altre procedure (che potete provare a fare a casa)• una che trova il valore minimo e l'indice corrispondente• una che calcola media e deviazione standard• una che ordina gli elementi in ordine crescente

MODULE stat_module

CONTAINS SUBROUTINE rmax ( a, n, max_reale, imax ) IMPLICIT NONE

! Dichiarazione dei parametri formali INTEGER, INTENT(IN) :: n REAL, INTENT(IN), DIMENSION(n) :: a REAL, INTENT(OUT) :: max_reale INTEGER, INTENT(OUT) :: imax ! Variabili locali INTEGER :: i

max_reale = a(1) imax = 1 DO i = 2,n IF( a(i) > max_reale ) THEN max_reale = a(i) imax = i END IF END DO END SUBROUTINE rmax

! Seguono le definizioni degli altri sottoprogrammi

END MODULE stat_module

Page 36: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

36

Moduli e sottoprogrammi (cont.)

• Attenzione che il compilatore Fortran di norma non controlla che la chiamata di un sottoprogramma sia conforme alla sua definizione

– non controlla cioè che il numero ed il tipo dei parametri attuali passati corrisponda al numero ed al tipo dei parametri formali del sottoprogramma!

• Questo perchè non c'è in Fortran il concetto di "prototipo" di un sottoprogramma, per cui un chiamante "non sa" come è fatta l'intestazione di un sottoprogramma

– è compito del programmatore assicurarsi che il passaggio parametri sia fatto correttamente

• altrimenti il comportamento è imprevedibile

• C'è però una maniera per permettere al compilatore di controllare che l'invocazione sia fatta rispettando il numero ed il tipo dei parametri: definire il sottoprogramma dentro ad un modulo

– se invoco un sottoprogramma definito in un modulo, permetto (anzi, obbligo) il compilatore a controllare che il passaggio parametri sia fatto in maniera corretta

• Consiglio: definite sempre i vostri sottoprogrammi dentro ad un modulo

Page 37: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

37

Gestione dei file in Fortran

• La gestione dei file in Fortran è basata sugli stessi concetti che ci sono in C:

– apertura del file– lettura/scrittura di elementi– chiusura del file

• Le operazioni di lettura e scrittura sono le stesse READ e WRITE che abbiamo già visto

• Per ora noi abbiamo scritto READ e WRITE sempre come READ (*,*) e WRITE (*,*)

– in realtà la sintassi di READ e WRITE è la seguente:READ ( identificatore di file, formato ) ...WRITE ( identificatore di file, formato ) ...

– se metto * al posto del formato, READ e WRITE si arrangiano a capire che cosa sto leggendo/scrivendo: se sono interi, caratteri, reali, ecc.

• i codici di formato in Fortran sono anche più macchinosi e complicati che non in C, ve li guardate sul libro se siete curiosi...

– se metto * al posto dell'identificatore del file, la READ assume che stia leggendo da Standard Input, mentre la WRITE assume che stia scrivendo su Standard Output

• Se voglio leggere da un file diverso da Standard Input o scrivere su un file diverso da Standard Output, devo aprire il file, assegnarli un numero identificativo, e poi usare questo numero identificativo al posto di *

– l'identificativo del file è un numero intero non negativo

Page 38: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

38

Gestione dei file in Fortran (cont.)

• Noi non entreremo in tutti i dettagli della gestione dei file in Fortran, vediamo solo un esempio, giusto per avere un'idea

– vedete il libro per tutti i dettagli in proposito

• Scriviamo un programma che– apre un file esistente di nome filein.dat in modalità lettura, e

gli assegna il numero identificativo 10

– apre un nuovo file di nome fileout.dat in modalità scrittura, e gli assegna il numero identificativo 11

– legge un valore reale dal primo file– scrive il valore letto nel secondo file– chiude entrambi i file

PROGRAM manipola_fileIMPLICIT NONE

INTEGER, PARAMETER :: id_fin = 10INTEGER, PARAMETER :: id_fout = 11! Uso la variabile ierror per! registrare eventuali errori nelle operazioni! di apertura dei fileINTEGER :: ierrorREAL :: v

! Apro il file in ingressoOPEN ( UNIT=id_fin, FILE="filein.dat", & STATUS="OLD", ACTION="READ", IOSTAT=ierror )! Apro il file in uscitaOPEN ( UNIT=id_fout, FILE="fileout.dat", & STATUS="NEW", ACTION="WRITE", IOSTAT=ierror )

! Leggo un valore reale dal file in ingressoREAD (id_fin, *) v! Scrivo il valore letto nel file in uscitaWRITE (id_fout, *) v

! Chiudo i fileCLOSE (id_fin)CLOSE (id_fout)

END PROGRAM manipola_file

Page 39: Introduzione al Fortranhome.deib.polimi.it/romanoni/docs/InfoCivili2012-2013/F… ·  · 2012-12-21Stephen J. Chapman Fortran 90/95 guida alla programmazione (2a ed.) McGraw-Hill,

39

Un'osservazione conclusiva

• Anche in Fortran esiste il concetto di puntatore• Questo però non mi serve più per realizzare il passaggio

parametri per indirizzo, visto che il passaggio parametri in Fortran è già per indirizzo così come è

• Il concetto di puntatore mi serve per fare altre cose, più avanzate, che noi non abbiamo visto in C e che non vedremo neanche in Fortran, per cui lo lasciamo perdere...

– il libro di Fortran contiene tutte le informazioni necessarie se qualcuno è curioso in proposito