Fortran 77. Manuale di riferimento [1 ed.]
 8876613455, 9788876613456

Table of contents :
INDICE
1. SET DI CARATTERI.................................................................................1
2. PARSING ...................................................................................................1
3. ETICHETTE (LABEL)...............................................................................1
4. FORMATO DEL CODICE SORGENTE ..................................................2
5. IDENTIFICATORI.....................................................................................2
6. INIZIO DEL PROGRAMMA PRINCIPALE ............................................3
7. VARIABILI ................................................................................................3
8. COSTANTI.................................................................................................3
9. TIPI DI DATI..............................................................................................4
9.1 INTEGER............................................................................................6
9.2 REAL..................................................................................................6
9.3 DOUBLE PRECISION.......................................................................7
9.4 COMPLEX .........................................................................................7
9.5 LOGICAL...........................................................................................8
9.6 CHARACTER ....................................................................................8
9.6.1 Sottostringhe ...................................................................................9
10. VETTORI E MATRICI ........................................................................10
11. INIZIALIZZAZIONE DELLE VARIABILI........................................12
11.1 INIZIALIZZAZIONE DI VETTORI E MATRICI ..........................13
12. ASSEGNAZIONI .................................................................................14
12.1 ASSIGN ............................................................................................15
13. OPERAZIONI.......................................................................................15
13.1 OPERAZIONI ARITMETICHE.......................................................16
13.1.1 Priorità.......................................................................................16
13.1.2 Associatività..............................................................................16
13.1.3 Tipo del risultato .......................................................................16
13.2 OPERAZIONI SU STRINGHE ....................................................... 17
13.3 ESPRESSIONI RELAZIONALI......................................................17
13.3.1 Confronto tra caratteri............................................................... 18
13.3.2 Confronto tra stringhe............................................................... 18
13.4 ESPRESSIONI LOGICHE...............................................................19
13.5 CALCOLO DELLE ESPRESSIONI................................................20
14. ISTRUZIONI DI SALTO..................................................................... 20
14.1 GOTO INCONDIZIONATO............................................................20
14.2 GOTO CALCOLATO......................................................................20
14.3 ASSIGNED GOTO ..........................................................................21
15. ESPRESSIONI CONDIZIONALI........................................................21
15.1 IF ARITMETICO.............................................................................21
15.2 IF LOGICO.......................................................................................22
16. ESECUZIONI CICLICHE ...................................................................23
16.1 CICLI IMPLICITI ............................................................................26
16.1.1 Annidamento.............................................................................26
17. TERMINE DELL’ESECUZIONE DEL PROGRAMMA ................... 27
18. TERMINE DI CIASCUN MODULO .................................................. 27
19. SOTTOPROGRAMMI.........................................................................27
19.1 SUBROUTINE.................................................................................30
19.2 FUNCTION......................................................................................31
19.3 FUNZIONI A SINGOLA ISTRUZIONE ........................................ 32
19.4 PUNTI DI INGRESSO MULTIPLI ................................................. 32
19.5 RITORNI ALTERNATIVI DA SOTTOPROGRAMMI................. 33
19.6 MANTENIMENTO DEI VALORI TRA LE CHIAMATE............. 33
19.7 PASSAGGIO DI NOMI DI FUNZIONE A SOTTOPROGRAMMI........ 34
19.8 FUNZIONI DI LIBRERIA (INTRINSECHE)................................. 35
20. EQUIVALENZA DI AREE DI MEMORIA........................................36
21. AREE COMUNI...................................................................................39
21.1 NAMED COMMON ........................................................................39
21.2 BLANK COMMON .........................................................................40
21.3 INIZIALIZZAZIONE DELLE VARIABILI COMMON ................41
22. INPUT/OUTPUT..................................................................................42
22.1 INPUT...............................................................................................42
22.2 OUTPUT...........................................................................................43
22.3 INPUT/OUTPUT FORMATTATO..................................................44
22.3.1 Formato dei dati nelle istruzioni di I/O.....................................45
22.3.2 Descrittori di campo..................................................................48
22.3.3 Prefissi dei descrittori................................................................52
22.3.4 Ripetizioni dei descrittori..........................................................53
22.4 FREE-FORMAT (LIST-DIRECTED I/O) .......................................54
22.5 UNFORMATTED I/O ......................................................................54
22.6 I/O DI VETTORI E MATRICI.........................................................55
23. INPUT/OUTPUT SU FILE ..................................................................56
23.1 APERTURA......................................................................................57
23.2 CHIUSURA ......................................................................................58
23.3 LETTURA FILE SEQUENZIALI....................................................58
23.4 SCRITTURA FILE SEQUENZIALI................................................59
23.5 RIPOSIZIONAMENTO DI FILE SEQUENZIALI .........................59
23.6 LETTURA FILE DIRETTO.............................................................60
23.7 SCRITTURA FILE DIRETTO.........................................................60
23.8 FILE INTERNI .................................................................................60
23.9 RICHIESTA CARATTERISTICHE DI UN FILE...........................61
24. INCLUSIONE DI FILE........................................................................63
25. BIBLIOGRAFIA ..................................................................................63
A. APPENDICE – FUNZIONI INTRINSECHE STANDARD ................... 64
B. PICCOLA APPENDICE SUL CALCOLO NUMERICO ....................... 71

Citation preview

Claudio Fornaro

FORTRAN 77 Manuale di riferimento

© Celid, febbraio 2007 via Cialdini, 26 – 10138 Torino tel. 011.44.74.774 www.celid.it I diritti di riproduzione, di memorizzazione e di adattamento totale o parziale con qualsiasi mezzo (compresi microfilm e copie fotostatiche) sono riservati.

ISBN ??-????-???-? Stampa SATIZ (TO)

INDICE

iii

INDICE 1.

SET DI CARATTERI .................................................................................1

2.

PARSING ...................................................................................................1

3.

ETICHETTE (LABEL)...............................................................................1

4.

FORMATO DEL CODICE SORGENTE ..................................................2

5.

IDENTIFICATORI.....................................................................................2

6.

INIZIO DEL PROGRAMMA PRINCIPALE ............................................3

7.

VARIABILI ................................................................................................3

8.

COSTANTI.................................................................................................3

9.

TIPI DI DATI..............................................................................................4 9.1

INTEGER............................................................................................6

9.2

REAL ..................................................................................................6

9.3

DOUBLE PRECISION.......................................................................7

9.4

COMPLEX .........................................................................................7

9.5

LOGICAL ...........................................................................................8

9.6 CHARACTER ....................................................................................8 9.6.1 Sottostringhe ...................................................................................9 10.

VETTORI E MATRICI ........................................................................10

11.

INIZIALIZZAZIONE DELLE VARIABILI........................................12

11.1 12. 12.1 13.

INIZIALIZZAZIONE DI VETTORI E MATRICI ..........................13 ASSEGNAZIONI .................................................................................14 ASSIGN ............................................................................................15 OPERAZIONI.......................................................................................15

13.1 OPERAZIONI ARITMETICHE.......................................................16 13.1.1 Priorità.......................................................................................16 13.1.2 Associatività..............................................................................16 13.1.3 Tipo del risultato .......................................................................16

iv

INDICE 13.2

OPERAZIONI SU STRINGHE ....................................................... 17

13.3 ESPRESSIONI RELAZIONALI...................................................... 17 13.3.1 Confronto tra caratteri............................................................... 18 13.3.2 Confronto tra stringhe............................................................... 18 13.4

ESPRESSIONI LOGICHE............................................................... 19

13.5

CALCOLO DELLE ESPRESSIONI ................................................ 20

14.

ISTRUZIONI DI SALTO..................................................................... 20

14.1

GOTO INCONDIZIONATO............................................................ 20

14.2

GOTO CALCOLATO ...................................................................... 20

14.3

ASSIGNED GOTO .......................................................................... 21

15.

ESPRESSIONI CONDIZIONALI........................................................ 21

15.1

IF ARITMETICO ............................................................................. 21

15.2

IF LOGICO....................................................................................... 22

16.

ESECUZIONI CICLICHE ................................................................... 23

16.1 CICLI IMPLICITI ............................................................................ 26 16.1.1 Annidamento............................................................................. 26 17.

TERMINE DELL’ESECUZIONE DEL PROGRAMMA ................... 27

18.

TERMINE DI CIASCUN MODULO .................................................. 27

19.

SOTTOPROGRAMMI......................................................................... 27

19.1

SUBROUTINE ................................................................................. 30

19.2

FUNCTION ...................................................................................... 31

19.3

FUNZIONI A SINGOLA ISTRUZIONE ........................................ 32

19.4

PUNTI DI INGRESSO MULTIPLI ................................................. 32

19.5

RITORNI ALTERNATIVI DA SOTTOPROGRAMMI ................. 33

19.6

MANTENIMENTO DEI VALORI TRA LE CHIAMATE ............. 33

19.7

PASSAGGIO DI NOMI DI FUNZIONE A SOTTOPROGRAMMI 34

19.8

FUNZIONI DI LIBRERIA (INTRINSECHE) ................................. 35

INDICE

v

20.

EQUIVALENZA DI AREE DI MEMORIA ........................................36

21.

AREE COMUNI ...................................................................................39

21.1

NAMED COMMON ........................................................................39

21.2

BLANK COMMON .........................................................................40

21.3

INIZIALIZZAZIONE DELLE VARIABILI COMMON ................41

22.

INPUT/OUTPUT ..................................................................................42

22.1

INPUT...............................................................................................42

22.2

OUTPUT...........................................................................................43

22.3 INPUT/OUTPUT FORMATTATO..................................................44 22.3.1 Formato dei dati nelle istruzioni di I/O.....................................45 22.3.2 Descrittori di campo..................................................................48 22.3.3 Prefissi dei descrittori................................................................52 22.3.4 Ripetizioni dei descrittori..........................................................53 22.4

FREE-FORMAT (LIST-DIRECTED I/O) .......................................54

22.5

UNFORMATTED I/O ......................................................................54

22.6

I/O DI VETTORI E MATRICI.........................................................55

23.

INPUT/OUTPUT SU FILE ..................................................................56

23.1

APERTURA......................................................................................57

23.2

CHIUSURA ......................................................................................58

23.3

LETTURA FILE SEQUENZIALI....................................................58

23.4

SCRITTURA FILE SEQUENZIALI................................................59

23.5

RIPOSIZIONAMENTO DI FILE SEQUENZIALI .........................59

23.6

LETTURA FILE DIRETTO.............................................................60

23.7

SCRITTURA FILE DIRETTO.........................................................60

23.8

FILE INTERNI .................................................................................60

23.9

RICHIESTA CARATTERISTICHE DI UN FILE...........................61

24.

INCLUSIONE DI FILE ........................................................................63

25.

BIBLIOGRAFIA ..................................................................................63

vi

INDICE

A.

APPENDICE – FUNZIONI INTRINSECHE STANDARD ................... 64

B.

PICCOLA APPENDICE SUL CALCOLO NUMERICO ....................... 71

SET DI CARATTERI

1

1. SET DI CARATTERI Il FORTRAN 77 standard riconosce solamente i seguenti caratteri: A-Z 0-9 + - * / = ( ) , . ' $ : spazio I caratteri minuscoli sono accettati dallo standard solo nei commenti e nella stampa di un testo. Attualmente tutti i compilatori considerano i caratteri minuscoli come equivalenti ai maiuscoli e alcuni di essi accettano anche il carattere " (doppi apici) come delimitatore di stringhe costanti. I restanti caratteri (fra i quali ! # & _) in genere possono essere utilizzati per i valori delle variabili e delle costanti di tipo stringa, oltre che per i commenti, ma ciò dipende dal compilatore. La letteratura consiglia di scrivere le keyword del linguaggio (GOTO, READ, IF, DO, ecc.) in maiuscolo, i nomi delle costanti in minuscolo e i nomi delle variabili con la prima lettera (ed eventuali lettere intermedie) maiuscola (es. Somma, SommaTotale).

2. PARSING Gli spazi non facenti parte di stringhe vengono ignorati e servono solo per aumentare la leggibilità del programma, ad esempio ‘GOTO’, ‘GO TO’ e ‘G OTO’ sono equivalenti, ma il terzo è poco leggibile. Si sconsiglia di suddividere un identificatore in più parti o su più righe. Per quanto detto, la dichiarazione INTEGER Prima Seconda dichiara la variabile PrimaSeconda e non le due variabili Prima e Seconda.

3. ETICHETTE (LABEL) Servono per identificare (“etichettare”) univocamente una linea di codice. Una label è costituita da un numero intero compreso tra 1 e 99999. Le label devono avere tutte valori diversi e ogni riga può averne al massimo una. Non devono essere utilizzate per identificare le righe di continuazione. Sono visibili solo dall’interno del modulo attuale (principale o sottoprogrammi). Possono essere

2

FORMATO DEL CODICE SORGENTE

assegnate senza un ordine preciso, ma è utile e consueto assegnarle in ordine crescente non consecutivo (10, 20, 30, ecc., in modo che si possano eventualmente aggiungerne altre intermedie senza venir meno all’ordine crescente). La letteratura consiglia di incolonnarle a destra alla quinta colonna.

4. FORMATO DEL CODICE SORGENTE Il codice FORTRAN deve sottostare a delle regole di posizione, il contenuto delle colonne del codice sorgente è il seguente: 1 se vi è presente il carattere ‘C’ o ‘*’, tutta la riga è ignorata in fase di compilazione e può essere usata come commento. I commenti terminano a fine riga 1-5 collocazione dell’eventuale label (una riga di commento non può averla) 6 un carattere in questa colonna indica che la riga è la continuazione della riga precedente. Il carattere viene ignorato, ma non deve essere né uno spazio né uno zero, di solito è un ‘+’, un ‘*’ o un ‘&’. Ogni istruzione può avere al massimo 19 righe di continuazione. Se queste sono più di una, vengono talvolta usati come caratteri di continuazione le cifre da ‘1’ a ‘9’ 7-72 colonne riservate a contenere le istruzioni. Si consiglia di non mettere più di un’istruzione per riga e di indentare il codice per facilitarne la leggibilità. E’ sconsigliato l’uso dei caratteri TAB 73-80 i caratteri scritti in queste colonne vengono ignorati (tali colonne erano utilizzate per scrivere a mano sulla scheda perforata)

5. IDENTIFICATORI Sono i nomi degli oggetti creati: variabili, costanti, nomi di funzioni e subroutine, nomi di programmi. Un identificatore non può essere utilizzato contemporaneamente per più oggetti (ad esempio sia per una variabile che per un sottoprogramma). Anche le keyword del linguaggio (GOTO, END, IF, ecc.) non sono riutilizzabili (sono “riservate”). Ogni identificatore può essere costituito al massimo da 31 caratteri (il primo deve essere una lettera, gli eventuali successivi possono essere lettere e cifre). Lo standard afferma che solo i primi

INIZIO DEL PROGRAMMA PRINCIPALE

3

6 caratteri sono significativi (gli altri sono utili per migliorare la leggibilità del programma), ossia se l’identificatore è composto da più di 6 caratteri, quelli dopo il sesto vengono ignorati (e quindi Valore1 e Valore2 sono la stessa variabile). Spesso i compilatori recenti accettano più di 6 caratteri significativi.

6. INIZIO DEL PROGRAMMA PRINCIPALE Il modulo principale di ogni programma dovrebbe sempre iniziare con l’istruzione PROGRAM nome dove nome è un identificatore. In realtà per lo standard è facoltativo, ma molti compilatori lo richiedono.

7. VARIABILI I nomi delle variabili sono identificatori ed è consuetudine scriverli con la prima lettera (ed eventualmente altre significative) maiuscola (es. Somma, SommaTot, ecc.). Hanno come scope (campo di visibilità, dove possono essere utilizzate) il solo modulo dove sono definite (principale o procedure). Per renderle visibili ad altri moduli si usa l’istruzione COMMON (vedasi sezione 21, pag. 39). E’ buona pratica commentare in sede di definizione il contenuto futuro delle variabili qualora questo non sia ovvio.

8. COSTANTI I nomi delle costanti sono identificatori ed è consuetudine scriverli tutti in minuscolo. Vengono valutate al momento della compilazione. Per dare un nome ad una costante (numerica o no) si usa l’istruzione: PARAMETER (nome=expr, nome1=expr1, …) Il tipo di nome o viene dichiarato precedentemente come se fosse la definizione di una variabile o vengono utilizzate le dichiarazioni implicite. expr può

4

TIPI DI DATI

contenere solo valori costanti e nomi di costanti definite nello stesso modulo con la stessa o con altre istruzioni PARAMETER. PARAMETER deve essere collocata prima delle eventuali istruzioni DATA. Esempio REAL pigreco, eulero PARAMETER (pigreco = 3.14, eulero = 2.71E+0) Le costanti possono essere usate nella dichiarazione delle dimensioni di array e matrici. Esempio INTEGER n PARAMETER (n=10) DIMENSION Var1(n) REAL Var2(n) Per le costanti stringa il valore deve essere messo tra apici: CHARACTER*5 pianeta PARAMETER (pianeta = 'Terra')

9. TIPI DI DATI Il tipo delle variabili e delle costanti può essere determinato automaticamente dal compilatore (“dichiarazione implicita”) o definito dal programmatore (“dichiarazione esplicita”). Nella dichiarazione implicita il tipo delle variabili e delle costanti non dichiarate viene determinato considerando la prima lettera dell’identificatore: Prima lettera da I a N da A ad H e da O a Z

Tipo della variabile o costante INTEGER REAL

TIPI DI DATI

5

La dichiarazione implicita può essere modificata con l’istruzione IMPLICIT che deve essere collocata prima della dichiarazione delle variabili: IMPLICIT tipo (lettera1, lettera2, lettera3-lettera4, …), (…),… Questa istruzione fa sì che, per le variabili non dichiarate che iniziano con le lettere elencate tra parentesi, il tipo sia quello indicato da tipo; il trattino definisce un intervallo di valori (range). Esempi IMPLICIT INTEGER*2 (A,B), COMPLEX (C) IMPLICIT INTEGER*4 (D-K), LOGICAL(L) IMPLICIT REAL*8 (M-O,Q,T) Le dichiarazioni implicite sono sconsigliabili e per disabilitarle molti compilatori dispongono dell’istruzione non standard IMPLICIT NONE, da collocare subito dopo l’istruzione PROGRAM; questa istruisce il compilatore affinché non proceda alla compilazione se trova qualche variabile non è dichiarata esplicitamente. IMPLICIT non cambia il tipo delle funzioni intrinseche. La dichiarazione esplicita ha la forma seguente: tipo[*dim1] var[*dim2], var[*dim3], ... Per la lunghezza delle variabili esiste un valore di default (in byte o caratteri) che dipende dal tipo, questo valore può essere ignorato se è presente un dimensionamento esplicito. Se dim1 viene indicata, essa prevale sulla dimensione di default di tipo e viene applicata a tutte le variabili della lista prive di dimensione esplicita; dim2 e dim3 sono dimensioni esplicite e si riferiscono ciascuna alla sola variabile che seguono, se sono indicate prevalgono sia sulla dimensione di default che su dim1. La dichiarazione esplicita prevale sull’implicita: se una variabile viene dichiarata di un certo tipo, il tipo implicito non viene considerato. Notazione Nel seguito con var-list si indicherà un elenco di nomi di variabili (identificatori) separati da virgole, per ciascuno di questi è possibile indicare la lunghezza (numero di byte in cui verrà memorizzato il valore) come indicato: var1[*dimensione1], var2[*dimensione2], ...

6

TIPI DI DATI

9.1 INTEGER Sono valori interi memorizzati in complemento a due su 2 o 4 byte (in genere corrisponde alla word della macchina). COSTANTI: sequenze di cifre senza punto decimale ed eventualmente precedute dal segno “+” o “-”. VARIABILI: possono essere di 2 o 4 byte (se non è specificato, la scelta viene fatta dal compilatore), implicitamente sono di questo tipo le variabili la cui lettera iniziale è compresa tra I ed N (anche in questo caso la lunghezza viene scelta dal compilatore). INTEGER var-list INTEGER*2 var-list INTEGER*4 var-list INPUT/OUTPUT: si usano i descrittori di campo I, O e Z. 9.2 REAL Valori reali memorizzati in formato floating point (in genere IEEE P754) su 4 o 8 byte. REAL e REAL*4 (4 byte) sono sinonimi e hanno:  8 bit di esponente, intervallo di valori: [2-127, 2+127], circa [10-38, 10+38]  23 bit di mantissa, precisione: 2-23, circa 7 cifre decimali REAL*8 (8 byte) coincide con DOUBLE PRECISION (vedasi 9.3, pag. 7). COSTANTI: numeri con punto decimale e/o in notazione esponenziale (es. 3.1415, +3.1E+03). L’eventuale esponente deve essere intero. Se il modulo del numero è compreso tra zero e uno (estremi esclusi) si può tralasciare lo zero prima del punto (es. .02). Se il numero (diverso da zero) ha parte decimale nulla le cifre zero dopo il punto decimale possono essere tralasciate (es. 10. ). VARIABILI: possono essere memorizzate su di 4 o 8 byte, implicitamente sono di questo tipo le variabili la cui lettera iniziale è compresa tra A-K e O-Z. REAL var-list REAL*4 var-list REAL*8 var-list INPUT/OUTPUT: si usano i descrittori di campo E, F, D e G. CALCOLI: le funzioni intrinseche di solito hanno il nome che inizia con la lettera A.

TIPI DI DATI

7

9.3 DOUBLE PRECISION Coincidono con i REAL*8 (è preferibile usare DOUBLE PRECISION). Rispetto ai REAL*4, i 4 byte in più sono usati tutti per estendere la mantissa, si hanno quindi:  8 bit di esponente, intervallo di valori: [2-127, 2+127], circa [10-38, 10+38]  55 (23+4*8) bit di mantissa, precisione: 2-55, circa 16 cifre decimali COSTANTI: sono scritte in notazione esponenziale con D al posto di E (es. +3.14D+00). VARIABILI: è tipico far iniziare i nomi delle variabili con la lettera D. DOUBLE PRECISION var-list INPUT/OUTPUT: si usano i descrittori E, F, G, D. Vengono stampate in notazione esponenziale con la lettera D al posto della lettera E. Per non perdere di precisione nella stampa si può usare il formato E21.14. CALCOLI: le funzioni intrinseche intrinseche di solito hanno il nome che inizia con la lettera D. 9.4 COMPLEX Sono costituite da due parti, entrambe di tipo REAL*4, corrispondenti la prima alla parte reale (e) del numero, la seconda a quella immaginaria (m). Nella memoria le due parti sono immagazzinate consecutivamente. COSTANTI: vengono scritte tra parentesi: (e, m), esempio: (12.3,3.11) VARIABILI: è tipico far iniziare i nomi delle variabili con la lettera C. COMPLEX var-list INPUT (list directed): chiede in lettura 2 REAL. OUTPUT (list directed): vengono stampate nella forma (e, m). INPUT (formatted): vengono letti due REAL (corrispondenti a parte e e parte m) con un solo descrittore di campo F. OUTPUT (formatted): si usano 2 descrittori di campo F, con il primo viene stampata la parte reale, con il secondo la parte immaginaria. CALCOLI: i calcoli tra numeri complessi danno risultati complessi. Le funzioni intrinseche di solito hanno il nome che inizia con la lettera C.

8

TIPI DI DATI

9.5 LOGICAL Tipo logico (o booleano). COSTANTI: sono i due valori .TRUE. e .FALSE. VARIABILI: possono essere specificate di lunghezza pari a 1, 2 o 4 byte, il contenuto è sempre costituito dai valori .TRUE. e .FALSE., LOGICAL e LOGICAL*1 coincidono. LOGICAL var-list INPUT (list directed): si deve introdurre una stringa il cui primo carattere non blank sia ‘T’ o ‘F’. OUTPUT (list directed): stampa il carattere ‘T’ o ‘F’. INPUT/OUTPUT (formatted): si usa il descrittore di campo L. CONFRONTO: si devono usare .EQV. e .NEQV. (non .EQ. e .NE. che confrontano invece valori numerici). 9.6 CHARACTER Le sequenze di caratteri sono dette stringhe. COSTANTI: si scrivono tra apici, ad esempio 'ABCDE', per includere un apice lo si deve raddoppiare (es. 'Perche'' no'). VARIABILI: si deve normalmente indicarne la lunghezza perché di default è pari a 1. CHARACTER [*lunghezza] var-list Tutte le variabili della lista sono composte da lunghezza caratteri (a meno che le singole variabili non specifichino per se stesse una lunghezza diversa). Si accede ai singoli caratteri con la notazione Var(i:i) (i-esimo carattere di Var). Esempi CHARACTER Var*100 definisce la variabile Var di tipo CHARACTER (ossia una stringa) composta da 100 caratteri. CHARACTER Var(100) definisce l’array Var di 100 elementi di 1 carattere ciascuno (non è una stringa di 100 caratteri), si accede ad ogni elemento con la notazione Var(I) (i-esimo elemento di Var).

TIPI DI DATI

9

CHARACTER*5 Var*4, Bar(10), Zar(6)*8 definisce Var come stringa composta da 4 caratteri, Bar come array di 10 stringhe di 5 caratteri ciascuna e Zar come array di 6 stringhe di 8 caratteri. Il 3o carattere della 4a stringa di Zar è: Zar(4)(3:3). INPUT (list directed): legge una sequenza di caratteri che deve essere introdotta racchiusa tra apici. Se la stringa in lettura è costituita da un numero di caratteri maggiore della lunghezza w della variabile stringa che deve contenerla, alla variabile vengono assegnati solo i w caratteri più a destra (troncamento a sinistra) della stringa letta; nel caso opposto si ha padding (riempimento) con spazi a destra. OUTPUT (list directed): stampa tutta la stringa (senza apici delimitatori) compresi gli eventuali spazi di padding. INPUT/OUTPUT (formatted): si usa il descrittore di campo A. CALCOLI: la libreria standard fornisce alcune funzioni intrinseche: INDEX (expr1, expr2) cerca expr2 all’interno di expr1 e ne dà la posizione di inizio (1 è il primo carattere); expr sono espressioni di tipo CHARACTER (variabili, costanti, ecc.) Esempio La sequenza delle due seguenti istruzioni cerca la seconda presenza di S2 in S1 (e ne memorizza l’indice in J ): K=INDEX (S1, S2) J=INDEX (S1(K+1:), S2) + K LEN (expr) dà la lunghezza in byte dell’espressione di tipo carattere expr (si noti che viene data la dimensione dello spazio occupabile massimo). 9.6.1 Sottostringhe Per definire una stringa a partire da un’altra stringa si usa la forma seguente: expr([expr1]:[expr2]) La sottostringa risultante è costituita dai caratteri di expr a partire dal carattere di indice expr1 (per default è il primo) e finendo con quello di indice expr2 (per default è l’ultimo). expr in genere è una variabile di tipo CHARACTER, ma può essere una costante o in generale un’espressione di tipo stringa; expr deve avere lunghezza maggiore o uguale della lunghezza della sottostringa.

10

VETTORI E MATRICI

Una sottostringa può essere usata come una normale variabile o costante di tipo CHARACTER (variabile o costante a seconda di che cosa sia expr). Le parti di una stringa che compaiono a sinistra del segno di assegnazione “=” non possono essere utilizzate nella stessa istruzione anche a destra (neppure all’interno di una funzione, come in Var(3:5) = FUNZ (Var(4:6)) ), in particolare se si copia da una stringa su se stessa mediante sottostringhe, le due porzioni della stringa non devono avere parti comuni. Esempi 'abcdef'(3:5) è la stringa costante 'cde' Se Var ='abcdefghi', allora l’istruzione Var(3:6)='XYZT' cambia Var in 'abXYZTghi'. Se Var ='abcdefghij', allora per l’istruzione Var(4:8)='XYZ', essendo il range specificato composto da 5 caratteri, si ha che 'XYZ' viene prima esteso a 'XYZ' aggiungendo 2 spazi in fondo (padding) e poi assegnato, ottenendo 'abcXYZij'.

10. VETTORI E MATRICI Per l’inizializzazione vedasi 11.1, pag. 13. Per le di operazioni Input/Output vedasi 22.6, pag. 55. Le variabili multidimensionali possono avere al massimo 7 dimensioni. Per definire le dimensioni di un vettore (array) si può utilizzare uno dei seguenti metodi:  utilizzare la definizione di tipo esplicita dell’array e fornire contemporaneamente le dimensioni o i valori minimo e massimo degli indici (metodo consigliato): REAL Matrice(23,21),A(3),B(-3:2),R(2:3,-2:2)  utilizzare la definizione di tipo esplicita senza indicare le dimensioni oppure utilizzare quella implicita; in entrambi i casi poi indicare le dimensioni con l’istruzione DIMENSION (da collocare prima delle istruzioni DATA e di quelle eseguibili): INTEGER A REAL Matrice, B, R DIMENSION Matrice(23,21),A(3),B(-3:2),R(2:3,-2:2)

11

VETTORI E MATRICI 

sfruttare la definizione delle COMMON: REAL A COMMON /BLOCCO/A(15) Le dimensioni e i valori minimo e massimo degli indici devono essere espressioni costanti. E’ possibile specificare l’intervallo di valori che gli indici possono assumere (di default partono da 1) con la notazione: tipo var(indice-min:indice-max) Esempio REAL Vettor(-3:6) definisce un vettore di 10 elementi con indice compreso tra -3 e +6. La letteratura consiglia di non interporre spazi tra il nome della variabile e la parentesi, mentre in tutti gli altri casi (ad esempio dopo i nomi delle istruzioni, dei sottoprogrammi, ecc.) consiglia di metterlo per un più agevole riconoscimento visivo. I valori sono collocati in memoria sequenzialmente per colonne, questo significa che ad esempio gli elementi di una matrice Mat di dimensioni 22 vengono memorizzati nell’ordine: Mat(1,1), Mat(2,1), Mat(1,2), Mat(2,2). Più in generale, per una variabile con più indici l’ordine di memorizzazione fisico è quello secondo cui il primo indice è quello che varia più velocemente. L’accesso in sequenza agli elementi in questo ordine risulta in genere più veloce perché ottimizzato dal compilatore. Per lo stesso motivo nel caso seguente vengono inizializzate due colonne al valore 1 e altre 2 al valore 2: DIMENSION A(5,4) DATA A/10* 1.0, 10* 2.0/ 1.0 1.0 1.0 1.0 1.0

1.0 1.0 1.0 1.0 1.0

2.0 2.0 2.0 2.0 2.0

2.0 2.0 2.0 2.0 2.0

12

INIZIALIZZAZIONE DELLE VARIABILI

11. INIZIALIZZAZIONE DELLE VARIABILI Per vettori e matrici si veda 11.1, pag. 13. Le variabili non inizializzate espressamente hanno valori indefiniti. Le variabili (di qualsiasi tipo) possono essere inizializzate nei modi seguenti. 1. Nella definizione di tipo (non si può utilizzare per le variabili COMMON): tipo var /valore/ Esempi INTEGER IVett(3) /1,2,3/ REAL RVett(3) /1.0,2.0,3.0/ Si possono usare i moltiplicatori come abbreviazione. Esempi REAL Vettore(200) /200 * 0.0/ Inizializza a 0 i 200 elementi di Vettore. CHARACTER*20 Nome /20 * ' '/ Inizializza con 20 spazi la variabile Nome. 2. Con l’istruzione DATA: DATA var1/valore1/, var2/valore2/, … DATA var3,var4, …/val3,val4, …/[,[/]]varx,…/valx,…/ Esempi INTEGER A, B, C, D, E, F(4) LOGICAL FLAG DATA A/5/, B/4/ DATA C,D,E/4,2,2/, F/5,7,2,4/ DATA FLAG/.TRUE./ Nel caso di variabili COMMON, l’istruzione DATA può comparire solo all’interno del apposito modulo BLOCK DATA (vedasi 21.3, pag. 41).

INIZIALIZZAZIONE DELLE VARIABILI

13

11.1 INIZIALIZZAZIONE DI VETTORI E MATRICI Gli elementi non espressamente inizializzati hanno valore indefinito. I modi possibili di usare l’istruzione DATA per inizializzare matrici (e più in generale variabili multidimensionali) sono i seguenti: 1. vengono assegnati i singoli elementi: DATA Var(1), Var(2), … /n*valore/, … essendo n il numero di elementi di Var che si vogliono inizializzare tutti a valore. 2. Vengono assegnati alcuni valori (o tutti) con una “implicit DO list”: DATA (var(ind)[,var(ind+costante)]...,ind=m1,m2[,m3])/n*valore/,... essendo n il numero di elementi di var (a partire dal primo) che si vogliono inizializzare tutti a valore. n e l’indice ind sono valori interi. m1, m2, m3 sono il valore iniziale, quello finale e l’incremento (come per i cicli DO, salvo che qui essi devono essere necessariamente espressioni costanti di tipo intero e m3 deve essere positivo). Se la variabile indice ind viene utilizzata anche in altri punti del programma, il valore che ha prima del ciclo non viene modificato dall’esecuzione del ciclo stesso1, questo non accade per i cicli impliciti normali. Esempio I=78 DATA (Somma(I), Somma(I+1), I=1,7,3) /6*4.0/ inizializza a 4.0 gli elementi: Somma(1), Somma(2), Somma(4), Somma(5), Somma(7), Somma(8). Gli altri elementi hanno valore indefinito. Il valore di I dopo la DATA continua ad essere 781. 3. Vengono assegnati gli elementi dell’intero array (o la parte iniziale):  ad un unico valore: DATA array /dimensione*valore/ dove dimensione è il numero di elementi di array che si vogliono inizializzare (a partire dal primo)  a valori diversi, indicati uno per uno: DATA array / val1, val2, …/ 1

Questo è quanto afferma lo standard, ma molti compilatori non rispettano affatto la regola.

14

ASSEGNAZIONI In entrambi i casi, se vengono forniti meno valori di quanti sono gli elementi dell’array, vengono inizializzati solo i primi, mentre i restanti continuano ad essere indefiniti.

12. ASSEGNAZIONI Le assegnazioni avvengono con la seguente sintassi: var = expr var è il nome di una variabile (con l’eventuale indicazione degli indici se si tratta di elemento di un vettore o di una matrice; es. Var(2), Stringa(3:6)). expr è un’espressione e può contenere variabili, costanti e chiamate a funzioni. Per le variabili numeriche, se il tipo di var e quello di expr sono diversi si ha una conversione del risultato nel tipo di var. La conversione da tipo reale a tipo intero avviene per troncamento della parte frazionaria. Esempi Var Var Var Var Var

= = = = =

-12 21. + (2*Variab) Variab .TRUE. 'abcdef'

Per le stringhe, nel caso dell’istruzione A=B, essendo lenA il numero di caratteri di A e lenB quello di B, si hanno i seguenti casi:  lenA = lenB tutti i caratteri di B vengono assegnati ad A,  lenA > lenB prima dell’assegnazione si ha il padding a destra di B con (lenA - lenB) spazi (non viene modificato il contenuto di B, ma una sua copia temporanea in memoria)  lenA < lenB vengono assegnati ad A solo i primi lenA caratteri di B Esempi CHARACTER Var*4 Var = 'a'  assegna 'a ' a Var (padding di spazi spazi a destra) Var = 'abcdef'  assegna 'abcd' a Var (il resto è ignorato).

OPERAZIONI

15

Se Var='abcdefghij', allora per l’istruzione Var(4:8)='XYZ', essendo il range specificato composto da 5 caratteri, si ha che 'XYZ' viene prima esteso a 'XYZ ' aggiungendo 2 spazi in fondo (padding) e poi assegnato, ottenendo 'abcXYZ ij'. 12.1 ASSIGN ASSIGN label TO var-intera Questa istruzione permette di usare var-intera al posto di label nelle FORMAT e nelle istruzioni ASSIGNED GOTO (vedasi 14.3, pag. 21) Dopo la ASSIGN, var-intera non può più essere utilizzata in espressioni aritmetiche in quanto non contiene il valore numerico di label, ma un valore che dipende dal compilatore. La dimensione di var-intera (il numero di byte) limita il numero di valori diversi che le possono essere assegnati: ad es. a una variabile di tipo INTEGER*2 possono essere assegnati fino a 22*8-1=32768 valori diversi. Esempio INTEGER FINE ASSIGN 2510 TO FINE

13. OPERAZIONI Le espressioni che continuano su più righe è bene siano indentate per riconoscerle visivamente subito come righe di continuazione. Il troncamento consiste semplicemente nel tralasciare le cifre decimali. L’arrotondamento si ha al valore precedente se la prima cifra da omettere è inferiore a 5, al valore successivo se maggiore o uguale a 5: 3.123456 viene arrotondato a: 3, 3.1, 3.12, 3.123, 3.1235, 3.12346 e 3.123456 a seconda delle cifre decimali volute per il numero finale.

16

OPERAZIONI

13.1 OPERAZIONI ARITMETICHE 13.1.1 Priorità La priorità degli operatori indica l’ordine di calcolo delle operazioni in un’espressione. Segue l’elenco delle operazioni secondo priorità decrescente: ( ) raggruppamento con parentesi ** potenza2 * / moltiplicazione e divisione3 + somma e sottrazione 13.1.2 Associatività Indica come vengono raggruppate le operazioni aventi la stessa priorità. ** da destra a sinistra: A**B**C equivale a A**(B**C) * / + - da sinistra a destra: A+B-C equivale a (A+B)-C 13.1.3 Tipo del risultato Le operazioni tra interi danno risultati intermedi interi (ottenuti per troncamento). In un’espressione possono essere presenti costanti e variabili numeriche di tipo diverso (“mixed mode”), in questo caso i tipi meno precisi vengono automaticamente promossi al tipo più preciso presente nell’espressione in modo da poter fare i calcoli solo con valori del tipo più preciso; il tipo del risultato è quello dell’operando più preciso. La promozione di tipo avviene solo nel momento in cui si deve fare un’operazione i cui due operandi sono di tipo diverso, cioè nei calcoli intermedi si ha la promozione solo quando serve: (5/2)*4.0 dà come risultato 8.0 e non 10.0 perché la divisione avviene tra interi e il risultato di essa è 2 e non 2.5, poi questo viene promosso a reale e infine moltiplicato per 4.0. Si faccia anche attenzione agli errori di approssi2

La potenza baseesponente con esponente reale è calcolata come: EXP(esponente*LOG(base)) quindi se base è negativa si ha errore. Però se esponente ha valore intero si può usare per esso il tipo intero, questo fa sì che la potenza venga calcolata con moltiplicazioni e non ci siano errori. 3 La divisione intera tronca la parte decimale del risultato.

OPERAZIONI

17

mazione: ad esempio assegnando il risultato di 30.0/0.1 ad una variabile intera, su alcune macchine si potrebbe in realtà assegnare 299 e non 300. Se uno degli elementi è COMPLEX e l’altro è INTEGER o REAL, il secondo viene trasformato in COMPLEX con parte immaginaria pari a 0. Non si possono avere nella stessa espressione valori sia COMPLEX che DOUBLE PRECISION.

13.2 OPERAZIONI SU STRINGHE // concatenazione Gli operandi devono essere variabili o costanti di tipo CHARACTER, non possono essere nomi di array, ma possono essere elementi di array. Esempio CHARACTER*10 Var, Nome*4/'EFGH'/, Arr(2)*4, Brr(4)*4 Var = 'ABCD' // Nome Arr(1) = 'AB'//'CD' Var = Arr//Brr  Esempio non corretto: sono array, non stringhe 13.3 ESPRESSIONI RELAZIONALI Sono espressioni di confronto tra operandi entrambi numerici o stringhe, il risultato è sempre di tipo LOGICAL. Gli operatori sono: .LT. Less Than .LE. Less or Equal than .EQ. EQual to .NE. Not Equal to .GT. Greater Than .GE. Greater or Equal than Esempio Var = PIGRECO .NE. EULERO

18

OPERAZIONI

E’ meglio non fare confronti fra espressioni aritmetiche di tipo diverso: è più sicuro farne prima una conversione esplicita di tipo. Per evitare problemi di approssimazione, è meglio non usare né .EQ. né .NE. fra espressioni floating point, ma calcolarne la differenza in valore assoluto e confrontare il risultato con un valore sufficientemente piccolo (indicante la precisione). 13.3.1 Confronto tra caratteri Il confronto tra caratteri avviene secondo le seguenti regole:  le lettere maiuscole sono ordinate alfabeticamente e costituiscono un insieme ordinato detto collating sequence  le cifre sono ordinate numericamente e costituiscono un’altra collating sequence; sono collocate o tutte prima o tutte dopo le lettere maiuscole (lo standard non dice dove sono collocate rispetto alle lettere)  lo spazio precede sia le lettere sia le cifre  per gli altri caratteri, lettere minuscole incluse, secondo lo standard il comportamento è indefinito, in pratica dipende dal codice utilizzato dalla macchina (ASCII o EBCDIC) Lo standard garantisce la possibilità di confrontare tra loro solo i caratteri appartenenti alla stessa collating sequence oltre allo spazio; in realtà la maggior parte dei compilatori considera il codice usato dalla macchina (ASCII o EBCDIC) come un’unica (e la sola esistente) collating sequence. 13.3.2 Confronto tra stringhe Il confronto tra stringhe avviene secondo le seguenti regole:  la stringa più corta viene estesa a destra con degli spazi fino ad avere la stessa lunghezza di quella più lunga  le due stringhe vengono confrontate carattere per carattere da sinistra a destra fino a incontrare una differenza o a raggiungerne la fine  se c’è differenza tra due caratteri nella stessa posizione delle due stringhe, la relazione tra i due caratteri diversi è il risultato finale del confronto delle due stringhe  altrimenti le stringhe sono uguali

19

OPERAZIONI

Se per ragioni di portabilità del codice si vuole considerare l’ordine di tutti i caratteri secondo il codice ASCII (indipendentemente da quello utilizzato dalla macchina), si possono utilizzare le funzioni intrinseche seguenti: LGE(C1,C2) equivale a (C1 .GE. C2) su una macchina ASCII LGT(C1,C2) equivale a (C1 .GT. C2) su una macchina ASCII LLE(C1,C2) equivale a (C1 .LE. C2) su una macchina ASCII LLT(C1,C2) equivale a (C1 .LT. C2) su una macchina ASCII 13.4 ESPRESSIONI LOGICHE Gli operandi e il risultato devono essere di tipo LOGICAL. Gli operatori, elencati con priorità decrescente, sono i seguenti: .NOT. .AND. .OR. .EQV. stessa priorità .NEQV.

}

.NOT. X X .AND. Y X. OR. Y X .EQV.Y X .NEQV. Y

dà risultato opposto a quello di X dà risultato .TRUE. se sia X che Y sono .TRUE. dà risultato .TRUE. se almeno uno tra X e Y è .TRUE. (EQuiValenza) dà risultato .TRUE. se entrambi gli operandi hanno lo stesso valore logico (funzione logica EX-NOR) (Non EQuiValenza) dà risultato .TRUE. se gli operandi hanno valore logico diverso (funzione logica EX-OR)

20

ISTRUZIONI DI SALTO

13.5 CALCOLO DELLE ESPRESSIONI Nell’ordine vengono valutati4: 1. i calcoli matematici 2. le espressioni relazionali 3. le espressioni logiche

14. ISTRUZIONI DI SALTO L’ordine naturale di esecuzione delle istruzioni di un programma è sequenziale, le istruzioni di salto permettono di far continuare l’esecuzione a partire da un altro punto. 14.1 GOTO INCONDIZIONATO Fa continuare l’esecuzione del programma dalla riga avente la label indicata. GOTO label Esempio GOTO 200 ... 200 istruzione 14.2 GOTO CALCOLATO L’esecuzione continua, secondo il valore di expr, a una delle righe indicate dalle label: GOTO (label-1, label-2, …), expr expr deve essere un espressione di tipo intero, se è compresa tra 1 e il numero di label presenti, il GOTO CALCOLATO è equivalente all’istruzione: GOTO label-i (essendo i il valore di expr) altrimenti è ignorato (passa alla linea successiva). 4

Diversamente dal linguaggio C, l’espressione .NOT. A.LT.B equivale a .NOT.(A.LT.B) perché prima vengono eseguiti i calcoli relazionali (.LT.) e poi quelli logici (.NOT.); inoltre non ha senso l’espressione (.NOT.A).LT.B in quanto A non è una variabile logica e .NOT. A non è quindi un valore numerico.

ESPRESSIONI CONDIZIONALI

21

Esempio GOTO (1250,1260,1270,1280), 2*A Se A vale 1, l’esecuzione passa alla riga con label 1260 Questa istruzione esiste per compatibilità con vecchie versioni di FORTRAN, ne è sconsigliato l’uso. 14.3 ASSIGNED GOTO L’esecuzione continua alla riga la cui label è stata assegnata alla variabile intera var per mezzo dell’istruzione ASSIGN. GOTO var [,(label1, label2, …)] Se la lista di label esiste viene fatto il controllo che il valore di var sia uno di quelli elencati. Esempio INTEGER FINE ASSIGN 1250 TO FINE GOTO FINE, (1250,1260,1270) Questa istruzione esiste per compatibilità con vecchie versioni di FORTRAN, ne è sconsigliato l’uso.

15. ESPRESSIONI CONDIZIONALI 15.1 IF ARITMETICO L’esecuzione prosegue, a seconda del segno di expr, a una delle righe indicate dalle label: IF (expr) label-1, label-2, label-3 expr deve essere un’espressione di tipo numerico, si hanno i seguenti casi:  expr < 0 l’esecuzione prosegue alla riga avente label label-1  expr = 0 l’esecuzione prosegue alla riga avente label label-2  expr > 0 l’esecuzione prosegue alla riga avente label label-3 Questa istruzione esiste per compatibilità con vecchie versioni di FORTRAN, ne è sconsigliato l’uso.

22

ESPRESSIONI CONDIZIONALI

15.2 IF LOGICO Prima forma: IF (expr) istruzione Se expr è .TRUE. viene eseguita istruzione. expr deve essere un’espressione di tipo logico, istruzione deve essere eseguibile (non definizione di tipo, non CONTINUE, ecc.), escluse END, IF e DO. Seconda forma: IF (expr1) THEN blocco istruzioni ELSEIF (expr2) THEN blocco istruzioni ELSE blocco istruzioni ENDIF

} Parte opzionale ripetibile } Parte opzionale non ripetibile

Se expr1 è .TRUE. viene eseguito il solo primo blocco istruzioni, altrimenti se expr2 è .TRUE. viene eseguito il solo secondo blocco istruzioni, altrimenti viene eseguito l’ultimo blocco istruzioni. expr1 ed expr2 devono essere espressioni di tipo logico, blocco istruzioni non deve contenere END. Quando si hanno IF annidate, ogni ELSE è associata alla IF più vicina che la precede. Si può usare GOTO per uscire da un blocco istruzioni, ma non per entrarvi.

ESECUZIONI CICLICHE

23

16. ESECUZIONI CICLICHE Il FORTRAN 77 standard prevede solo cicli a conteggio, ovviamente i cicli condizionali possono essere realizzati mediante istruzioni IF e GOTO. I cicli a conteggio permettono di ripetere un determinato numero di volte l’esecuzione di un blocco di istruzioni. Una variabile tiene traccia del numero dell’iterazione corrente. Dove possibile, si preferiscano i cicli impliciti (vedasi 16.1, pag. 26) agli espliciti (quelli introdotti da DO) in quanto più efficienti.

label

DO label [,] var=expr1, expr2 [, expr3] blocco istruzioni CONTINUE

var è una variabile intera o reale detta indice (per evitare problemi nel calcolo del numero di iterazioni, è meglio che sia INTEGER) e mantiene il numero dell’iterazione corrente (in realtà è una funzione del numero di iterazione corrente, come spiegato al punto seguente); dentro blocco istruzioni il valore di var è utilizzabile, ma non modificabile. expr1, expr2, expr3 sono espressioni aritmetiche intere o reali, positive o negative e vengono convertite al tipo di var, corrispondono rispettivamente al valore iniziale, al valore finale e all’incremento (che per default vale 1) dell’indice var, non si devono modificare all’interno del blocco istruzioni (non ha comunque effetto). All’ingresso del ciclo viene calcolato il numero di iterazioni da eseguire: numero_iterazioni = intero( (expr2-expr1+expr3)/ expr3 ) Questo valore viene memorizzato internamente e quindi non può essere cambiato. Se il numero di iterazioni è minore o uguale a 0, blocco istruzioni non verrà eseguito, altrimenti verrà eseguito ad ogni iterazione. Ad ogni iterazione idealmente si ha: 1. confronto dell’indice con il valore finale: se var > expr2 il blocco istruzioni non viene eseguito e le operazioni continuano dopo l’istruzione CONTINUE (questo dal punto di vista logico, in realtà internamente viene confrontato il numero di iterazioni eseguite con quello totale da eseguire), 2. esecuzione del blocco istruzioni, 3. incremento della variabile indice var del valore expr3, 4. ritorno al punto 1.

24

ESECUZIONI CICLICHE

Esempio DO 10 I=1,10 WRITE (*,*) I 10 CONTINUE Il ciclo viene eseguito 10 volte e vengono stampati i numeri da 1 a 10. Alla fine del ciclo, il valore finale di var non è uguale a expr2 ma a: expr1 + numero_iterazioni * expr3 Se invece si interrompe il ciclo uscendo dal blocco istruzioni per effetto di un GOTO, il valore attuale di var non viene modificato. Non si deve entrare in un blocco istruzioni con un GOTO, ma si può uscirne. Esempi DO 10 I=1,10 PRINT *, I 10 CONTINUE Al termine del ciclo, dopo la CONTINUE, il valore di I sarà 11. DO 10 I=1,50,2 PRINT *, I 10 CONTINUE Esegue 25 iterazioni, dopo la CONTINUE il valore di I sarà 51. DO 10 I=1,10 IF (I .EQ. 3) GOTO 20 10 CONTINUE 20 ... Qui il ciclo termina per effetto del GOTO, il valore di I alla riga 20 è 3. CONTINUE è un’istruzione non eseguibile, identifica semplicemente la fine del ciclo. La stessa CONTINUE può chiudere più cicli se questi sono annidati (i DO avranno quindi la stessa label).

25

ESECUZIONI CICLICHE Esempio DO 10 I=1,10 DO 10 J=6,42 DO 10 K=78,110 blocco istruzioni 10 CONTINUE

CONTINUE può essere omessa se la label viene associata all’ultima istruzione del blocco istruzioni, questa però non deve essere: PROGRAM, STOP, END, GOTO, DO, IF, ENDIF, RETURN o DO. Si può utilizzare CONTINUE non solo per i cicli, ma anche come istruzione fittizia con il solo scopo di definire una label (vedasi l’esempio per il ciclo WHILE più avanti). Alcuni compilatori accettano le seguenti forme non standard:  Ciclo a conteggio DO var=expr1, expr2 [, expr3] blocco istruzioni ENDDO Equivale al ciclo DO classico, non fa uso di label e la fine del ciclo viene identificata dalla keyword ENDDO 

Ciclo condizionale di tipo WHILE DO WHILE (expr) blocco istruzioni ENDDO Il blocco istruzioni viene eseguito fintanto che l’espressione logica expr continua ad essere vera.

La letteratura consiglia anche le seguenti strutture per simulare i cicli condizionali: Ciclo WHILE label1 IF (.NOT. condizione) GOTO label2 blocco istruzioni GOTO label1 label2 CONTINUE Fintanto che condizione è vera viene eseguito il ciclo.

condiz

blocco istruzioni

26 Ciclo REPEAT-UNTIL o DO-WHILE label1 CONTINUE blocco istruzioni IF (.NOT. condizione) GOTO label1 Quando condizione diventa vera si esce dal ciclo.

ESECUZIONI CICLICHE

blocco istruzioni condiz

16.1 CICLI IMPLICITI Un ciclo implicito ha come effetto il far ripetere più volte l’azione dell’istruzione che lo contiene (l’operazione viene considerata effettuata una sola volta, ad es. la WRITE non va a capo dopo ogni iterazione, ma solo dopo averle eseguite tutte), incrementando l’indice. E’ il metodo principale per leggere e scrivere i valori di vettori e matrici. ( expr, indice = expr1, expr2 [,expr3] ) expr è una generica espressione e può anche utilizzare indice, expr1, expr2 ed expr3 sono le stesse dei cicli DO espliciti. Esempi PRINT *, (Var(I), I=1,10) PRINT *, (Var(I*2)+3.14, I=1,10) PRINT *, ('abcd', I=1,10) tutte e tre le istruzioni stampano 10 quantità consecutivamente, senza andare a capo. I cicli impliciti non necessitano di CONTINUE; valgono le stesse considerazioni viste per il ciclo DO. Nel caso di inizializzazione con DATA di array e matrici (“implicit DO list”) ci sono restrizioni sulle expr, vedasi 11.1, pag. 13. 16.1.1 Annidamento I cicli impliciti possono essere annidati sul modello seguente: (...((expr, i1=p1,a1[,s1]), i2=p2,a2[,s2])...) essendo i gli indici (i1 varia più velocemente di tutti gli altri) p i valori di partenza a i valori di arrivo s i valori di incremento

TERMINE DELL’ESECUZIONE DEL PROGRAMMA

27

Esempio WRITE (*,100) ((Array(I,J), J=1,10), I=1,10) 100 FORMAT (1X, 10I7) il moltiplicatore (10) della specifica di formato della FORMAT specifica quanti valori scrivere sulla stessa riga prima di continuare la stampa a capo (vedasi sezione 22, pag. 42); in questo caso ogni 10 valori scritti va a capo (il ciclo di per sé li stamperebbe sulla stessa riga).

17. TERMINE DELL’ESECUZIONE DEL PROGRAMMA E’ necessario indicare il punto (o i punti) dove il programma deve terminare l’esecuzione. Questo si ottiene con l’istruzione eseguibile STOP: STOP ['messaggio'] STOP [numero-intero] numero-intero è costituito al massimo da 5 cifre.

18. TERMINE DI CIASCUN MODULO I moduli PROGRAM, FUNCTION, SUBROUTINE e BLOCK DATA devono terminare con END. Per le FUNCTION e le SUBROUTINE la END fa anche da RETURN. Per il PROGRAM fa anche da STOP. END è un’istruzione eseguibile. END

19. SOTTOPROGRAMMI Hanno scope globale (cioè sono visibili e richiamabili da tutti i moduli). E’ uso scriverli con la prima lettera maiuscola (es. Calcola, StampaSomma, ecc.). Non sono recursivi né direttamente né indirettamente. I parametri (o argomenti) indicati fra parentesi alla chiamata vengono detti attuali e possono essere espressioni sia costanti che variabili. I parametri indicati fra parentesi nella definizione del sottoprogramma (utilizzabili solo all’interno di esso) vengono detti parametri formali e possono esse-

28

SOTTOPROGRAMMI

re solo delle variabili, queste vengono dichiarate insieme alle variabili locali del sottoprogramma. Ogni parametro attuale all’atto della chiamata del sottoprogramma viene fatto corrispondere ad un parametro formale, quindi il numero dei parametri attuali deve essere uguale a quello dei parametri formali. Deve esserci coerenza tra i tipi dei parametri attuali e quelli dei parametri formali in quanto non c'è conversione automatica di tipo. Attenzione che le costanti numeriche intere (numeri, non le costanti definite con PARAMETER) hanno lunghezza che dipende dal compilatore, mentre i corrispondenti parametri formali possono avere lunghezza diversa, specificata nel sottoprogramma. Questo può generare un errore se si verificano contemporaneamente le seguenti condizioni:  il parametro attuale è un valore costante intero (un numero, non definito con PARAMETER)  il compilatore considera gli interi di lunghezza non specificata (costanti, risultati dei calcoli, variabili dichiarate INTEGER senza specificazione della lunghezza) come INTEGER*n  il parametro formale è definito nel sottoprogramma come INTEGER*m, con m diverso da n Il problema si risolve in uno dei seguenti modi: 1. dichiarando il parametro formale come INTEGER (senza lunghezza) 2. mettendo i parametri attuali in variabili (o costanti PARAMETER) di tipo uguale a quella dei parametri formali e poi passando le variabili (o costanti PARAMETER) 3. dando opportune direttive al compilatore (è però un metodo non standard e varia da compilatore a compilatore) I nomi dei parametri attuali e quelli dei corrispondenti formali possono essere (e tipicamente sono) diversi. I parametri attuali sono passati by reference (con il puntatore): le aree di memoria di un parametro attuale e del corrispondente formale sono coincidenti. Se il parametro attuale è una variabile, la modifica all’interno del sottoprogramma del parametro formale corrispondente si ripercuote sul parametro attuale stesso (metodo utilizzabile per restituire dei valori). Se possibile, i parametri siano passati raggruppati per scopo: quelli di input, quelli di output, quelli di controllo, tutti gli altri.

SOTTOPROGRAMMI

29

Per passare vettori e matrici se ne indica il nome senza parentesi nella lista degli argomenti; si possono passare contemporaneamente come parametri anche le loro dimensioni o i valori massimi e minimi degli indici (ciò è detto “dichiarazione di array modificabili”). Alternativamente le dimensioni possono essere contenute in variabili di un blocco COMMON del sottoprogramma. Esempio SUBROUTINE Nome (Vett, Dim) INTEGER Dim REAL Vett(Dim) All’interno di un sottoprogramma, nella definizione di tipo di un parametro formale multidimensionale (vettore, matrice, ecc.) si può mettere un ‘*’ al posto dell’ultima (o unica) dimensione o dell’indice massimo (ciò è detto “dichiarazione di array di dimensioni presunte”). In questo caso però un eventuale (dipende dal compilatore) controllo automatico sul non aver oltrepassato i limiti non viene effettuato. Esempio INTEGER Param1(3,2,*), Vett(*) Le variabili con indici definite in un sottoprogramma in modo presunto non possono essere utilizzate senza indici nelle liste di I/O, ad esempio in questo caso l’istruzione WRITE (*,*) Vett non è accettabile in quanto non si sa come Vett sia strutturata (in questo caso si può utilizzare un ciclo implicito). Gli array di caratteri di dimensioni presunte non possono essere utilizzati per contenere il formato di un’istruzione FORMAT (vedasi 22.3, pag. 44). Se la dimensione in byte dell’argomento formale è minore di quella dell’argomento attuale, vengono passati solo i primi byte dell’argomento attuale. Ad esempio se una matrice è definita come Mat(3,3,3) e nel sottoprogramma si ha: SUBROUTINE Sub (Mat) tipo Mx(3,3)

30

SOTTOPROGRAMMI

Qui il sottoprogramma utilizza la matrice Mx(3,3) costituita da una parte di Mat, più precisamente da Mat(3,3,1) perché questa è memorizzata per colonne (pratica sconsigliata perché poco chiara). Per le stringhe la lunghezza dell’argomento formale deve essere minore o uguale di quella dell’argomento attuale. Per rendere un sottoprogramma indipendente dalla lunghezza della stringa passatale, si può definire (nel sottoprogramma) la variabile carattere come segue: CHARACTER * (*) Var e si può poi usare la funzione intrinseca LEN() (vedi CALCOLI in 9.6, pag. 8) per calcolarne la lunghezza effettiva (la lunghezza con cui è stata definita la variabile stringa passata). Viene consigliato di mettere uno spazio tra il nome del sottoprogramma e la parentesi per distinguerla visivamente più facilmente da una variabile multidimensionale. 19.1 SUBROUTINE Definizione SUBROUTINE nome (var1, var2, …) tipo var1 tipo var2 tipo localvar1 .... RETURN END Chiamata CALL nome (arg1, arg2, …) Se non ci sono parametri non si mettono le parentesi né nella definizione né nella chiamata. Il risultato viene passato al modulo chiamante modificando (alcuni) argomenti della lista o modificando variabili COMMON.

SOTTOPROGRAMMI

31

19.2 FUNCTION Il FORTRAN permette al programmatore di scrivere delle funzioni, queste vengono dette anche esterne per distinguerle da quelle predefinite dette funzioni intrinseche (vedasi 19.8, pag. 35). Definizione [tipofunz] FUNCTION nome (var1, var2, …) tipo var1, var2, … tipo localvar1, localvar2, … ... nome = expr ... RETURN END Chiamata [tipofunz nome]  dichiarazione di tipo nel modulo chiamante ... nome (arg1, arg2, …) La chiamata di una funzione può comparire ovunque possa comparire un’espressione (es. Var=4*MiaFunz (A,B,C) ). In fase di definizione della FUNCTION, se tipofunz viene omesso vale il tipo implicito. Anche nel modulo chiamante deve esserci la dichiarazione di tipo della funzione (senza parentesi né argomenti, come fosse una variabile), altrimenti vengono utilizzate le dichiarazioni implicite. Se il tipo dichiarato nel modulo chiamante è diverso dal tipo indicato in sede di definizione della funzione, non essendoci conversione di tipo il risultato è scorretto. Il nome della funzione nel modulo chiamante è trattato come una normale variabile (nelle conversioni, nei calcoli, ecc.). Se la funzione deve restituire un valore di tipo CHARACTER e questo può avere dimensione varia, si può definire la funzione in questo modo: CHARACTER * (*) FUNCTION nome (arg…) e avere, nei moduli da dove viene chiamata, la dichiarazione: CHARACTER*dim nome dove la dimensione dim può essere diversa da modulo a modulo.

32

SOTTOPROGRAMMI

In una FUNCTION il risultato viene fornito per mezzo di nome e non si dovrebbero restituire risultati attraverso i parametri. Se non ci sono parametri da passare, si mettono comunque le parentesi sia nella definizione che nella chiamata. 19.3 FUNZIONI A SINGOLA ISTRUZIONE Le funzioni solo aritmetiche costituite da una sola istruzione possono essere definite senza ricorrere alla definizione di funzione con FUNCTION. Esempio PERIMETRO (Lato1, Lato2, Lato3) = Lato1+Lato2+Lato3 I nomi dei parametri sono fittizi: variabili con lo stesso nome non vengono modificate alla chiamata della funzione (questo afferma lo standard, in realtà i compilatori non sempre rispettano la regola). Il tipo dei parametri e delle funzioni può essere sia dichiarato esplicitamente che implicitamente. Lo scope è locale al modulo dove sono definite. Devono essere collocate dopo tutte le istruzioni di specificazione e prima di quelle eseguibili. Possono referenziare anche altre istruzioni a singola istruzione purché dichiarate precedentemente. Possono utilizzare funzioni esterne purché queste non modifichino il valore dei parametri attuali. Sono veloci ed efficienti. 19.4 PUNTI DI INGRESSO MULTIPLI Per entrare direttamente all’interno del codice di un sottoprogramma (SUBROUTINE o FUNCTION), iniziando da un’istruzione che non è la prima, si può usare l’istruzione ENTRY secondo il seguente schema:

}

SUBROUTINE nome1 (lista-param1) ... ENTRY nome2 (lista-param2) Sottoprog. ... nome2 END

}

Sottoprog. nome1

E’ come la definizione di un sottoprogramma, ma sfrutta parte del codice di un altro (i due sottoprogrammi, contenente e contenuto, sono o entrambi

SOTTOPROGRAMMI

33

FUNCTION o entrambi SUBROUTINE). La lista dei parametri può essere diversa, i nomi dei sottoprogrammi devono essere diversi. Questa istruzione esiste per compatibilità con le vecchie versioni di FORTRAN, se ne sconsiglia l’uso in quanto il programma risulta essere non più strutturato. 19.5 RITORNI ALTERNATIVI DA SOTTOPROGRAMMI CALL nome (var, var, *label-1, *label-2, …) ... SUBROUTINE nome (param, param, *, *, …) ... RETURN expr label-i sono le label presenti nel modulo chiamante (possono essere mescolate agli altri parametri (es. var1, *label-1, var2, var3, *label-2). expr è un’espressione di tipo intero di valore i compreso tra 1 e il numero di label presenti nella lista (altrimenti dà errore). RETURN expr esegue una RETURN seguita da una GOTO label-i. Questa istruzione esiste per compatibilità con le vecchie versioni di FORTRAN, se ne sconsiglia l’uso in quanto il programma risulta essere non più strutturato. 19.6 MANTENIMENTO DEI VALORI TRA LE CHIAMATE Uscendo da un sottoprogramma e rientrandovi, il valore delle variabili locali non lì inizializzate è normalmente indefinito. Per far sì che esse mantengano il loro valore da una chiamata all’altra si usa (prima delle dichiarazioni di tipo e dei DATA) l’istruzione: SAVE [var, var, …] Se la lista di variabili non è presente, vengono mantenuti i valori di tutte le variabili (esclusi i parametri formali). Le eventuali DATA presenti nel sottoprogramma vengono usate solo alla prima chiamata. Molti compilatori eseguono una SAVE automaticamente, ma si tratta di una caratteristica non standard.

34

SOTTOPROGRAMMI

Per le variabili COMMON si tenga presente il seguente esempio:  una SUBROUTINE (SubA) ne chiama un’altra (SubB) la quale a sua volta ne chiama una terza (SubC)  solo SubB e SubC hanno in comune una NAMED COMMON

PROGRAM

SubA

SubB

SubC COMMON

Quando l’esecuzione ritorna a SubA le variabili del blocco COMMON diventano indefinite e la memoria da esse occupata potrebbe essere rilasciata al sistema (molti compilatori invece di fatto mantengono i valori e quindi la memoria non viene liberata). Se l’intenzione è quella di mantenere le variabili del blocco COMMON, si possono adottare le seguenti soluzioni: 1. salvare tutte quante le variabili di un blocco con un’istruzione SAVE, questa deve essere presente in tutti i moduli che utilizzano quel blocco (nell’esempio si tratta di SubB e SubC) si noti che si mette il solo nome del blocco tra barre: SAVE Var1, /BLOCCO1/, Var2 2. si definisce il blocco anche nel modulo principale (anche se non viene lì utilizzata alcuna variabile del blocco). 19.7 PASSAGGIO DI NOMI DI FUNZIONE A SOTTOPROGRAMMI Per passare ad un sottoprogramma il nome di una funzione come parametro, è necessario che nel programma chiamante questo sia dichiarato con: INTRINSIC funzione, funzione, … per le funzioni intrinseche EXTERNAL funzione, funzione, … per quelle non intrinseche I nomi delle funzioni vengono indicati senza parentesi e parametri.

SOTTOPROGRAMMI

35

Esempio INTRINSIC ALOG ... CALL Subr (X, ALOG) ... SUBROUTINE Subr (A, Funz) EXTERNAL Funz ... Temp = Funz (A) Non possono essere passati ad un sottoprogramma i nomi delle funzioni intrinseche di conversione di tipo, di confronto stringhe, di ricerca di massimi e minimi. La dichiarazione EXTERNAL è facoltativa se il sottoprogramma viene poi utilizzato effettivamente come sottoprogramma (è evidente che un identificatore esterno collocato dopo una CALL o seguito da una parentesi senza essere dichiarato come array identifica un sottoprogramma e non un array o altro) come nell’esempio precedente. EXTERNAL con un nome di funzione intrinseca dichiara che esiste una subroutine o funzione esterna con lo stesso nome della funzione intrinseca indicata, quest’ultima non è più utilizzabile e ogni chiamata a quel nome esegue invece il sottoprogramma (utile per sostituire una funzione intrinseca con una propria). Se il modulo principale dichiara con INTRINSIC una funzione e questa viene passata ad un sottoprogramma, quest’ultimo per passarla ad un altro sottoprogramma deve dichiararla con EXTERNAL e non con INTRINSIC. 19.8 FUNZIONI DI LIBRERIA (INTRINSECHE) I nomi delle funzioni intrinseche possono essere utilizzati come nomi di variabili purché i nomi non compaiano in un’istruzione INTRINSIC (alcuni compilatori non lo permettono comunque). Ciò rende non disponibili e funzioni stesse. Di solito il tipo del risultato è indicato dal primo carattere del nome (dichiarazioni intrinseche, A per REAL, D per DOUBLE PRECISION, C per COMPLEX, L per LOGICAL) e gli argomenti sono dello stesso tipo del risultato. Gli argomenti devono essere tutti dello stesso tipo e coincidere con il tipo richiesto dalla funzione, fanno eccezione le “generic function” (non presenti nelle prime

36

EQUIVALENZA DI AREE DI MEMORIA

versioni del FORTRAN) che possono essere chiamate con argomenti di qualsiasi tipo (ma tutti dello stesso tipo) e producono un risultato che di solito è dello stesso tipo degli argomenti. Si utilizzino normalmente le generic function salvo nel caso in cui il risultato debba essere passato come argomento attuale ad un sottoprogramma. Esistono funzioni intrinseche di conversione di tipo, matematiche e per le stringhe (vedasi l’appendice A a pag. 64).

20. EQUIVALENZA DI AREE DI MEMORIA EQUIVALENCE fa sì che più variabili di qualsiasi tipo e composizione condividano la stessa area di memoria. Lo standard afferma che queste devono essere o tutte numeriche (sono incluse le LOGICAL) o tutte CHARACTER, alcuni compilatori non rispettano questa restrizione. EQUIVALENCE (var1, var2, var3,…), (…), … Sta al programmatore il mantenere traccia di che cosa è memorizzato e in particolare del tipo (ad es. non ha in genere senso scrivere un REAL e leggerlo come INTEGER). In una EQUIVALENCE per riferirsi al primo elemento di un array si può usare anche il solo nome dell’array. Esempio INTEGER*2 Buf(2) REAL*4 Dati EQUIVALENCE (Buf, Dati) In questo caso i 4 byte del vettore Buf (2 variabili intere) e quelli del reale Dati sono coincidenti (occupano la stessa zona di memoria). Esempio INTEGER*4 A(5), B(9), C(2,2) EQUIVALENCE ( A(1), B(4), C(1,2) ) Qui EQUIVALENCE fa coincidere le 3 variabili indicate tra parentesi; trattandosi di array e matrici (si ricordi che sono memorizzate per colonne) anche gli altri elementi di questi risultano essere allineati (A(2) con B(5) e con C(2,2), B(3) con C(2,1), ecc.). Si riassume la situazione con il seguente schema (ad ogni riga corrispondono gli stessi 4 byte):

37

EQUIVALENZA DI AREE DI MEMORIA

A(1) A(2) A(3) A(4) A(5)

B(1) B(2) B(3) B(4) B(5) B(6) B(7) B(8) B(9)

C(1,1) C(2,1) C(1,2) C(2,2)

Esempio CHARACTER*5 A, B, C(2)*2 EQUIVALENCE (A(4:),B), (B(2:),C(2)) La EQUIVALENCE è equivalente alla seguente: EQUIVALENCE (A(4:), B, C(1)(2:)) e produce (ogni riga corrisponde a 1 byte): A(1:1) A(2:2) A(3:3) A(4:4) A(5:5)

B(1:1) B(2:2) B(3:3) B(4:4) B(5:5)

C(1)(1:1) C(1)(2:2) C(2)(1:1) C(2)(2:2)

EQUIVALENCE può essere utilizzata per costruire dei record contenenti variabili di tipo diverso (attenzione che però lo standard non accetta la mescolanza di variabili carattere con numeriche).

38

EQUIVALENZA DI AREE DI MEMORIA

Esempio INTEGER*2 A REAL*4 B 8 byte LOGICAL*2 C INTEGER*2 Rec(4) 8 byte (4 coppie di byte) EQUIVALENCE (Rec(1),A), (Rec(2),B), (Rec(4),C) EQUIVALENCE qui fa sì che A venga memorizzata nelle locazioni di Rec(1), B in quelle di Rec(2) e Rec(3), C in quelle di Rec(4).

}

EQUIVALENCE può essere utilizzata per poter considerare una variabile carattere come un array di caratteri e viceversa, come indicato nell’esempio. Esempio CHARACTER*1 Vett(4) CHARACTER*4 Dati EQUIVALENCE (Vett, Dati) quindi si può scrivere: DATA Vett/'abcd'/ READ *, Dati e utilizzare sia Vett(i) che Dati(i:i). EQUIVALENCE può essere utilizzata con i blocchi COMMON per identificare solo le parti del blocco che interessano in un particolare modulo. Esempio REAL A0,A1,A2,… COMMON /BLOCCO1/ A0,A1,A2,A3,A4,A5,A6,A7,A8,A9, * B0(5), B1(10), B2(3:9), B3(4:5), B4(8), B5(20), * B6(4:6), B7(-12:12), B8(7,9), B9(6,3) Se in un sottoprogramma si vuole accedere solo alle variabili comuni A0, A7 e B4, si può scrivere: (BLOCCO1 è un array di 210 numeri REAL): REAL BLOCCO(210), A1, A7, B4 COMMON /BLOCCO1/ BLOCCO(210) EQUIVALENCE (A0,BLOCCO),(A7,BLOCCO(8)),(B4,BLOCCO(53))

AREE COMUNI

39

21. AREE COMUNI Servono per estendere lo scope delle variabili, altrimenti visibili solo dentro il modulo in cui sono state definite. Le dichiarazioni COMMON devono essere collocate dopo la definizione delle variabili e prima delle eventuali istruzioni DATA. Nello stesso blocco COMMON non ci possono essere sia variabili di tipo numerico (incluse le LOGICAL) che di tipo CHARACTER. Una variabile COMMON passata (come argomento) ad un sottoprogramma non può da questo essere passata ad un altro sottoprogramma. Per il mantenimento dei valori di variabili COMMON tra le successive chiamate di sottoprogrammi si veda 19.6, pag. 33. 21.1 NAMED COMMON Si usa quando si devono condividere delle variabili solo tra alcuni moduli. COMMON /nome-blocco1/lista1 [[,]/nome-blocco2/lista2]… Tutti i moduli che hanno un’istruzione COMMON recante il nome di blocco nome-blocco condividono tutte le variabili di quel blocco (elencate nella lista associata). Tutte le liste associate nei vari moduli allo stesso nome-blocco devono avere lo stesso numero di elementi; poiché le variabili vengono passate per posizione e non per nome (per questa caratteristica vengono talvolta utilizzate al posto delle EQUIVALENCE), ci deve essere una corrispondenza di tipo (vedi esempio sotto). Ogni variabile può comparire in un solo blocco. Il nome del blocco deve essere diverso dagli identificatori presenti nei moduli che utilizzano tale blocco, dalle keyword, dai nomi degli altri moduli e dai nomi delle altre COMMON. Esempio MODULO1 COMMON /BLOCCO1/Intera, Reale, Complessa/ MODULO2 COMMON /BLOCCO1/Int, Real, Compl/ Le variabili nella lista della COMMON hanno tipo dichiarato o esplicitamente o implicitamente e dimensioni dichiarate o in fase di definizione, o da una DIMENSION oppure dalla COMMON che fa essa stessa da DIMENSION. Esempio

40

AREE COMUNI REAL A, B DIMENSION A(10) COMMON /BLOCCO/A, B(100)

Se lo stesso nome di blocco compare in più istruzioni COMMON nello stesso modulo, viene creato (in memoria) un unico blocco costituito dalla concatenazione dei blocchi COMMON con quel nome nell’ordine indicato. Esempio COMMON COMMON COMMON equivale a: COMMON

/NOME1/Var1 /NOME2/Num1, /NOME1/Var2 /NOME1/Var3,Var4, /NOME2/Num2 /NOME1/Var1,Var2,Var3,Var4, /NOME2/Num1,Num2

Poiché la COMMON riserva semplicemente dello spazio, questo può anche essere visto in modo differente (riorganizzato) dai moduli che lo condividono (pratica sconsigliata perché poco chiara). Esempio MODULO1 REAL A(5,5) COMMON /BLOCCO1/A MODULO2 REAL A(5), B(5), C(5), D(5), E(5) COMMON /BLOCCO1/A, B, C, D, E In MODULO1 si vede una matrice 5x5, in MODULO2 lo stesso spazio viene visto come 5 array di 5 elementi. 21.2 BLANK COMMON Si usa quando si devono condividere delle variabili tra (quasi) tutti i moduli. COMMON [//]var1, var2, [stessa lista della NAMED COMMON]… La doppia barra è opzionale se le prime variabili fanno parte del blocco senza nome. L’area di BLANK COMMON è unica per ogni programma e può essere o di tipo numerico (LOGICAL inclusi) o di tipo CHARACTER.

AREE COMUNI

41

Non possono essere inizializzate, neppure in un’istruzione BLOCK DATA. Non diventano mai indefinite (vedasi 19.6, pag. 33). I moduli di un programma possono considerare i BLANK COMMON anche di dimensione diversa (a differenza dei NAMED COMMON): nei moduli il contenuto dell’area COMMON deve sempre essere definito dall’inizio, ma la definizione può terminare subito dopo il punto che contiene le variabili che si vogliono utilizzare: le restanti variabili restano tuttavia inaccessibili al modulo che non le definisce. Esempio MODULO 1 (vede solo le prime 6 variabili del BLANK COMMON) REAL A, B, C, D, E, F COMMON A, B, C, D, E, F MODULO 2 (vede solo le prime 3 variabili del BLANK COMMON) REAL O, P, Q COMMON O, P, Q MODULO 3 (vede solo le prime 5 variabili del BLANK COMMON) REAL Q1, Q2, F3, C6, QQ COMMON Q1, Q2, F3, C6, QQ 21.3 INIZIALIZZAZIONE DELLE VARIABILI COMMON Le variabili COMMON (di tutti i moduli) possono essere inizializzate con le istruzioni DATA solo se queste ultime vengono raggruppate nel modulo apposito BLOCK DATA. BLOCK DATA [nome] nome ha scope globale ed è il nome del modulo. Il modulo BLOCK DATA viene richiamato automaticamente (non si deve chiamare esplicitamente con una CALL) all’inizio dell’esecuzione. Può contenere solo le istruzioni IMPLICIT, SAVE, PARAMETER, DIMENSION, COMMON, EQUIVALENCE, DATA, le istruzioni di definizione di tipo e i commenti. Può essere utilizzato solo per le variabili dei NAMED COMMON. Esempio BLOCK DATA nome INTEGER A, B, C, D, E COMMON /BLOCCO1/ A, B, C(100)

42

INPUT/OUTPUT COMMON /BLOCCO2/ D, E DATA A, B, C, D, E / 1, 2, 100* 3, 4, 5/ END

22. INPUT/OUTPUT Le operazioni di lettura e scrittura possono essere dei seguenti tipi:  con formato libero (“list-directed I/O”, “free-FORMAT”, vedasi 22.4, pag. 54), in cui il formato utilizzato per leggere o stampare un valore dipende dal tipo del valore (il compilatore utilizza un formato di default per ciascun tipo);  con formato indicato esplicitamente (vedasi 22.3, pag. 44), in cui il formato utilizzato viene descritto per mezzo di una sequenza di descrittori di campo, in genere collocati in un’istruzione FORMAT;  senza formato (“unformatted I/O”, vedasi 22.5, pag. 54) in cui i dati vengono letti e scritti esattamente come sono in memoria (sequenze di bit). Ogni riga letta o scritta viene detta “record” (corrispondeva a una scheda perforata). Nel seguito lu è la “Logical Unit” (o “Unit”), ossia un numero maggiore o uguale a 0 che viene utilizzato all’interno del programma per identificare un dispositivo di I/O. Questo numero viene associato ad un file o a un dispositivo di I/O per mezzo dell’istruzione OPEN oppure è predefinito. Tra i dispositivi predefiniti si hanno: * (asterisco) corrisponde sia allo standard input (tastiera) che allo standard output (video), 1 o 5 valore tipico di input da terminale, 2 o 6 valore tipico di output su terminale. 22.1 INPUT Ogni lettura inizia da una riga (record) nuova: se una READ non ha letto tutti valori dati sulla riga che ha iniziato a leggere, la READ successiva li ignora e inizia a leggere dalla riga seguente. Ma se un ciclo implicito viene utilizzato per leggere un vettore (oppure la lista della READ contiene il nome di un vetto-

INPUT/OUTPUT

43

re), se il record non ha abbastanza elementi per riempire il vettore allora la lettura non passa a considerare il record successivo e vengono assegnati valori nulli (o spazi a seconda del tipo di variabile). L’istruzione di lettura è: READ ([UNIT=]lu, [FMT=]label) lista-variabili label FORMAT (lista-descrittori-di-campo) Legge dal dispositivo di input identificato dal numero lu il valore da assegnare alle variabili elencate nella lista (separate da virgole), utilizza o il formato (vedasi 22.3.2, pag. 48) indicato nell’istruzione FORMAT associata tramite la label o il formato standard (vedasi 22.4, pag. 54). Il formato completo dell’istruzione READ è indicato nella sezione 23, pag. 56. Altra forma della READ: READ label, lista-variabili A differenza dalla precedente forma, qui lu non è qui specificata, ma corrisponde al terminale. 22.2 OUTPUT Se l’output va su stampante (ad aghi o a impatto) il primo carattere di ogni riga, detto “Carriage Control Character” ed emesso di solito per mezzo dei descrittori X o H, non viene stampato, ma fa eseguire un’azione di formattazione prima di scrivere la nuova riga: ‘1’ emette il carattere di salto a pagina nuova ‘ ’ (spazio) emette il carattere di ritorno a capo (single spacing) ‘+’ non emette il carattere di ritorno a capo (si ha una sovrascrittura, se la riga da stampare è identica alla precedente si ha una scritta più marcata, ossia in grassetto; se le righe sono diverse questo meccanismo può essere usato per scrivere più caratteri nella stessa posizione, ad es. ‘O’ e ‘/’ per avere il simbolo di diametro , a questo fine si può meglio utilizzare il descrittore di formato T) ‘0’ (zero) emette due caratteri di ritorno a capo (double spacing) Gli caratteri altri vengono considerati al pari dello spazio (e quindi non vengono stampati).

44

INPUT/OUTPUT

Su un terminale video non hanno invece alcun effetto e tutti i caratteri vengono stampati. Alcuni compilatori, però, non fanno differenza tra terminale video e stampante. Ogni chiamata alle funzioni di output fa sì che la successiva stampa inizi a capo, salvo usare il descrittore \ (o $ per alcuni compilatori) al termine della FORMAT. Un errore (es. campo troppo piccolo per far stare tutte le cifre della parte intera di un numero) fa sì che il campo venga stampato riempito di asterischi. Le istruzioni di output sono due: PRINT label, lista-espressioni label FORMAT (lista-descrittori-di-campo) Stampa sul dispositivo standard di output (di solito il video) il valore delle espressioni (anche semplici variabili o costanti) indicate separate da virgole nella lista-espressioni; il formato dipende dall’istruzione FORMAT indicata dalla label (vedasi 22.3, pag. 44). Va a capo dopo la stampa dell’intera lista. Equivale all’istruzione: WRITE (*,label) lista-espressioni Se il dispositivo standard di output è la stampante, PRINT aggiunge automaticamente lo spazio iniziale come carattere speciale. WRITE ([UNIT=]lu, [FMT=]label) lista-espressioni label FORMAT (lista-descrittori-di-campo) Stampa sul dispositivo di output identificato dal numero lu il valore delle espressioni (anche delle semplici variabili o costanti) indicate separate da virgole nella lista-espressioni, utilizza il formato indicato da label (vedasi 22.3, pag. 44). La sintassi completa dell’istruzione WRITE è riportata in 23.4, pag. 59. 22.3 INPUT/OUTPUT FORMATTATO Nell’input formattato lo spazio può essere considerato equivalente allo zero:  per i dispositivi “precollegati” (standard input) dipende dal compilatore

INPUT/OUTPUT

45



per i file aperti con OPEN il default è ignorare gli spazi, ma si può indicare esplicitamente il comportamento da seguire con la specifica BLANK nella OPEN stessa (vedasi 23.1, pag. 57) In entrambi i casi si possono utilizzare i prefissi dei descrittori BN e BZ (vedasi 22.3.3, pag. 52). Sia nelle istruzioni di input che in quelle di output il formato dei dati da leggere e scrivere è indicato per mezzo di un parametro. Tipicamente tale parametro è una label che identifica una riga di codice contenente un’istruzione FORMAT (usualmente la successiva, ma alcuni le mettono tutte al fondo del programma, prima della END). La lista dell’istruzione non eseguibile FORMAT è costituita da descrittori di campo, uno per ciascuno dei valori indicati nella lista dell’istruzione di I/O associata ad essa. Esempio PRINT 100, A, B, C 100 FORMAT (F3.1, F3.1, F3.1) Per stampare un testo ASCII, lo si deve mettere tra gli altri descrittori racchiuso tra apici (è detto “descrittore ad apici”) e separato da questi da virgole. Se si va a capo a metà di una stringa, vengono considerati anche tutti gli spazi fino alla colonna 72 e tutti quelli dall’inizio della riga successiva fino al primo nonspazio. Esempio WRITE (*, 100) Somma 100 FORMAT (1X, 'La somma e'': ', F5.2) Il descrittore 1X della FORMAT non corrisponde ad una variabile della lista della WRITE, serve semplicemente per far emettere uno spazio prima del testo da stampare: è il Carriage Control Character, necessario per l’output su stampante (e per alcuni compilatori non standard anche su video). 22.3.1 Formato dei dati nelle istruzioni di I/O Il formato può essere indicato in vari modi, la posizione indicata con label può di fatto contenere (gli esempi seguenti sono equivalenti):

46

INPUT/OUTPUT

1. una label che identifica la riga in cui è presente un’istruzione FORMAT WRITE (*, 100) Somma 100 FORMAT (1X, 'La somma e'': ', F5.2) 2. una variabile intera assegnata da ASSIGN con la label di un’istruzione FORMAT ASSIGN 100 TO Var WRITE (*, Var) Somma 100 FORMAT (1X, 'La somma e'': ', F5.2) 3. una costante di tipo CHARACTER WRITE (*, '(1X, ''La somma e'''' '', F5.2)') Somma PRINT '(1X, ''La somma e'''' '', F5.2)', Somma 4. una variabile di tipo CHARACTER Var = '(1X, ''La somma e'''' '', F5.2)' WRITE (*, Var) Somma 5. un array di tipo CHARACTER (non deve essere un array di dimensioni presunte) il formato è la concatenazione di tutti elementi dell’array CHARACTER*21 Var(3) Var(1) = '(1X,' Var(2) = ' ''La somma e'''' '',' Var(3) = ' F5.2)' WRITE (*, Var) Somma 6. un elemento di array di tipo CHARACTER Var(2) = '(1X, ''La somma e'''' '', F5.2)' WRITE (*, Var(2)) Somma 7. un’espressione di tipo CHARACTER Var1 = '(1X,' Var2 = ' ''La somma e'''' '', F5.2)' WRITE (*, Var1//Var2) Somma Nei casi in cui si utilizzino espressioni CHARACTER per il formato (detto “formato incorporato”), la lista dei descrittori deve essere messa tra apici e pa-

INPUT/OUTPUT

47

rentesi, ad esempio '(1X, F5.2)'; eventuali apici interni facenti parte di descrittori ad apici devono essere raddoppiati; gli apici interni ai descrittori ad apici stessi vanno quindi quadruplicati. Se nella FORMAT ci sono più descrittori di campo di quante sono le variabili nella lista, questi vengono ignorati (ciò è utile per usare la stessa FORMAT con più istruzioni o quando non si sa a priori quanti elementi verranno stampati da un ciclo implicito). Viceversa, se nella FORMAT ci sono meno descrittori di campo, i descrittori della FORMAT vengono riutilizzati secondo le seguenti regole:  se non ci sono sottoliste di descrittori (vedasi 22.3.4, pag. 53), il formato viene ripetuto dall’inizio (ogni volta inizia da una riga nuova, nella stampa va a capo);  se ci sono sottoliste, si segue la seguente procedura:  viene valutata la penultima parentesi chiusa (l’ultima è quella dell’istruzione FORMAT stessa)  viene trovata la corrispondente parentesi aperta (che corrisponde quindi all’inizio dell’ultima sottolista) e i descrittori vengono riutilizzati da qui in avanti (ogni volta inizia da una riga nuova, nella stampa va a capo)  se la sottolista ha un moltiplicatore, esso viene considerato (senza iniziare una riga nuova, nella stampa non va a capo) Esempio Nel secondo esempio di 22.3.4, pag. 53 viene ripetuta la sequenza di descrittori 2(I2,F4.1). Il riutilizzo dei descrittori unito all’uso dei cicli impliciti permette la stampa di n valori per riga. Esempio WRITE (*,100) (Vett(I), I=1,100) 100 FORMAT (1X, 5F12.4) Gli elementi di Vett vengono stampati a 5 per riga.

48

INPUT/OUTPUT

22.3.2 Descrittori di campo Specificano il formato delle variabili della lista di lettura o stampa. I descrittori dei formati numerici allineano il numero a destra nello spazio a disposizione (campo). w è il numero di caratteri totali inclusi gli eventuali: segno, punto decimale, lettera E o D, segno dell’esponente. d è il numero di caratteri dopo il punto decimale. Se un valore non può essere scritto nel formato indicato per mancanza di spazio, viene stampata una sequenza di asterischi di lunghezza pari al campo disponibile. Iw.m

lettura/scrittura di intero in base decimale INPUT: legge esattamente w caratteri (lo spazio può essere considerato equivalente ad uno zero), m non ha significato. OUTPUT: scrive il numero su w cifre totali, se w > numero cifre vengono aggiunti spazi a sinistra per avere dimensione totale w (questo viene detto “padding” a sinistra con spazi). m è il numero minimo di cifre da stampare (eventualmente precede le cifre significative con degli zeri), se m = 0 e il numero da stampare è 0, stampa w spazi. Deve sempre essere w  m.

Ow

scrittura di intero in base ottale (non standard 77)

Zw

scrittura di intero in base esadecimale (non standard 77)

Lw

lettura/scrittura di valore logico INPUT: legge w caratteri, tra questi viene cercata una delle sequenze “T”, “.T”, “F”, “.F” eventualmente precedute da spazi e seguite da altri caratteri. OUTPUT: viene stampata la lettera T o F preceduta da w-1 spazi.

Aw

lettura/scrittura di stringa ASCII INPUT: se w < lunghezza-var, si ha troncamento a destra se w > lunghezza-var, si ha padding a destra con (lunghezza-w) spazi

INPUT/OUTPUT

49

se w non è indicato vengono letti tanti caratteri quanto è lunga la variabile Non si deve mettere tra apici la stringa che viene letta (in modalità list-directed I/O invece è necessario). Esempio CHARACTER*8 Var READ (*, 100) Var 100 FORMAT (A10), Var dopo la lettura di 'abcdefgh', Var contiene 'cdefgh '. OUTPUT: se w < lunghezza-var, stampa solo i primi w caratteri se w > lunghezza-var, si ha padding a sinistra con spazi se w non è indicato stampa tutti i caratteri, inclusi eventuali spazi di padding (come nel formato list-directed). Fw.d

lettura/scrittura di reali in notazione non esponenziale INPUT: legge al più w caratteri totali; se fra questi è presente il punto decimale il valore di d viene ignorato, altrimenti viene automaticamente considerato come posizionato a d cifra da destra (es. se il descrittore è F4.1, quando viene letta la sequenza di cifre 1246 essa viene interpretata come 124.6, cioè 1 cifra dopo la virgola). Per leggere numeri reali con e senza virgola in formato fisso si può utilizzare d pari a 0. Questo descrittore può leggere il valore in input anche se è in formato esponenziale, il numero totale di caratteri è comunque w e, se non c'è la virgola, la parte frazionaria viene considerata quella costituita dai d caratteri a partire dal fondo della sola mantissa. Lo spazio può essere considerato equivalente alla cifra 0 (vedasi 22.3.3, pag. 52); quelli dopo E o D prima dell’esponente (e del relativo segno) sono ignorati (es. 3.2E +21). Alcune implementazioni accettano la forma non standard SxxxxSxxx, ossia trascurano la presenza di E o D e usano una cifra in più per l’esponente. OUTPUT: si ha la stampa dei valori nella forma Sxxx.xxxx (S=segno, x=cifra) secondo le seguenti regole: se d > numero-cifre-decimali, si ha padding a destra con 0 del campo dei decimali se d < numero-cifre-decimali, si ha arrotondamento a d cifre

50

INPUT/OUTPUT se ci sono per la parte intera meno cifre del massimo previsto si ha padding a sinistra con spazi. I numeri minori di 1 sono stampati con 0. davanti.

Ew.dEe lettura/scrittura di reali in notazione esponenziale La parte Ee è facoltativa (di default e vale 2) e in essa e indica le cifre riservate per l’esponente; INPUT: Si applicano tutte le considerazioni viste per il descrittore F. Poiché cerca di leggere e cifre per l’esponente, quando lo spazio viene considerato come 0 (vedasi 22.3.3, pag. 52) si ha che la lettura di ‘ .1E2 ’ interpreta la sequenza letta come il valore ‘0.1E20’. OUTPUT: si ha la stampa dei valori con mantissa compresa tra 0.1 e 0.9 nella forma: S0.xxxESxx (S=segno, x=cifra); è necessario che sia soddisfatta la relazione w d+e+5, se necessario si ha padding a sinistra con spazi per la parte intera e padding a destra con zeri per la parte decimale. Gw.dEe lettura/scrittura di reali in notazione variabile la parte Ee è facoltativa (di default e vale 2) e in essa e indica le cifre riservate per l’esponente; INPUT: Si applicano tutte le considerazioni viste per i descrittori F ed E. OUTPUT: si considera il numero espresso nella forma 0.xxx Eee, se il numero è compreso tra i valori 0.1 e 10d viene utilizzata la sequenza di descrittori ‘F(w - 4).(d - numero-cifre-parte-intera),4X’ altrimenti viene usato il descrittore ‘Ew.dEe’. Dw.d

wX

lettura/scrittura di reali in doppia precisione INPUT: equivalente al descrittore E. OUTPUT: equivalente al descrittore E, salvo che i numeri sono scritti con D al posto di E per indicare l’esponente. caratteri ignorati o di spaziatura INPUT: fa saltare w caratteri. OUTPUT: emette w spazi.

wHabc…

costanti Hollerith (ASCII)

INPUT/OUTPUT

51

INPUT: non utilizzabile. OUTPUT: vengono stampati i w caratteri che seguono la H; viene ormai usata solo per il “Carriage Control Character” (vedasi 22.2, pag. 43). /

interruzione di istruzione di I/O funziona anche da separatore (le virgole ai lati possono essere tralasciate). INPUT: la parte non letta della linea di dati attuale viene scartata e la lettura riprende dalla successiva linea di dati (in alcuni compilatori fa terminare l’operazione di lettura e le variabili non lette hanno valore indefinito, tipicamente non cambiano). OUTPUT: scarica il contenuto dei buffer (“flush”) e va a capo; il primo carattere dopo ‘/’ è il “Carriage Control Character” (vedasi 22.2, pag. 43).

:

separatore di lista variabile di descrittori INPUT: non utilizzabile. OUTPUT: nell’interpretazione della FORMAT, quando si arriva a un ‘:’ si valuta se ci sono altre variabili nella lista da stampare, se ci sono il resto della FORMAT viene valutato, altrimenti l’istruzione termina. E’ utile per riutilizzare la stessa FORMAT con più istruzioni WRITE aventi diverso numero di variabili da stampare. Esempio WRITE (*,10) A WRITE (*,10) A, B 10 FORMAT (1X, 'A=', F5.1 : 'B=', F5.1)

$

soppressione di ritorno a capo (non standard 77) INPUT: non utilizzabile. OUTPUT: messo in fondo alla lista della FORMAT sopprime il successivo ritorno a capo. soppressione di ritorno a capo (standard 77) INPUT: non utilizzabile. OUTPUT: messo in fondo alla lista della FORMAT sopprime il successivo ritorno a capo.

\

52

INPUT/OUTPUT

posizionamento assoluto sulla stessa riga INPUT: fa continuare la successiva lettura dalla colonna n-esima. OUTPUT: fa continuare la successiva scrittura dalla colonna n-esima. TLn TRn posizionamento relativo alla posizione attuale sulla stessa riga Se il valore di n indica una posizione precedente la prima, la posizione corrente diventa comunque la prima. INPUT: fa continuare la lettura n colonne prima/dopo quella attuale. OUTPUT: fa continuare la successiva scrittura n colonne prima/dopo quella attuale.

Tn

22.3.3 Prefissi dei descrittori Modificano il funzionamento dei descrittori, hanno vigore da quando vengono incontrati fino al termine della FORMAT. nP

fattore di scala Precede i descrittori F, E, D e G. INPUT: il numero letto viene diviso per 10^n prima di essere memorizzato nella variabile, utile per la lettura dei valori di percentuali, (obsoleto e sconsigliato, lo si documenti accuratamente quando viene usato). OUTPUT: non ha effetto.

SP

segno dei valori numerici sempre espresso Precede i descrittori I, F, E, D e G. INPUT: non utilizzabile. OUTPUT: i valori numerici vengono sempre stampati preceduti dal segno.

SS

segno dei valori numerici Precede i descrittori I, F, E, D e G. INPUT: non utilizzabile. OUTPUT: i valori numerici negativi vengono sempre stampati preceduti dal segno, i positivi mai.

S

segno di defaut dei valori numerici Precede i descrittori I, F, E, D e G.

INPUT/OUTPUT

53

INPUT: non utilizzabile. OUTPUT: ripristina il comportamento di default (di solito uguale a quello descritto per SS) per la stampa dei valori numerici: i valori numerici negativi vengono sempre stampati preceduti dal segno, per i positivi dipende dal compilatore. BN

non interpretazione dello spazio come zero Precede i descrittori I, F, E, D e G. Ha precedenza sull’opzione BLANK della OPEN. INPUT: non fa considerare i caratteri spazio come degli 0 (vengono ignorati). OUTPUT: non utilizzabile.

BZ

interpretazione dello spazio come zero Precede i descrittori I, F, E, D e G. Ha precedenza sull’opzione BLANK della OPEN. INPUT: i caratteri spazio vengono considerati come degli 0 (comportamento di default). OUTPUT: non utilizzabile.

Esempio FORMAT (BNF5.1, F5.2, BZI5) 22.3.4 Ripetizioni dei descrittori Per evitare di ripetere lo stesso descrittore più volte, è possibile indicarne la ripetizione mettendo un numero intero con significato di moltiplicatore davanti ai vari descrittori (tranne X e H). Il moltiplicatore può essere usato anche per sottoliste di identificatori (indicate tra parentesi). Esempi FORMAT(X, 4I3) equivale a FORMAT(X, I3, I3, I3, I3) FORMAT(X,2I8,2(I2,F4.1)) equivale a FORMAT(X,I8,I8,I2,F4.1,I2,F4.1)

54

INPUT/OUTPUT

22.4 FREE-FORMAT (LIST-DIRECTED I/O) Si ottiene mettendo un carattere asterisco ‘*’ al posto della label per il formato. Il formato utilizzato per la lettura o la scrittura è determinato automaticamente in base al tipo del valore. PRINT *, lista-espressioni WRITE (*,*) lista-espressioni READ *, lista-var READ (*,*) lista-var Se si deve leggere un REAL e viene passato un valore senza punto decimale né esponente, il valore letto viene interpretato correttamente come REAL con parte decimale nulla (per la lettura con formato è invece indispensabile specificare un valore di d pari a 0 nel descrittore Fw.d). I valori in input devono essere separati da virgole, da spazi, dalla barra ‘/’ o dal ritorno a capo. I valori di tipo stringa devono essere passati al programma racchiusi tra apici (la lettura con formato non li richiede invece). La lettura può continuare alla riga (record) successiva. Per stampare delle stringhe costanti, le si mettono semplicemente (racchiuse tra apici) come argomenti della lista-espressioni. Esempio PRINT *, 'La somma di', A, ' e ', B, 'vale ', A+B 22.5 UNFORMATTED I/O I dati vengono letti e scritti per mezzo delle istruzioni WRITE e READ esattamente come sono in memoria (sequenze di bit). Questo è utile quando i dati prodotti da un programma devono essere elaborati da un altro programma fatto eseguire su una macchina identica. Si può risparmiare in questo modo il tempo di trasformazione dei dati dalla notazione interna a quella leggibile nel primo programma e quello della trasformazione inversa nel secondo; si ha anche il

INPUT/OUTPUT

55

vantaggio di non avere alcun errore di approssimazione dovuto alla conversione di base dei numeri. Viene ottenuto non specificando alcun riferimento a formato nelle operazioni di I/O. Esempi WRITE (*) Var WRITE (UNIT=6) Var READ (*) Var Poiché ogni operazione di I/O non formattato legge o scrive un solo record, è necessario che l’output prodotto da un’istruzione WRITE non formattata venga letto da un’istruzione READ non formattata avente una lista di variabili esattamente uguale per numero e tipo a quella della WRITE. Nel caso in cui la lista della READ sia più corta di quella della WRITE, i restanti dati vengono scartati. Nel caso opposto si ha errore. 22.6 I/O DI VETTORI E MATRICI La lettura in blocco dei valori degli elementi di vettori e matrici può essere effettuata nei seguenti modi: 1) READ *, Var Se Var è una variabile a n dimensioni, con questa istruzione vengono letti tutti gli elementi della matrice. L’ordine di lettura è quello di immagazzinamento in memoria (per colonne): è come se gli indici (che non vengono indicati) venissero automaticamente incrementati, l’indice più veloce a variare è il primo, il meno veloce l’ultimo). Esempi INTEGER T(2,2) READ *, T Vengono letti in sequenza gli elementi: T(1,1), T(2,1), T(1,2), T(2,2); i valori vengono immessi separandoli con spazi, virgole o ritorni a capo. PRINT *, T Vengono stampati su una sola riga tutti gli elementi della matrice T, gli indici variano come nel caso precedente (la sequenza è la stessa).

56

INPUT/OUTPUT SU FILE

Gli esempi precedenti sono equivalenti all’uso di cicli impliciti aventi indici che variano in modo tale da rispettare l’ordine di memorizzazione degli elementi. 2)

Si possono usare i cicli impliciti nella forma: READ (*,*) (var(indice), indice=m1,m2[,m3]) WRITE (*,*) (var(indice), indice=m1,m2[,m3]) I valori m1, m2 e m3 possono essere anche espressioni variabili appena lette: READ *, N, (A(I), I=1,N) Poiché in questo caso possono non esserci controlli sulla dimensione dell’array (dipende dal compilatore), se N > dimensione-di-A ci può essere un errore: conviene allora spezzare l’istruzione in tre parti: 1) lettura di N 2) confronto con il limite (dimensione-di-A) 3) lettura con ciclo implicito

23. INPUT/OUTPUT SU FILE Per utilizzare un file, lo si deve prima aprire con un istruzione OPEN, questa gli assegna una Logical Unit e da questo momento ogni riferimento al file da dentro il programma avviene solo tramite questa. Si possono usare valori interi qualsiasi (maggiori o uguali a zero), meglio evitare quelli già associati al terminale (che sono storicamente 1 o 5 per lo standard input, ossia il terminale, e 2 o 6 per lo standard output, eventualmente una stampante). Tutte le stringhe usate come parametri possono essere precedute da spazi in quanto questi sono ignorati (ad esempio la stringa ' MIOFILE.TXT' è equivalente a 'MIOFILE.TXT' e la stringa ' FORMATTED' equivale a 'FORMATTED').

INPUT/OUTPUT SU FILE

57

23.1 APERTURA Assegna una Logical Unit ad un file in modo che questo possa essere scritto o letto dall’interno del programma. OPEN([UNIT=]lu, FILE=filename [,STATUS=status] [,ACCESS=acc] [,FORM=form] [,ERR=err-label] [,IOSTAT=iostat] [,RECL=lun] [,BLANK=bl]) filename: variabile o costante di tipo CHARACTER contenente il nome del file da aprire, status: stato del file all’apertura: 'OLD' - il file deve già esistere altrimenti dà errore, 'NEW' - il file viene creato, se già esiste dà errore, 'SCRATCH' - il file (di output) viene cancellato alla CLOSE, 'UNKNOWN' - (default) dipende dal compilatore, di solito però se il file esiste si comporta come 'OLD', altrimenti come 'NEW'; acc: tipo di accesso: 'DIRECT' - file ad accesso diretto (causale, random), in lettura i record essere tutti di lunghezza uguale, in scrittura vengono creati tali, 'SEQUENTIAL' - file ad accesso sequenziale (default), i record possono essere di lunghezza diversa; form: formato: 'FORMATTED' - i dati vengono letti e scritti come caratteri ASCII (ossia nella forma consueta leggibile); è il modo di default per i file sequenziali, 'UNFORMATTED' - i dati vengono letti e scritti secondo il formato interno (così come sono mantenuti in memoria); err-label: label della riga da cui il programma continua l’esecuzione in caso ci sia un errore; iostat: variabile intera che contiene il codice d'errore dell’ultima operazione sul file. Il valore 0 indica che non ci sono stati errori; un valore negativo indica il raggiungimento della fine del file, un valore positivo indica un errore, il significato dei valori (eccetto 0) dipendono dal compilatore; lun: espressione numerica indicante la lunghezza in byte dei record per i file ad accesso diretto, si può omettere in caso di apertura di file già esistente;

58

INPUT/OUTPUT SU FILE

bl: per i soli file di tipo FORMATTED, se vale 'NULL' gli spazi vengono ignorati (default), se vale 'ZERO' gli spazi vengono considerati zeri. I descrittori di campo BN e BZ possono cambiare questo funzionamento (vedi 22.3.3, pag. 52). Subito dopo l’istruzione OPEN alcuni sistemi richiedono anche l’istruzione REWIND (vedasi 23.5, pag. 59) 23.2 CHIUSURA Termina l’associazione tra una Logical Unit e un file, da questo momento il file non è più utilizzabile da dentro il programma (salvo riaprirlo con OPEN di nuovo). CLOSE ([UNIT=]lu [,STATUS=chiusura] [,ERR=err-label] [,IOSTAT=iostat]) chiusura: destino del file alla chiusura: 'KEEP': il file non viene cancellato (è il default se il file non è stato aperto in modo 'SCRATCH') 'DELETE': il file viene cancellato (è il default se il file è stato aperto in modo 'SCRATCH') La stessa terminazione dell’esecuzione di per sé chiude tutti i file aperti. Per scrivere su un file il record di END-OF-FILE (utile solo per i file sequenziali e per certi sistemi operativi) si può usare, prima della CLOSE, l’istruzione: ENDFILE lu ENDFILE ([UNIT=]lu [,ERR=err-label] [,IOSTAT=iostat]) ENDFILE lascia il file posizionato dopo il record di EOF appena scritto e da questo momento non è più possibile scrivere o leggere su quel file senza un riposizionamento con un istruzione REWIND o BACKSPACE. In alcuni sistemi la CLOSE non esegue una ENDFILE automaticamente, tale istruzione deve essere presente nel codice prima della CLOSE, in altri non serve del tutto (ma può essere comunque utilizzato per compatibilità). 23.3 LETTURA FILE SEQUENZIALI READ ([UNIT=]lu [,[FMT=]label][,ERR=err-label] [,END=end-label] [,IOSTAT= iostat]) lista-variabili

INPUT/OUTPUT SU FILE

59

lu: logical unit per identificare il file (già aperto) da cui leggere; la keyword UNIT= può essere omessa se lu è il primo parametro, label: label per la FORMAT, serve solo se l’input è di tipo FORMATTED; la keyword FMT= può essere omessa se label è il secondo parametro, end-label: label della riga di programma a cui saltare quando si arriva a EOF, se l’istruzione viene rieseguita si ha errore e salta a err-label; la si può utilizzare per uscire da un ciclo quando termina l’input. iostat: variabile intera che contiene il codice d'errore dell’ultima operazione sul file, il significato del codice è il seguente: iostat = 0 non ci sono stati errori; iostat < 0 è stato raggiunto l’EOF (non standard ma molto comune), iostat > 0 ci sono stati problemi (es. di formato). Il valore dei codici, a parte lo 0 che è standard, dipende dal compilatore. La fine del file viene rilevata quando si legge l’ultimo record del file (che è appunto un record di END-OF-FILE). Se si verifica una condizione di errore, anche se l’opzione ERR è stata utilizzata il valore delle variabili della READ diventa indefinito. 23.4 SCRITTURA FILE SEQUENZIALI WRITE ([UNIT=]lu, [,[FMT=]label] [,ERR=err-label] [,IOSTAT=iostat]) lista-espressioni La scrittura su un file sequenziale provoca la distruzione di tutte le informazioni contenute nel file dopo il record appena scritto. Per aggiungere alla fine del file nuovi record si deve raggiungere la fine del file per mezzo di letture successive, quando si incontra il record di END-OF-FILE si torna indietro prima di esso con il comando BACKSPACE e da questo punto in poi si può scrivere sul file con WRITE. 23.5 RIPOSIZIONAMENTO DI FILE SEQUENZIALI REWIND lu REWIND ([UNIT=]lu [,ERR=err-label] [,IOSTAT=iostat]) Ritorna all’inizio del file così che la prossima lettura riparta dal primo record.

60

INPUT/OUTPUT SU FILE

BACKSPACE lu BACKSPACE ([UNIT=]lu [,ERR=err-label] [,IOSTAT=iostat]) Torna indietro di un record così che la prossima lettura legga di nuovo l’ultimo record letto. 23.6 LETTURA FILE DIRETTO READ ([UNIT=]lu, REC=num [,[FMT=]label] [,ERR=err-label] [,IOSTAT=iostat]) lista-variabili num: espressione intera corrispondente al numero d'ordine progressivo del record da leggere (il primo ha il numero 1). Se la lettura richiede l’input da più record, il valore di REC viene incrementato automaticamente di 1 ogni volta. 23.7 SCRITTURA FILE DIRETTO WRITE ([UNIT=]lu, REC=id [,[FMT=]label] [,ERR=err-label] [,IOSTAT=iostat]) lista-espressioni Se la scrittura manda in output più record, il numero di REC viene incrementato automaticamente di 1 ogni volta. Esempio WRITE (8,200,REC=75) (A(I), I=1,100) 200 FORMAT (10F12.2) scrive 10 record, dal numero 75 all’84 inclusi. Non si devono scrivere più dati di quanti possono essere contenuti (in base al parametro RECL nella OPEN), ma se ne possono scrivere di meno: se il file è di tipo UNFORMATTED il resto del record viene riempito con valori non significativi (e tutto è coerente finché si legge solo quanto è stato scritto), se è di tipo FORMATTED si ha padding a sinistra con spazi. 23.8 FILE INTERNI Le operazioni di READ e WRITE (di tipo FORMATTED, sequenziali e non in free-format) possono essere effettuate non solo su file esterni, ma anche su variabili di tipo carattere, elementi di array, sottostringhe e array di caratteri, da indicare al posto della Logical Unit. Gli array di caratteri vengono considerati

61

INPUT/OUTPUT SU FILE

costituiti da tanti record quanti sono gli elementi dell’array; le variabili, gli elementi di array e le sottostringhe vengono ciascuno considerati come record unici. Ogni READ e ogni WRITE inizia sempre dal primo carattere della variabile di tipo CHARACTER (anche in presenza dei descrittori di campo per la soppressione del ritorno a capo). Non si usano le altre istruzioni dei file (in particolare OPEN e CLOSE). 23.9 RICHIESTA CARATTERISTICHE DI UN FILE Ci sono due modalità di utilizzo dell’istruzione INQUIRE:  nel modo “Unit Enquiry” vengono richieste informazioni relative alle caratteristiche di un file aperto, identificandolo con la sua Logical Unit. INQUIRE ([UNIT=]lu, lista-attributi)  nel modo “File Enquiry” vengono richieste informazioni relative alle caratteristiche di un file qualsiasi, identificandolo con il suo nome. INQUIRE (FILE=filename, lista-attributi) lista-attributi: è una lista di coppie specifier=var separate da virgole; le variabili var devono essere del tipo indicato nella tabella e i valori vengono assegnati dall’istruzione INQUIRE stessa. In caso di file non collegato (aperto), per il modo Unit Enquiry i valori restituiti nelle variabili dopo l’esecuzione della INQUIRE non sono significativi. Gli specifier corrispondono in genere ai parametri della OPEN, gli altri sono o indicati nelle note o sono evidenti.

Specifier

Tipo di var

ACCESS

CHARACTER

BLANK

CHARACTER

DIRECT

CHARACTER

ERR EXIST

INTEGER LOGICAL

Contenuto della variabile File enquiry Unit enquiry 'SEQUENTIAL' 'DIRECT' 'NULL' 'ZERO' 'YES' 'NO' 'UNKNOWN' SNE .TRUE. .FALSE.

'SEQUENTIAL' 'DIRECT' 'NULL' 'ZERO' SNE .TRUE. .FALSE.

Note



62

INPUT/OUTPUT SU FILE FORM

CHARACTER

FORMATTED

CHARACTER

IOSTAT NAME NAMED

INTEGER CHARACTER LOGICAL

NEXTREC

INTEGER

Specifier

Tipo di var

NUMBER OPENED

INTEGER LOGICAL

RECL SEQUENTIAL

INTEGER CHARACTER

UNFORMATTED

CHARACTER

'FORMATTED' 'UNFORMATTED' 'YES' 'NO' 'UNKNOWN' Codice di errore NR

'FORMATED' 'UNFORMATTED' Codice di errore FLU .TRUE. .FALSE. NR

Contenuto della variabile File enquiry Unit enquiry LU .TRUE. .FALSE. Lunghezza record 'YES' 'NO' 'UNKNOWN' 'YES' 'NO' 'UNKNOWN'

LU .TRUE. .FALSE. Lunghezza record -

  

Note



Codici e note SNE: Numero di riga in cui è stata messa una routine di gestione dell’errore FLU: file associato a lu NR: numero del record successivo per file ad accesso diretto LU: Logical Unit assegnata al file aperto  indefinito se il file è UNFORMATTED  indefinito se il file è di tipo SCRATCH  non applicabile ai file di tipo SCRATCH  indefinito per i file ad accesso sequenziale o in caso di errore  indefinito per i file ad accesso sequenziale Esempio CHARACTER*10 TipoAccesso, NomeFile INQUIRE (8, ACCESS=TipoAccesso, NAME=NomeFile)

INCLUSIONE DI FILE

63

24. INCLUSIONE DI FILE INCLUDE 'filename' include il codice FORTRAN contenuto in filename al posto dell’istruzione INCLUDE stessa prima di lanciare la compilazione (utile per non dover riscrivere, delle definizioni comuni a più file quali le COMMON). Non è FORTRAN 77 standard, ma è accettato da quasi tutti i compilatori.

25. BIBLIOGRAFIA “Programmazione strutturata in FORTRAN 77 ”, T.M.R. Ellis, Zanichelli, 1995 “Structured FORTRAN 77: for Engineers and Scientists ”, D.M. Etter, Benjamin-Cummings, 1983 “Fortran 77 Coding Guidelines ”, D.L. Levine, 1989 “FORTRAN 77 Full Language”, Standard ANSI X3J3/90.4

64

APPENDICE – Funzioni intrinseche standard

A. APPENDICE – FUNZIONI INTRINSECHE STANDARD Funzione Conversione di tipo

Definizione

Numero di argomenti

Nome generico

Nome specifico

Tipo relativo a Argomento Funzione

Conversione a INTEGER int (a) Vedi nota 1

1

INT

INT IFIX IDINT -

INTEGER REAL REAL DOUBLE COMPLEX

INTEGER INTEGER INTEGER INTEGER INTEGER

Conversione to REAL Vedi nota 2

1

REAL

REAL FLOAT SNGL -

INTEGER INTEGER REAL DOUBLE COMPLEX

REAL REAL REAL REAL REAL

Conversione a DOUBLE Vedi nota 3

1

DBLE

-

INTEGER REAL DOUBLE COMPLEX

DOUBLE DOUBLE DOUBLE DOUBLE

Conversione a COMPLEX Vedi nota 4

1o2

CMPLX

-

INTEGER REAL DOUBLE COMPLEX

COMPLEX COMPLEX COMPLEX COMPLEX

Conversione a INTEGER Vedi nota 5

1

ICHAR

CHAR.

INTEGER

Conversione a CHAR. Vedi nota 5

1

CHAR

INTEGER

CHAR.

Troncamento

int (a) Vedi nota 1

1

AINT

AINT DINT

REAL DOUBLE

REAL DOUBLE

Numero intero più vicino

int (a+.5) se a  0 int (a-.5) se a < 0

1

ANINT

ANINT

REAL

REAL

DNINT

DOUBLE

DOUBLE

INTEGER più vicino

int (a+.5) se a  0 int (a-.5) se a < 0

1

NINT

REAL

INTEGER

IDNINT

DOUBLE

INTEGER

NINT

65

APPENDICE – Funzioni intrinseche standard Funzione Valore assoluto

Definizione |a|

Numero di argomenti

Nome generico

Nome specifico

Tipo relativo a Argomento Funzione

1

ABS

IABS ABS DABS CABS

INTEGER REAL DOUBLE COMPLEX

INTEGER REAL DOUBLE REAL

(ar2+ai2)1/2 Resto

a1-a2* *int (a1/a2) Vedi note 1 e A

2

MOD

MOD AMOD DMOD

INTEGER REAL DOUBLE

INTEGER REAL DOUBLE

Trasferimento del segno

|a1| se a2 0 -|a1| se a2 a2 0 se a1  a2

2

DIM

IDIM

INTEGER

INTEGER

DIM

REAL

REAL

DDIM

DOUBLE

DOUBLE

DPROD

REAL

DOUBLE

Prodotto di DOUBLE

a1*a2

2

Ricerca del massimo

max(a1,a2,…)

2

MAX

MAX0 AMAX1 DMAX1 AMAX0 MAX1

INTEGER REAL DOUBLE INTEGER REAL

INTEGER REAL DOUBLE REAL INTEGER

Ricerca del minimo

min(a1,a2,…)

2

MIN

MIN0 AMIN1 DMIN1 AMIN0 MIN1

INTEGER REAL DOUBLE INTEGER REAL

INTEGER REAL DOUBLE REAL INTEGER

Lunghezza

Lunghezza di entità CHAR. Vedi nota 9

1

LEN

CHAR.

INTEGER

Indice di sottostringa

Posizione della sottostringa a2 nella stringa a1 Vedi nota 8

2

INDEX

CHAR.

INTEGER

66 Funzione

APPENDICE – Funzioni intrinseche standard Definizione

Numero di argomenti

Parte immaginaria di valore COMPLEX

ai

Coniugato di valore COMPLEX

(ar, -ai)

Radice quadrata

(a)1/2 Vedi nota C

1

Elevamen. di e a potenza

ea1

1

Logaritmo naturale

log (a) Vedi nota D

1

Logaritmo decimale

log10 (a) Vedi nota D

Seno

Nome generico

Nome specifico

Tipo relativo a Argomento Funzione

1

AIMAG

COMPLEX

REAL

1

CONJG

COMPLEX

COMPLEX

SQRT

SQRT DSQRT CSQRT

REAL DOUBLE COMPLEX

REAL DOUBLE COMPLEX

EXP

REAL DEXP CEXP

REAL DOUBLE COMPLEX

DOUBLE COMPLEX

LOG

ALOG DLOG CLOG

REAL DOUBLE COMPLEX

REAL DOUBLE COMPLEX

1

LOG10

ALOG10 DLOG10

REAL DOUBLE

REAL DOUBLE

sin (a) Vedi note 7, E

1

SIN

SIN DSIN CSIN

REAL DOUBLE COMPLEX

REAL DOUBLE COMPLEX

Coseno

cos (a) Vedi note 7, E

1

COS

COS DCOS CCOS

REAL DOUBLE COMPLEX

REAL DOUBLE COMPLEX

Tangente

tan (a) Vedi note 7, E

1

TAN

TAN DTAN

REAL DOUBLE

REAL DOUBLE

Arcoseno

arcsin (a) Vedi note 7, F

1

ASIN

ASIN DASIN

REAL DOUBLE

REAL DOUBLE

Arcocos.

arccos (a) Vedi note 7, G

1

ACOS

ACOS DACOS

REAL DOUBLE

REAL DOUBLE

Vedi nota 6

Vedi nota 6

67

APPENDICE – Funzioni intrinseche standard Numero di argomenti

Nome generico

Nome specifico

Tipo relativo a Argomento Funzione

Funzione

Definizione

Arcotang.

arctan (a) Vedi note 7, H

1

ATAN

ATAN DATAN

REAL DOUBLE

REAL DOUBLE

arctan (a1/a2) Vedi nota 7

2

ATAN2

ATAN2 DATAN2

REAL DOUBLE

REAL DOUBLE

Seno iperbolico

sinh (a) Vedi nota 7

1

SINH

SINH DSINH

REAL DOUBLE

REAL DOUBLE

Coseno iperbolico

cosh (a) Vedi nota 7

1

COSH

COSH DCOSH

REAL DOUBLE

REAL DOUBLE

Tangente iperbolica

tanh (a) Vedi nota 7

1

TANH

TANH DTANH

REAL DOUBLE

REAL DOUBLE

 lessicale (ASCII)

a1a2 Vedi nota 10

2

LGE

CHAR.

LOGICAL

> lessicale (ASCII)

a1>a2 Vedi nota 10

2

LGT

CHAR.

LOGICAL

 lessicale (ASCII)

a1a2 Vedi nota 10

2

LLE

CHAR.

LOGICAL

< lessicale (ASCII)

a1