APPUNTI DEL CORSO DI LABORATORIO DI CALCOLO AVANZATO

Save this PDF as:
 WORD  PNG  TXT  JPG

Dimensione: px
Iniziare la visualizzazioe della pagina:

Download "APPUNTI DEL CORSO DI LABORATORIO DI CALCOLO AVANZATO"

Transcript

1 APPUNTI DEL CORSO DI LABORATORIO DI CALCOLO AVANZATO Concetti fondamentali di FORTRAN 90 MARCO LIMONGI Istituto Nazionale di Astrofisica Osservatorio Astronomico di Roma

2 1. CONCETTI FONDAMENTALI DI FORTRAN 90 Sviluppare un programma in fortran implica i seguenti tre passi: Scrivere il sorgente. Cioe, attraverso un editor di testo, scrivere un file ascii che contenga tutte le istruzioni da eseguire Compilare. Cioe trasformare le istruzioni in linguaggio macchina Eseguire il Programma. La sequenza di comandi da digitare in ambiente bash e : $emacs programma.f90 & (editing del programma) $ifort [eventuali opzioni] programma.f90 (compilazione del programma) $./a.out (esecuzione del programma) oppure $ifort [eventuali opzioni] programma.f90 o eseguibile $./eseguibile 1.1. Struttura di un programma in Fortran Un programma Fortran ha generalmente la seguente struttura: Sezione dichiarativa: che include il nome del programma (o della routine, o della funzione), il tipo e il nome delle variabili utilizzate. Sezione esecutiva: che include le istruzioni che descrivono le azioni che il programma deve compiere. Sezione conclusiva: che e la dichiarazione di fine del programma (o della routine, o della funzione) 1

3 Program nomeprogramma! SEZIONE DICHIARATIVA Implicit none...dichiarazioni di variabili :! SEZONE ESECUTIVA...istruzioni! SEZIONE CONCLUSIVA End Program 1.2. Sezione dichiarativa La sezione dichiarativa e la prima parte del programma e consiste in una serie di dichiarazioni (o definizioni) preliminari Tipi semplici intrinseci. Il fortran 90 mette a disposizione 5 tipi di dati intrinseci: - INTEGER tipo numerico per gli interi - REAL tipo numerico per i reali - COMPLEX tipo numerico per i numeri complessi (non trattato in questo corso) - LOGICAL tipo per la gestione dei valori logici - CHARACTER tipo per la rappresentazione di stringhe di caratteri Variabili. Le variabili nella sezione dichiarativa vengono definite attraverso le istruzioni di dichiarazione. La dichiarazione associa ad una determinata variabile un determinato tipo, che ne definisce le caratteristiche. Per ogni tipo si avra in generale una dichiarazione differente. 2

4 Tipo INTEGER. Questo tipo puo utilizzare 1, 2, 4 o 8 bytes. L intervallo di definizione dipendera dal numeri di bytes utilizzati. Percio la sintassi per la dichiarazione di una variabile intera sara : - INTEGER(KIND=1) :: variabile (1 byte, valori da 2 7 a 2 7 1) - INTEGER(KIND=2) :: variabile (2 bytes, valori da 2 15 a ) - INTEGER(KIND=4) :: variabile (4 bytes, valori da 2 31 a ) - INTEGER(KIND=8) :: variabile (8 bytes, valori da 2 63 a ) Tipo REAL. Questo tipo puo utilizzare 4, 8, o 16 bytes. L intervallo di definizione e la precisione dipendera dal numeri di bytes utilizzati. Percio la sintassi per la dichiarazione di una variabile reale sara : - REAL(KIND=4) :: variabile (4 bytes, valori da a circa in modulo, precisione 8 cifre decimali) - REAL(KIND=8) :: variabile (8 bytes, valori da a circa in modulo, precisione 16 cifre decimali) - REAL(KIND=16) :: variabile (16 bytes, valori da a circa in modulo, precisione 32 cifre decimali) Tipo LOGICAL. Questo tipo e utilizzato per rappresentare i valori logici VERO o FALSO. In generale questo tipo puo utilizzare, come gli interi, 1, 2, 4 o 8 bytes. La sintassi per la dichiarazione di una variabile di tipo logico e : - LOGICAL(KIND=1) :: variabile (1 byte) - LOGICAL(KIND=2) :: variabile (2 bytes) - LOGICAL(KIND=4) :: variabile (4 bytes) - LOGICAL(KIND=8) :: variabile (8 bytes) Tipicamente si utilizza la dichiarazione con 1 byte. Tipo CHARACTER. Questo tipo e utilizzato per rappresentare sequenze di caratteri (stringhe) e la sintassi generale per la dichiarazione di variabili stringhe e : - CHARACTER(LEN=n) :: variabile (n = numero di caratteri) 3

5 Costanti Le costanti possono essere utilizzate sia nella sezione dichiarativa che in quella esecutiva. Se utilizzate nella sezione dichiarativa la sintassi generale sara - TIPO(KIND=n),PARAMETER :: costante=valore dove, al solito, il tipo e uno di quelli definito sopra. Se, invece, le costanti sono utilizzate nella sezione esecutiva, allora il loro tipo sara definito implicitamente. Ad esempio: 0, +28, Costanti di tipo INTEGER 0.E0, -3.3E2,1.0E-2 Costanti di tipo REAL(KIND=4) 0.D0, -3.3D2,1.0D-2 Costanti di tipo REAL(KIND=8).TRUE.,.FALSE. Costanti di tipo LOGICAL ciao, ciao Costanti di tipo CHARACTER Vettori. Un vettore (a array) e una sequenza di variabili tutte dello stesso tipo. Queste variabili vengono memorizzate in posizioni contigue di memoria. Si puo accedere ad una di queste variabili direttamente tramite un indice (o piu in generale una n upla di indici). La dichiarazione di un vettore avviene aggiungendo al nome tipo la sua dimensione. - TIPO(KIND=n,LEN=n),DIMENSION(m) :: nome dove m deve essere un intero costante o una costante definita come parameter. Ad esempio: REAL(KIND=8),DIMENSION(3) :: a dichiara un vettore di 3 reali, accessibili singolarmente come a(1), a(2), a(3) Gli array possono avere piu indici (dimensioni). Il rango di un array e il numero di dimensioni dell array stesso. Ad esempio REAL(KIND=8),DIMENSION(4,6) :: b dichiara una matrice 4x6 i cui elementi sono accessibili singolarmente come a(i,j). 4

6 Gli indici degli array possono avere diversi valori di minimo e massimo. Percio la dichiarazione piu generale di un array e : - TIPO(KIND=n,LEN=n),DIMENSION([estremo_inferiore:]estr emo_superiore) :: nome Ad esempio. INTEGER(KIND=4),DIMENSION(4:10) :: b definisce un vettore b le cui compenenti vanno da b(4) a b(10). Come le altre variabili un array puo essere inizializzato nella sezione dichiarativa. Ad esempio: REAL(KIND=8),DIMENSION(3) :: forza=(/3.2d0,-1.7d0,0.5d0/) N.B. Il numero di elementi fra i delimitatori / deve coincidere con quello degli elementi dell array. E possibile definire array la cui dimensione e allocata dinamicamente, cioe durante l esecuzione. Lo spazio viene allocato solo quando viene incontrata l istruzione ALLOCATE. La funzione ALLOCATED informa se l array e stato allocato o meno. La funzione DEALLOCATE libera lo spazio allocato per l array. Per utilizzare queste funzioni, l array deve essere definito com ALLOCATABLE, cioe : - TIPO(KIND=n,LEN=n),ALLOCATABLE,DIMENSION(:) :: nome o anche piu semplicemente - TIPO(KIND=n,LEN=n),ALLOCATABLE :: nome(:) Percio le istruzioni: REAL(KIND=4),ALLOCATABLE :: b(:) REAL(KIND=4),ALLOCATABLE :: a(:,:) dichiarano rispettivamente un vettore b e una matrice a di dimensioni indefinite. Per l allocazione e la deallocazione dinamica della memoria degli array rimandiamo al paragrafo sulla sezione dichiarativa. 5

7 Blocchi di memoria etichettati. I blocchi di memoria etichettati, cioe provvisti di nomi, vengono definiti da una istruzione di specificazione nella sezione dichiarativa del programma che assume la forma generica - COMMON /nome/nlista dove nome e il nome globale del blocco COMMON e nlista e la lista dei nomi delle variabili e dei nomi dei vettori che sono nell area di memoria etichettata nome separati dalla virgola. A questa area di memoria puo accedere qualsiasi unita o sottoprogramma (vedi dopo) del programma principale semplicemente inserendo la stessa istruzione COMMON e preservando l ordine delle variabili. Un disallineamento delle variabili provochera un errore in compilazione. Ovviamente una variabile puo comparire solo in un COMMON all interno dello stesso programma, sottoprogramma o unita. Se in un COMMON compare un vettore, la sua dimensione non puo essere allocata dinamicamente ma deve essere specificata Definizione dei valori iniziali. L istruzione DATA assegna un valore iniziale ad una variabile prima che il programma entri nella parte esecutiva. Questa istruzione, quindi, si trova nella sezione dichiarativa del programma. La sintassi dell istruzione DATA e la seguente: - DATA nlist1/clist1/,nlist2/clist2/... dove nlist e una lista di nomi di variabili e clist e un elenco di costanti. L effetto di questa istruzione, quindi, e quello di assicurare che ogni variabile della lista abbia un assegnato valore iniziale specificato dalla corrispondente costante. Ad esempio l istruzione: DATA A/0.1d0/,B/0.2d0/,N/3/ dara alle variabili A e B (reali) i valori iniziali 0.1 e 0.2, e alla variabile N (intera) il valore iniziale 3. 6

8 1.3. Sezione esecutiva. La sezione esecutiva e costituita da una serie di istruzioni Espressioni Le espressioni numeriche sono in generale costituite da operandi numerici ed operatori numerici. Il risultato di una espressione numerica e generalmente un singolo valore numerico. Gli operatori numerici sono i seguenti: Operatore Funzione ** Elevamento a potenza * Moltiplicazione / Divisione + Somma Sottrazione Le operazioni tra numeri interi hanno come risultato numeri interi. L operazione eseguita sul risultato e un troncamento. Cioe : 3/4=0, 4/4=1, 20/4=5, 21/4=5 Le operazioni tra numeri reali hanno come risultato numeri reali. Attenzione, pero, numero reale non vuol dire appartenente ad un continuo. In generale il risultato di una operazione e una approssimazione. Cioe 3.E0/4.E0=0.75E0, 4.E0/4.E0=1.E0, 1.E0+1.E-16=1.E0 In operazioni miste tra reali ed interi i numeri interi vengono convertiti in reali. Attenzione pero che la conversione avviene in ogni singolo sottocalcolo. 1.E0+1/4=1.E0, 1.E0+1.E0/4=1.25E0 Le espressioni relazionali consistono in due (o piu ) espressioni i cui valori vengono confrontati tra loro per valutare se e verificata o meno la relazione stabilita dall operatore relazionale. Gli operatori relazioni sono: 7

9 Operatore Relazione < Minore di <= Minore di o uguale a == Uguale a /= Diverso da > Maggiore di >= Maggiore di o uguale a Il risultato dell espressione relazionale sara.true. o.false. se la relazione specificata dall operatore relazionale sara soddisfatta o meno. Le espressioni logiche consistono in uno o piu operatori logici e operandi logici, numerici o relazionali. Gli operatori logici sono: Operatore Esempio Relazione.AND. A.AND. B L espressione e vera se A e B sono vere.or. A.OR. B L espressione e vera se A o B, o entrambe, sono vere.eqv. A.EQV. B L espressione e vera se A e B sono entrambe vere o entrambe false.neqv. A.NEQV. B L espressione e vera se A o B sono vere, ma l espressione e falsa se entrambe A e B sono vere.not..not. A L espressione e vera se A e falsa, e falsa se A e vera. 8

10 Istruzioni di assegnazione Il simbolo = non e il simbolo di uguaglianza, ma di assegnazione. In generale, quindi, in una istruzione di assegnazione avremo a sinistra del simbolo = il nome di una variabile, a destra del simbolo = una qualsiasi espressione valida. A=100 Assegna alla variabile A il valore 100 I=I+1 Aggiunge 1 alla variabile I e assegna il risultato alla variabile I Allocazione dinamica Come gia detto in precedenza e possibile definire degli array la cui dimensione non e fissata a priori, ma viene stabilita dinamicamente durante l esecuzione del programma, a seconda delle necessita. Per fare questo, oltre a definire l array di tipo ALLOCATABLE, e necessario scrivere l istruzione - ALLOCATE(nomevettore(n)) dove n e la dimensione del vettore. Per definire un intervallo degli indici l istruzione sara - ALLOCATE(nomevettore(n1:n2)) dove n1 e n2 sono l indice inferiore e superiore del vettore, rispettivamente. Se ad essere allocata e una matrice, allora l istruzione sara : - ALLOCATE(nomematrice(n1:n2,m1:m2)) La generalizzazione di questo comando a matrici con piu indici e evidente. Ovviamente i valori degli indici non sono in generale noti al momento della compilazione ma possono essere definiti durante l esecuzione del programma. Dopo l utilizzo e opportuno deallocare la memoria con il comando - DEALLOCATE(nomevettore(n)) - DEALLOCATE(nomevettore(n1:n2)) - DEALLOCATE(nomematrice(n1:n2,m1:m2)) 9

11 Se si vuole verifica l allocazione di un vettore (o una matrice) si puo utilizzare il comando: - ALLOCATED(nomevettore(n)) che restituisce un valore logico.true. se il vettore e stato allocato o.false. veceversa. L allocazione dinamica della memoria e utile allorquando non si conoscano le taglie degli array al momento della compilazione. In questo modo, quindi, e possibile gestire la memoria con maggiore efficenza, consentendo di ottimizare la quantita di spazio richiesto per il programma e permettendo cosi di poter trattare problemi altrimenti non trattabili a causa della scarsita della memoria Costrutto IF THEN ELSE Per implementare algoritmi complessi abbiamo bisogno di istruzioni piu complesse. La prima di queste permette di effetuare delle decisioni all interno del programma. E possibile questo attraverso il costrutto IF-THEN-ELSE. La forma piu semplice per questo costrutto e : IF(espressione_logica) istruzione Questo quando l istruzione da effettuare e una sola. Se invece si ha un blocco di istruzioni e possibile utilizzare il comando: IF(espressione_logica) THEN istruzioni ENDIF Notate come sia opportuno (anche se non necessario) che le istruzioni siano indentate per aumentare la leggibilita del codice. Nel caso ci siano due possiblita da decidere il costrutto si puo complicare nella forma: 10

12 IF(espressione_logica) THEN istruzioni ELSE istruzioni ENDIF Nel caso le decisioni da prendere siano piu di due allora la sintassi sara : IF(espressione_logica) THEN istruzioni ELSEIF(espressione_logica2) THEN istruzioni ELSE istruzioni ENDIF 11

13 Quindi nella forma piu generale il costrutto sara: IF(espressione_logica_1) THEN sequenza_di_istruzioni_1 ELSEIF(espressione_logica_2) THEN sequenza_di_istruzioni_2 ELSE sequenza_di_istruzioni_3 ENDIF E possibile infine anche associare un nome al costrutto secondo la sintassi [nome:] IF(espressione_logica_1) THEN sequenza_di_istruzioni_1 ELSEIF(espressione_logica_2) THEN [nome] sequenza_di_istruzioni_2 ELSE [nome] sequenza_di_istruzioni_3 ENDIF [nome] dove nome deve essere una stringa lunga massimo 31 caratteri e deve iniziare con una lettere. Nelle clausole ELSE IF e ELSE il nome e opzionale, mentre in ENDIF e obbligatorio. 12

14 Costrutto SELECT CASE Un altra istruzione di diramazione e il costrutto SELECT CASE la cui sintassi piu generale e : [nome:] SELECT CASE(espressione_di_case) THEN CASE(selettore_1) [nome] sequenza_di_istruzioni_1 CASE(selettore_2) [nome] sequenza_di_istruzioni_2 CASE DEFAULT [nome] sequenza_di_istruzioni_3 END SELECT [nome] In questo caso espressione_di_case viene confrontata con i selettori. Un selettore specifica una lista di range: se espressione_di_case e nel range di un selettore, allora il blocco di istruzioni corrispondenti verra eseguito, altrimento si passa al selettore successivo e cosi via fino eventualmente ad eseguire il blocco di istruzion di CASE DEFAULT. Attenzione perche espressione_di_case deve essere di tipo INTEGER, CHARACTER o LOGICAL ma non di tipo REAL. Un range puo essere specificato come segue: - valore esegue il blocco se espressione_di_case==valore - valore: esegue il blocco se espressione_di_case>=valore - :valore esegue il blocco se espressione_di_case<=valore - val1:val2 esegue il blocco se val1<=espressione_di_case<=val2 Un esempio dell uso di questo costrutto e il seguente: 13

15 INTEGER :: valore SELECT CASE (valore) CASE (1,2,3,5,7,11,13) stampa a terminale Numero primo CASE (4,6,8:10,12,14:15) stampa a terminale Numero non primo CASE (16:) stampa a terminale Numero troppo grande CASE DEFAULT stampa a terminale Errore END SELECT Questo costrutto permette una maggiore chiarezza rispetto al costrutto IF-THEN- ELSE Istruzioni di ciclo DO Le istruzioni di ciclo si utilizzano per eseguire compiti ripetitivi fino a che una determinata condizione si verifica. I cicli possono essere determinati, se si conosce esattamente il numero di iterazioni da effettuare, o indeterminati, se il numero di iterazioni e ignoto a priori ma finito. I primi vengono detti cicli iterativi mentre i secondi cicli while. Nei cicli iterativi il numero di iterazioni e noto nel momenti un cui si inizia il ciclo. E quindi necessaria una variabile (detta contatore ) che funge da inidice del ciclo. Questa variabile viene inizializzata automaticamente all inizio del ciclo, viene aggiornata automaticamente ad ogni iterazione e non deve essere mai cambiata dal programmatore. E necessario, inoltre stabilire gli estremi (iniziale e finale) del ciclo, che possono essere decisi durante l esecuzione e una volta stabiliti non possono essere piu cambiati, ed eventualmente un incremento che anch esso puo essere definito durante l esecuzione del programma e una volta stabilito non puo essere piu cambiato. La sintassi generale di un ciclo iterativo e : 14

16 DO indice=inizio,fine[,incremento] END DO sequenza di istruzioni Nel caso piu semplice in cui l incremento e uguale a 1 avvengono implicitamente le seguenti cose: 1. Immediatamente prima del DO viene posto indice=inizio (cio avviene una sola volta. 2. Se indice<=fine allora viene eseguita la sequenza di istruzioni. Immediatamente prima di END DO viene posto indice=indice Altrimenti si esce dal ciclo In questo caso il numero di iterazioni totali sara fine-inizio+1. L estensione al caso in cui l incremento sia arbitrario e 1. Immediatamente prima del DO viene posto indice=inizio (cio avviene una sola volta. 2. Se indice incremento<=fine incremento allora viene eseguita la sequenza di istruzioni. Immediatamente prima di END DO viene posto indice=indice+incremento. 3. Altrimenti si esce dal ciclo In questo caso il numero di iterazioni totali sara (fineinizio+incremento)/incremento. Nei cicli iterativi, quindi, il numero di iterazioni da eseguire e noto al momento in cui si entra nel ciclo. La limitazione di questi cicli, pero, sta nel fatto che esistono problemi che non si possono risolvere con un numero di iterazioni definito a priori. Ad esempio la lettura da tastiera di una sequenza di interi terminata da uno 0, il calcolo della lunghezza della sequenza (senza lo 0) e la stampa a terminale di quest ultima. Questa limitazione puo essere superata con i cicli while. Nei cicli while il numero di iterazioni non e necessariamente noto al momento di iniziare le iterazioni. La sintassi generale di un ciclo while e la seguente: 15

17 DO END DO sequenza_di_istruzioni_1 IF(espressione_logica) EXIT sequenza_di_istruzioni_2 Sia la prima che la seconda sequenza di istruzioni possono essere vuote (ovviamente non contemporaneamente). L espressione_logica e la sentinella del ciclo e rappresenta un evento particolare (ad esempio un valore particolare di una variabile) per cui il ciclo deve essere interrotto. L istruzione EXIT, percio, determina l uscita dal ciclo. Nei cicli annidati questa istruzione ha effetto sempre sul ciclo piu interno. Percio in questa sequenza DO sequenza_di_istruzioni_1 DO END DO END DO sequenza_di_istruzioni_2 IF(espressione_logica) EXIT sequenza_di_istruzioni_3 sequenza_di_istruzioni_4 l istruzione EXIT porta alla sequenza_di_istruzioni_4. Nota che l itruzione EXIT puo essere utilizzata in qualsiasi tipo di ciclo, anche in quelli iterativi. Un altra possibilita di implementazione dei cicli while e la seguente: DO WHILE (condizione) END DO sequenza_di_istruzioni_1 In questo caso il ciclo viene eseguito fino a che la condizione risulta verificata. 16

18 Una istruzione spesso utilizzata all interno dei cicli (sia iterativi che while) e il CYCLE, che fa partire la prossima iterazione del ciclo. Se questa istruzione viene utilizzata nei cicli while, l esecuzione riparte dalla prima sequenza di istruzione del ciclo dopo il DO, se invece e utilizzata in un ciclo iterativo, allora il contatore viene incrementato e l esecuzione riparte dalla prima sequenza di istruzioni subito dopo il DO. DO END DO sequenza_di_istruzioni_1 IF(espressione_logica) CYCLE sequenza_di_istruzioni_2 DO indice=inizio,fine[,incremento] END DO sequenza_di_istruzioni_1 IF(espressione_logica) CYCLE sequenza di istruzioni_2 Come per l istruzione EXIT, anche l istruzione CYCLE, nei cicli annidati, ha effetto sempre sul ciclo piu interno. Come per i costrutti IF-THEN-ELSE e SELECT CASE, anche i cicli posso essere identificati con un nome. Percio in generale la sintassi completa sara : [nome:] DO indice=inizio,fine[,incremento] sequenza di istruzioni END DO [nome] 17

19 [nome:] DO sequenza_di_istruzioni_1 IF(espressione_logica) EXIT [nome] sequenza_di_istruzioni_2 END DO [nome] [nome:] DO WHILE (condizione) sequenza_di_istruzioni_1 END DO [nome] L utilizzo del nome e utile spesso per gestire i comandi EXIT e CYCLE nei cicli annidati. Ad esempio in questa sequenza di istruzioni: esterno: DO sequenza_di_istruzioni_1 interno: DO sequenza_di_istruzioni_2 IF(espressione_logica) EXIT esterno sequenza_di_istruzioni_3 END DO interno sequenza_di_istruzioni_4 END DO esterno sequenza_di_istruzioni_5 il comando EXIT non porta all esecuzione della sequenza_di_istruzioni_4 come farebbe se non ci fosse indicato il nome, ma porta all uscita del ciclo piu esterno e percio all esecuzione della sequenza_di_istruzioni_5. 18

20 Operazioni di Input/Output Un programma FORTRAN puo leggere e scrivere su file, cioe una sequenza di elementi (caratteri e/o numeri) memorizzati in memoria secondaria (es. hard disk). La disciplina di accesso ad un file puo essere sequenziale, cioe dal primo elemento ai successivi in sequenza, o casuale, cioe ad un elemento qualsiasi in qualsiasi momento. E da notare che questi concetti sono generali ed indipendenti dal linguaggio di programmazione. Le operazioni principali su file sono: - Apertura di un file - Lettura di dati - Scrittura di dati - Chiusura del file Aprire di un file signifca creare una corrispondenza tra il nome fisico del file ed un nome logico da utilizzare all interno del programma e si effettua attraverso l istruzione: - OPEN (lista_open) La lista_open e una lista di parametri separati da una virgola. I parametri sono: - UNIT: che e il nome logico da utilizzare per accedere al file all interno del programma. Es. UNIT=10 - FILE: che e il nome fisico del file. Es. FILE= pippo.txt - STATUS: che puo assumere i seguenti valori: - OLD : se il file esiste gia e deve essere solo aperto; se il file non esiste viene segnalato un errore. - NEW : per creare un nuovo file se questo non esiste; se il file invece e gia esistente viene segnalato un errore - REPLACE : se il file esiste viene cancellato e ricreato - SCRATCH : per creare un file temporaneo che non viene salvato - ACTION : che puo essere READ o WRITE READ : il file puo essere solo letto, se viene scritto viene segnalato un messaggio di errore WRITE : il file puo essere solo scritto, se viene letto viene segnalato un messaggio di error 19

21 READWRITE : il file puo essere sia letto che scritto - IOSTAT : variabile di tipo INTEGER che memorizza eventi particolari e che permette di controllare lo stato delle operazioni. La sintassi e IOSTAT=nome_variabile. Se nome_variabile==0 tutto e andato a buon fine nome_variaible/=0 c e stato un errore nell operazione (ad esempio, un file in lettura non esiste, si e raggiunto la fine di un file in lettura o la fine di una riga, si e sbagliato il formato di lettura, etc.) In generale, se si vuole aprire un file in scrittura e sufficiente l istruzione - OPEN (UNIT=10,FILE= pippo.txt,iostat=ierr) cioe si e assegnato al file nuovo pippo.txt il nome logico 10 e la variabile intera ierr contiene il risultato delle operazioni su questo file. Attenzione perche se il file esiste questo viene cancellato e ricreato. La chiusura di un file significa cancellare l accoppiamento tra il nome fisico del file e l unita logica creata all interno del programma. La sintassi del comando e : - CLOSE (UNIT=unita_logica) Se un file aperto non viene chiuso, la chiusura avviene in modo implicito al termine del programma. La lettura e la scrittura su file avvengono attraverso i comandi - READ (UNIT=unita_logica,formato,IOSTAT=variabile) - WRITE (UNIT=unita_logica,formato) dove appunto l unita_logica e il nome logico assegnato al file nel comando OPEN. La specifica di formato verra descritto nel paragrafo successivo. Altre operazioni che possiamo fare sui files sono: - REWIND che ci riposiziona all inizio del file - BACKSPACE che ci riposiziona alla linea precedente Se al posto dell unita logica si scrive un asterisco, allora questo indica una lettura o scrittura dall input o l ouptut standard, tipicamente il monitor. 20

22 Formattazione dell Input e Output Abbiamo visto nel paragrafo precedente che alla lettura e alla scrittura su file o su monitor puo essere associata una specifica di formato. La specifica di formato puo essere assegnata attraverso: - un intero che specifica l etichetta di una istruzione FORMAT esplicita. Ad es. write(*,100)a 100 FORMAT(decrittori_di_formato) dove 100 e l etichetta di formato; - una stringa costante con nome formato= (descrittori_di_formato) write(*,formato)a - una stringa costante senza nome write(*,fmt= (descrittori_di_formato) )a - una stringa variabile (uso sofisticato che non tratteremo in questo corso) In tutti i casi i descrittori_di_formato specificano completamente il formato. In particolare: Controllano la posizione verticale della riga Controllano la posizione orizzontale Specificano come stampare una determinato valore Specificano quante volte deve essere ripetuto un descrittore I descrittori di formato utilizzano i seguenti simboli: - c: numero di colonna - d: numero di cifre a destra del punto decimale - m: numero minimo di cifre da visualizzare - n: numero di spazi da saltare - r: fattore di ripetizione - w: quanti caratteri utilizzare per un dato valore Se al posto della specifica di formato c e un asterisco, allora si intende un formato libero, cioe senza formattazione. 21

23 Numeri Interi: Il descrittore di formato generale per i numeri interi ha la forma - riw.m: - r indica quanto volte applicare il descrittore - w indica quanti caratteri usare per il numero - m indica quante cifre mostrare Ecco alcuni esempi: Numeri Reali: Il descrittore di formato generale per i numeri reali ha la forma - rfw.d (formato non esponenziale o virgola fissa): - r indica quanto volte applicare il descrittore - w indica quanti caratteri usare per il numero - d indica quante cifre decimali usare dopo il punto - rew.d (formato esponenziale o virgola mobile): - r indica quanto volte applicare il descrittore - w indica quanti caratteri usare per il numero - d indica quante cifre decimali usare dopo il punto Nota bene, se il descrittore di formato e preceduto da 1P allora il primo carattere del numero e la prima cifra significativa. 22

24 Alcuni esempi: WRITE(*,FMT= (E12.4) ) E+00 XXXXXXXXXXXX WRITE(*,FMT= (1P,E12.4) ) E-01 WRITE(*,FMT= (F8.4) ) XXXXXXXX XXXXXXXXXXXX Stringhe: Il descrittore di formato generale per le stringhe ha la forma: - raw: - r indica quanto volte applicare il descrittore - w (opzionale) specifica la larghezza del campo Alcuni esempi: WRITE(*,FMT= (A6) ) pippo pippo XXXXXX WRITE(*,FMT= (A8) ) pippo pippo XXXXXXXXX 1.4. Sezione Conclusiva La sezione conclusiva e composta dal comando: - END [PROGRAM [nome_programma]] 23

25 1.5. Modularizzazione (Subroutine, Function, Module) La modularizzazione e un esigenza generale della programmazione. Essa e utile a chi utilizza moduli realizzati da altri ed e utile a chi programma moduli per farli usare ad altri. Un modulo e una scatola nera. Per utilizzarlo: basta conoscere cosa fa non serve conoscere come lo fa In questo corso vedremo come realizzare semplici moduli software chiamati sottoprogrammi. E ragionevole scrivere un sottoprogramma in almeno due casi: uno stesso compito deve essere ripetuto piu volte, in contesti diversi uno stesso compito e parametrico In FORTRAN90 esistono die tipi di unita di programma: SUBROUTINE FUNCTION Le unita di programma in FORTRAN90 possono essere contenute in apposite librerie denominate moduli (MODULE). FUNCTION, SUBROUTINE e MODULE possono essere all interno dello stesso file che contiene il programma principale oppure possono essere file a se stanti (con estensione.f90). In questo secondo caso devono essere compilate separatamente e successivamente collegate al programma principale. Supponiamo di avere i seguenti file sorgenti: princ.f90 (contiene il PROGRAM main o programma principale) miomod.f90 (contiene un MODULE modulo) miasub.f90 (contiene la SUBROUTINE stampe) miafunc.f90 (contiene la FUNCTION areacerchio) La sequenza di comandi per creare ed utilizzare il file eseguibile e la seguente: Compilazione separata dei singoli files: $ifort c princ.f90 risultato: file princ.o $ifort c miomod.f90 risultato: file miomod.o e modulo.mod 24

26 $ifort c miasub.f90 risultato: file miasub.o $ifort c miafunc.f90 risultato: file miafunc.o Collegamento (link) dei singoli files e creazione eseguibile: $ifort o prova princ.o miomod.o miasub.o miafun.o risultato file eseguibile prova Esecuzione file eseguibile: $./prova Percio in generale lo sviluppo di programmi prevede la situazione tipica in cui si ha: Un file sorgente (.f90) contente il PROGRAM (o programma principale) vari files sorgente (.f90) ogniuno contente un MODULE; ogni MODULE puo contenere varie SUBROUTINE e/o FUNCTION; vari files sorgente (.f90) contenenti una o piu SUBROUTINE e una o piu FUNCTION Ogni unita di programma sara cotituita, come il programma principale, da una sezione dichiarativa, una sezione esecutiva ed una sezione conclusiva e per queste varranno le stesse regole discusse per il programma principale. Andiamo a vedere piu in dettaglio le varie unita di programma SUBROUTINE Una subroutine e una unita di programma indipendente che puo essere utilizzata all interno di altri programmi accetta un certo numero di parametri in input che puo elaborare restituisce un cetro numero parametri in output La sintassi per la dichiarazione di una subroutine e la seguente: 25

27 SUBROUTINE nome_subroutine(lista_argomenti) RETURN sezione dichiarativa sezione esecutiva END SUBROUTINE nome_subroutine Nella dichiarazione della subroutine, la lista_argomenti e una lista di parametri che possono essere in input e/o output. Per invocare una subroutine e necessario utilizzare l istruzione CALL nome_subroutine(lista_argomenti) L istruzione RETURN a fine procedura e opzionale, tuttavia alcuni compilatori potrebbero richiederla obbligatoriamente MODULE Il Module e un unita di programma che permette di includere subroutine e funzioni al suo interno. La sintassi per la dichiarazione di un modulo e : MODULE nome_modulo CONTAINS sezione dichiarativa dichiarazioni_di_unita _di_sottoprogrammi END MODULE nome_modulo Per invocare i sottoprogrammi o utilizzare le definizioni di tipo contenuti nel modulo e necessario importare il modulo attraverso l istruzione USE. Ad es. PROGRAM nome_programma USE nome_modulo IMPLICIT NONE... 26

28 FUNCTION Le funzioni definite dall utente possono essere utilizzate come qualsiasi funzione implicita FORTRAN90. La sintassi per definire una funzione e : FUNCTION nome_function(lista argomenti)! sezione dichiarativa TIPO:: nome_function! sezione esecutiva... RETURN nome_function=espressione END FUNCTION [nome_function] O in maniera equivalente: TIPO FUNCTION nome_function(lista argomenti) Come nel caso delle subroutine anche in questo caso l istruzione RETURN e opzionale. Le differenze principali tra subrotuine e function sono le seguenti. Le function restituiscono un valore Il tipo di tale valore va opportunamente dichiarato Le function vengono chiamate all interno delle espressioni Nell invocazione di una function non va usata l istruzione CALL Regole di visibilita Le costanti/variabili dichiarate in una unita di programma si chiamano LOCALI e non sono visibili all esterno dell unita di sottoprogramma stessa. Analogamente, le costanti/variabili definite nel programma principale non sono visibili all interno delle varie unita di programma. Di conseguenza possiamo dichiarare costanti e/o variabili con lo stesso nome in vari sottoprogrammi senza paura che ci sia interferenza tra queste. 27

29 Passaggio dei parametri nei sottoprogrammi I parametri costituiscono l interfaccia di una unita di programma, ovvero i dati che occorrono per poterla utilizzare. La lista dei parametri, presente tra le parentesi tonde a fianco al nome dell unita di programma, e costituita in generale da variabili e/o array. I parametri dei sottoprogrammi FORTRAN90 sono detti argomenti fittizi, cioe sono dei segnaposto per i valori veri e propri che saranno utilizzati durante l esecuzione del programma (argomenti reali). Esistono tre modalita distinte per ogni parametro passato che si definiscono attraverso l attributo INTENT nei seguenti modi: INTENT(IN): ingresso. Il parametro non puo essere modificato dentro la subroutine o funzione INTENT(OUT): uscita. Al termine della subroutine o funzione il valore del parametro potra essere stato modifica, il valore in ingresso non sara utilizzato INTENT(INOUT): ingresso e uscita. Il parametro ha informazioni in ingresso ma potra essere modificato (DEFAULT). Quando si invoca un sottoprogramma e necessario istanziare tutti i parametri, sostituendo cioe ai parametri fittizi i valori effettivi (espressioni, variabili, array, costanti). Lo schema di passaggio dei valori utilizzato dal FORTRAN90 e quello per riferimento, non vengono passati i valori veri e propri ma viene passo il riferimento alla locazione di memoria che contiene il valore. 28

30 2.6. Diagrammi di flusso Per sviluppare programmi complessi e utile avvalersi dei cosi detti diagrammi di flusso che sono una rappresentazione grafica delle operazioni che il programma dovra eseguire per effettuare il compito che noi desideriamo. La notazione grafica dei diagrammi di flusso e riportata nella seguente figura: Un esempio di diagrammi di flusso di un programma e il seguente: 29

31 Diagramma di flusso del costrutto IF THEN ELSE Sulla base delle definizioni precedenti possiamo indicare il diagramma di flusso di un costrutto IF-THEN-ELSE che sara : Ad esempio se volessimo scrivere un programma che, acquisiti in ingresso due numeri a e b determini la soluzione dell equazione ax+b=0 e la stampi a terminale, avremmo il seguente diagramma di flusso: 30

32 Diagramma di flusso del costrutto SELECT CASE Analogamente il diagramma di flusso di un costrutto SELECT CASE sara : 31

33 Diagramma di flusso del ciclo DO Il diagramma di flusso di un ciclo iterativo e : Un esempio di implementazione di un ciclo iterativo in un programma piu complesso e : 32

34 Il diagramma di flusso per un ciclo while, invece, ha la forma: 33

35 34

Operazioni di input e output in Fortran 90

Operazioni di input e output in Fortran 90 Operazioni di input e output in Fortran 90 Ing. Luca De Santis DIS - Dipartimento di informatica e sistemistica Anno accademico 2006/2007 Fortran 90: file e formattazione DIS - Dipartimento di informatica

Dettagli

Struttura logica di un programma

Struttura logica di un programma Struttura logica di un programma Tutti i programmi per computer prevedono tre operazioni principali: l input di dati (cioè l inserimento delle informazioni da elaborare) il calcolo dei risultati cercati

Dettagli

Algebra Booleana ed Espressioni Booleane

Algebra Booleana ed Espressioni Booleane Algebra Booleana ed Espressioni Booleane Che cosa è un Algebra? Dato un insieme E di elementi (qualsiasi, non necessariamente numerico) ed una o più operazioni definite sugli elementi appartenenti a tale

Dettagli

Appunti del corso di Informatica 1. 6 Introduzione al linguaggio C

Appunti del corso di Informatica 1. 6 Introduzione al linguaggio C Università di Roma Tre Dipartimento di Matematica e Fisica Corso di Laurea in Matematica Appunti del corso di Informatica 1 (IN110 Fondamenti) 6 Introduzione al linguaggio C Marco Liverani (liverani@mat.uniroma3.it)

Dettagli

Appunti del corso di Informatica 1 (IN110 Fondamenti) 6 Introduzione al linguaggio C

Appunti del corso di Informatica 1 (IN110 Fondamenti) 6 Introduzione al linguaggio C Università di Roma Tre Facoltà di Scienze M.F.N. Corso di Laurea in Matematica Appunti del corso di Informatica 1 (IN110 Fondamenti) 6 Introduzione al linguaggio C Marco Liverani (liverani@mat.uniroma3.it)

Dettagli

JAVASCRIPT. Tale file è associato alla pagina web mediante il tag