Il linguaggio Fortran 90: 5. Formato di I/O e Files
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
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.
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
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*****
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
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
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
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 10.00 3.55 8.98 23.45 1.10
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
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.
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 a w
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.
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.
Istruzione OPEN OPEN (lista_open) lista_open: UNIT = espr_int FILE = espr_caratt STATUS = espr_caratt ACTION = espr_caratt IOSTAT = var_int Specificano, numero unità, nome e modalità di accesso al file
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’
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
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
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
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.
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
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
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
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 = 'input.txt' INTEGER, PARAMETER :: lunghezza_linea = 240 CHARACTER(lunghezza_linea) :: linea ! la linea letta di volta in volta INTEGER :: linee = 0 ! contatore delle linee lette INTEGER :: caratteri = 0 ! contatore dei caratteri letti INTEGER :: istatus
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
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
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
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
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
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