Il linguaggio Fortran 90: 5. Formato di I/O e Files 1 Formati di I/O • READ (*,*) WRITE (*,*) : formato libero di output • Si può specificare sia l’unita di I/O che il formato dell’I/O • REAL :: x INTEGER :: i WRITE (*,100) i , x 100 FORMAT (1X, I10, F10.2) • Risultato formattato: 10 20.40 • Risultato non formattato: 10 20.403456 2 Caratteri di controllo • Il Fortran utilizza il primo carattere di stampa come carattere di controllo. 1 Stampa all’inizio di una nuova pagina spazio Interlinea singola 0 Interlinea doppia + Nessuna interlinea, stampa sulla stessa riga • Occorre quindi aggiungere sempre un carattere all’inizio dell’istruzione di Format. 3 Descrittori di formato • Descrittore I : rIw.m I: rappresentazione di valori interi r: fattore di ripetizione w: numero massimo di cifre da visualizzare m: numero minimo di cifre da visualizzare • Se il valore e’ troppo grande per essere visualizzato con un certo formato vengono stampati asterischi • I valori sono allineati a destra nei loro campi 4 Esempio INTEGER :: index = -12, junk = 4, number = -12345 WRITE(*,200) index, index + 12, junk, number WRITE(*,210) index, index + 12, junk, number WRITE(*,220) index, index + 12, junk, number 200 FORMAT (1X, 2I5, I6, I10) 210 FORMAT (1X, 2I5.0, I6, I10.8) 220 FORMAT (1X, 2I5.3, I6, I5) ||-12||||0|||||4||||-12345 ||-12||||||||||4|-00012345 |-012||000|||||4***** 5 Descrittori di formato (cont.) • rFw.d F: descrittore di tipo di dato reale d: numero di cifre a destra del punto decimale • rEw.d E: descrittore di notazione esponenziale I valori sono rappresentati con una mantissa compresa tra 0.1 e 1. Ex: 8600.6 0.86006E+4 6 Descrittori di formato (cont.) • rLw L: Descrittore di formato logico I valori logici vengono stampati come T e F LOGICAL :: a = .TRUE., b = .FALSE. WRITE (*,200) a,b 200 FORMAT(‘ ‘, 2L5) ||||T||||F 7 Descrittori di formato (cont.) • nX : inserisce n spazi nel buffer permette di controllare la spaziatura nel formato di output • Tc : permettere di raggiungere la colonna c • / : chiude il buffer corrente ed apre un nuovo buffer, va a riga nuova 8 Stampa di una matrice di reali in forma tabellare Si intende stampare una matrice di reali con i valori sulla stessa colonna allineati sulla destra -0.34 8.98 10.00 23.45 3.55 1.10 9 Stampa di una matrice di reali in forma tabellare SUBROUTINE stampa_matrice2 (a, n, m) !Scopo: Stampa di una matrice in forma tabellare ! Dichiarazione paramentri formali IMPLICIT NONE INTEGER, INTENT(IN) :: n,m REAL, DIMENSION(:,:), INTENT(IN) :: a !Dichiarazione variabili locali INTEGER :: i,j DO i = 1, n WRITE (*,100) (a(i,j), j=1,m) END DO 100 FORMAT (' ', 8F8.2) STOP END SUBROUTINE stampa_matrice2 • • Assumiamo la linea di stampa del terminale formata di 80 caratteri Se m > 8, la stampa prosegue con stesso formato alla linea successiva 10 READ Formattante • Determina le modalità con cui i dati vengono letti dal buffer di input. • Specifica l’associazione tra le posizioni dei dati nel buffer di input e le variabili in lettura in una singola istruzione READ READ (*,100) incremento 100 FORMAT (6X, I6) Salta le prime 6 colonne e registra in incremento l’intero letto da colonna 7 a colonna 12. 11 Descrittori di Formato di Input • Descrittori Standard I, F, L • Descrittore A rA: legge i caratteri in un campo di lunghezza pari alla variabile carattere rAw: legge i caratteri per una lunghezza pari aw 12 Elaborazione dei File • I dati registrati in memoria centrale sono persi al termine dell’esecuzione dell’applicazione. • I File sono dispositivi di memorizzazione permanente dei dati su supporto magnetico oppure ottico. • I file possono essere indicati come unità di I/O all’interno di un’applicazione • L’unità di I/O viene specificata con un numero intero al posto del primo * nella prima posizione di una READ o di una WRITE. 13 Apertura e Chiusura di File • Il numero di unità è associato ad un file attraverso l’istruzione OPEN. • L’istruzione CLOSE annulla l’effetto della OPEN. • Quando il file è aperto, possiamo leggere o scrivere sul file con le stesse modalità di un buffer di Input o di Output. • Alcuni numeri di unità sono riservati, in genere 5 per lo standard input, 6 per lo standard output. 14 Istruzione OPEN • OPEN (lista_open) • lista_open: – – – – – UNIT = FILE = STATUS ACTION IOSTAT espr_int espr_caratt = espr_caratt = espr_caratt = var_int • Specificano, numero unità, nome e modalità di accesso al file 15 Istruzione OPEN (cont.) • UNIT = espr_int: indica il numero dell’unità • FILE = espr_caratt: specifica il nome dell’unità da aprire • STATUS = espr_caratt: specifica lo stato dell’unità da aprire, ‘OLD’, ‘NEW’, ‘REPLACE’, ‘SCRATCH’ o ‘UNKNOWN’ 16 Istruzione OPEN (cont.) • ACTION = espr_caratt: specifica se il file deve essere aperto solo in lettura, in scrittura o entrampi le modalità, ‘READ’, ‘WRITE’ o ‘READWRITE’ • IOSTAT = var_int: se OPEN ha successo allora la variabile è 0, altrimenti ritorna un codice di errore 17 Istruzione OPEN (cont.) • Ex: File di Input. INTEGER :: ierror OPEN (UNIT = 8, FILE = ‘ESEMPIO.DAT’, STATUS = ‘OLD’, ACTION = ‘READ’, IOSTAT = ierror) OLD: file già esistente READ: file di sola lettura, operazioni di scrittura restituiscono errore 18 Istruzione OPEN (cont.) • INTEGER :: unit, ierror CHARACTER (len = 6) :: nomefile unit = 25 Nome_file = ‘OUTDAT’ OPEN (UNIT = unit, FILE = nome_file, STATUS = ‘NEW’, ACTION = ‘WRITE’, IOSTAT = ierror) NEW: il file non esiste precedentemente • OPEN (UNIT = unit, FILE = nome_file, STATUS = ‘REPLACE’, ACTION = ‘WRITE’, IOSTAT = ierror) REPLACE: il file se esiste viene sostituito 19 Istruzione OPEN (cont.) • OPEN (UNIT = unit, FILE = nome_file, STATUS = ‘SCRATCH’, ACTION = ‘READWRITE’, IOSTAT = ierror) SCRATCH: il file viene aperto durante l’esecuzione del programma ed eliminato al termine. Serve per memorizzare risultati temporanei. 20 Istruzione CLOSE • CLOSE (lista_close) • Libera l’associazione tra numero di unità e file. Il file puo’ essere riaperto se non SCRATCH anche con un diverso numero di unità. • lista_close indica il numero dell’unità da chiudere 21 Somma degli elementi di un File ! File: sommafil.for ! Scopo: primo esempio di uso di file in sola lettura PROGRAM somma_file ! Questo programma legge un file che contiene numeri interi e ne ! calcola la somma. Il file ha nome fisico 'dati.txt‘ ! Su ogni riga di ‘dati.txt’ viene letto un solo intero. ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE CHARACTER(12), PARAMETER :: nome_file = 'dati.txt' INTEGER :: dato ! il dato letto di volta in volta INTEGER :: quanti = 0 ! contatore degli interi letti INTEGER :: somma = 0 ! somma degli interi letti INTEGER :: istatus ! stato I/O 22 Somma degli elementi di un File (cont.) ! apertura del file in sola lettura WRITE(*,*) 'Leggo dal file ', nome_file OPEN (UNIT = 9, FILE = nome_file, STATUS = 'OLD', ACTION = & 'READ',IOSTAT = istatus) IF (istatus == 0) THEN ! il file e' stato aperto correttamente DO READ (9,*,IOSTAT = istatus) dato ! lettura di un dato da file IF (istatus /= 0) EXIT ! si esce quando il file e' terminato WRITE(*,*) dato quanti = quanti + 1 somma = somma + dato END DO WRITE(*,*) 'Il file e'' composto di ', quanti, ' dati' WRITE(*,*) 'La somma dei dati vale ', somma ELSE ! il file non e' stato aperto correttamente WRITE(*,*) 'Il file ', nome_file, 'non esiste' END IF STOP END PROGRAM somma_file 23 Calcolo del numero di caratteri in un file ! File: conta.for ! Scopo: altro esempio di uso di file in sola lettura PROGRAM leggi_file ! Questo programma legge un file di testo e conta di quanti caratteri e ! quante linee e' composto. Il file ha nome fisico 'input.txt' ! Il programma legge una riga del file per ogni iterazione, ! immagazzinandola in una stringa di lunghezza fissata (240). ! Vengono usati alcuni aspetti peculiari delle stringhe: ! - lettura formattata con descrittore di formato A (legge tutta la ! linea) ! - funzione intrinseca LEN_TRIM(s), che restituisce la lunghezza della ! stringa s meno gli spazi vuoti finali ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE CHARACTER(12), PARAMETER :: nome_file INTEGER, PARAMETER :: lunghezza_linea CHARACTER(lunghezza_linea) :: linea ! INTEGER :: linee = 0 ! INTEGER :: caratteri = 0 ! INTEGER :: istatus = 'input.txt' = 240 la linea letta di volta in volta contatore delle linee lette contatore dei caratteri letti 24 Calcolo del numero di caratteri in un file (cont.) ! *** SEZIONE ESECUTIVA *** ! WRITE(*,*) 'Leggo dal file ', nome_file OPEN (UNIT = 9, FILE = nome_file, STATUS = 'OLD', ACTION = & &'READ', IOSTAT = istatus) IF (istatus == 0) THEN DO READ (9,100,IOSTAT = istatus) linea ! LETTURA di una linea da file IF (istatus /= 0) EXIT WRITE(*,*) linea(1:LEN_TRIM(linea)) linee = linee + 1 caratteri = caratteri + LEN_TRIM(linea) END DO WRITE(*,*) 'Il file e'' composto di ', linee, ' linee' WRITE(*,*) 'e di ', caratteri, ' caratteri' ELSE WRITE(*,*) 'Il file ', nome_file, 'non esiste' END IF STOP 100 FORMAT(A) END PROGRAM leggi_file 25 File in Scrittura ! File: util-for.for MODULE operazioni_su_file ! Questo modulo contiene alcune unita' che effettuano operazioni su ! file. ! - copia_file: copia un file in un altro file ! - stampa_file: stampa un file su schermo CONTAINS SUBROUTINE copia_file(sorgente,destinazione) ! *** SEZIONE DICHIARATIVA IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI CHARACTER(len=*), INTENT(IN) :: sorgente, destinazione ! nomi fisici dei file ! ** DICHIARAZIONE COSTANTI E VARIABILI LOCALI INTEGER, PARAMETER :: lunghezza_linea = 240 ! la lunghezza di linea massima ammessa CHARACTER(lunghezza_linea) :: linea ! la linea letta di volta in volta INTEGER :: istatus 26 File in Scrittura (cont.) WRITE(*,*) 'Sto copiando il file ', sorgente, ' nel file ', destinazione ! apertura del file sorgente in lettura OPEN (UNIT = 9, FILE = sorgente, STATUS = 'OLD', ACTION = 'READ', & & IOSTAT = istatus) IF (istatus == 0) THEN ! apertura del file destinazione in scrittura OPEN (UNIT=10, FILE=destinazione, STATUS='REPLACE', ACTION='WRITE') DO READ (9,100,IOSTAT = istatus) linea ! LETTURA di una linea da file IF (istatus /= 0) EXIT WRITE(10,*)linea(1:LEN_TRIM(linea)) END DO CLOSE(9) CLOSE(10) ELSE WRITE(*,*) 'Il file ', sorgente, 'non esiste' END IF 27 File in Scrittura (cont.) WRITE(*,*) 'Copia terminata' RETURN 100 FORMAT(A) END SUBROUTINE copia_file SUBROUTINE stampa_file(nome_file) ! *** SEZIONE DICHIARATIVA *** ! IMPLICIT NONE ! ** DICHIARAZIONE ARGOMENTI FITTIZI CHARACTER(len=*), INTENT(IN) :: nome_file ! ** DICHIARAZIONE VARIABILI LOCALI INTEGER, PARAMETER :: lunghezza_linea = 240 CHARACTER(lunghezza_linea) :: linea ! la linea letta di volta in volta INTEGER :: istatus 28 File in Scrittura (cont.) ! *** SEZIONE ESECUTIVA *** ! OPEN (UNIT = 9, FILE = nome_file, STATUS = 'OLD', ACTION = 'READ',& & IOSTAT = istatus) IF (istatus == 0) THEN WRITE(*,*) 'Contenuto del file ', nome_file DO READ (9,100,IOSTAT = istatus) linea ! LETTURA di una linea da file IF (istatus /= 0) EXIT WRITE(*,*) linea(1:LEN_TRIM(linea)) END DO CLOSE(9) WRITE(*,*) 'Fine file ', nome_file ELSE WRITE(*,*) 'Il file ', nome_file, 'non esiste' END IF RETURN 100 FORMAT(A) END SUBROUTINE stampa_file END MODULE operazioni_su_file 29 File in scrittura (cont.) ! File: copia.for PROGRAM prova_operazioni_su_file ! Questo programma verifica le unita' del modulo operazioni_su_file ! nel file util-fil.for ! *** SEZIONE DICHIARATIVA *** ! USE operazioni_su_file IMPLICIT NONE CHARACTER(12) :: nome_input, nome_output ! *** SEZIONE ESECUTIVA *** ! ! acquisizione dei nomi dei file WRITE(*,*) 'Inserisci il nome del file da cui leggere: ' READ (*,*) nome_input WRITE(*,*) 'Inserisci il nome del file su cui scrivere: ' READ (*,*) nome_output ! prova delle subroutine CALL copia_file(nome_input,nome_output) CALL stampa_file(nome_output) STOP END PROGRAM prova_operazioni_su_file 30