Introduzione all'Input/Output in Fortran
Le istruzioni di input e output in formato libero in Fortran offrono un metodo flessibile per leggere e scrivere dati senza la necessità di specificare un formato fisso.
Grazie a READ (*,*)
e WRITE (*,*)
, il programma determina automaticamente il formato basandosi sul tipo delle variabili coinvolte.
Questa tecnica semplifica la gestione dei dati, ma richiede attenzione all'ordine e al tipo dei valori forniti in input per evitare errori di runtime. Esploreremo il loro funzionamento con esempi pratici, analizzeremo le buone pratiche per garantire dati corretti e vedremo le limitazioni dell'output generato senza formattazione avanzata.
Istruzioni di Input/Output
Un'istruzione di input legge uno o più valori da un dispositivo di input e li memorizza in variabili specificate dal programmatore. Il dispositivo di input potrebbe essere una tastiera in un ambiente interattivo o un file su disco in un ambiente batch.
Un'istruzione di output scrive uno o più valori su un dispositivo di output. Il dispositivo di output potrebbe essere uno schermo in un ambiente interattivo o un file di output in un ambiente batch.
Iniziamo ad analizzare nel dettaglio le istruzioni di input e di output fornite dal linguaggio Fortran.
Istruzione READ
per l'input
Abbiamo già visto istruzioni di input e output nei programmi delle lezioni precedenti, come mostrato nel codice che segue:
READ (*,*) input_list
Dove input_list
è l'elenco delle variabili in cui vengono memorizzati i valori letti. Se ci sono più variabili nella lista, devono essere separate da virgole. Le parentesi (*,*)
nella dichiarazione contengono informazioni di controllo per la lettura:
- Il primo asterisco indica che i dati devono essere letti dal dispositivo standard del computer (di solito la tastiera in modalità interattiva).
- Il secondo asterisco specifica il formato in cui i dati devono essere letti (i formati saranno spiegati nelle prossime lezioni). L'asterisco in questo campo indica che deve essere utilizzato l'input guidato dalla lista (chiamato anche input in formato libero).
Il termine input in formato libero significa che i tipi delle variabili nell'elenco determinano il formato richiesto dei dati di input. Ad esempio, consideriamo le seguenti istruzioni:
PROGRAM input_example
INTEGER :: i, j
REAL :: a
CHARACTER(len=12) :: chars
READ (*,*) i, j, a, chars
END PROGRAM input_example
I dati di input forniti al programma devono consistere in due numeri interi, un numero reale e una stringa di caratteri, e devono essere in questo ordine.
I valori possono essere su una sola riga separati da virgole o spazi, oppure su righe separate.
L'istruzione di lettura continuerà a leggere i dati di input fino a quando non verranno trovati valori per tutte le variabili nell'elenco. Se i dati di input forniti al programma al momento dell'esecuzione sono:
1, 2, 3., 'Ciao'
- La variabile
i
verrà riempita con1
- La variabile
j
verrà riempita con2
- La variabile
a
verrà riempita con3.0
- La variabile
chars
verrà riempita con'Ciao '
(gli spazi alla fine sono dovuti al fatto chechars
ha una lunghezza di 12 caratteri e i caratteri rimanenti vengono riempiti con spazi).
Nota che per le letture in formato libero, le stringhe di caratteri di input devono essere racchiuse tra virgolette singole o doppie se contengono spazi.
Quando si utilizza l'input in formato libero, i valori da leggere devono corrispondere alle variabili nell'elenco di input sia per ordine che per tipo. Se i dati di input fossero stati:
1, 2, 'Ciao', 3.
si sarebbe verificato un errore di runtime quando il programma avrebbe tentato di leggere i dati.
Lettura e gestione delle linee di input
Ogni istruzione READ
in un programma inizia la lettura da una nuova riga di dati in input. Se rimangono dati inutilizzati dalla riga di input precedente, questi vengono scartati. Ad esempio, consideriamo il seguente programma:
PROGRAM input_example_2
INTEGER :: i, j, k, l
READ (*,*) i, j
READ (*,*) k, l
END PROGRAM input_example_2
Se i dati di input forniti al programma sono:
1, 2, 3, 4
5, 6, 7, 8
Dopo l'esecuzione delle istruzioni READ
, le variabili conterranno i seguenti valori:
- i
= 1
- j
= 2
- k
= 5
- l
= 6
I valori 3
e 4
della prima riga di input non vengono mai utilizzati. Così come i valori 7
e 8
della seconda.
Stampare il contenuto dell'input dopo averlo ricevuto: Echo
È consigliabile ripetere (echo) ogni valore letto da una tastiera con un'istruzione WRITE
dopo la lettura.
Questo aiuta a verificare che il valore sia stato digitato e processato correttamente. Se un errore di battitura si verifica nei dati di input, potrebbe causare una risposta errata, e l'utente del programma non si accorgerebbe dell'errore.
La ripetizione del valore può avvenire subito dopo la lettura o più avanti nell'output del programma, ma ogni variabile di input dovrebbe essere riportata da qualche parte nell'output del programma.
Istruzione WRITE
per l'output
L'istruzione di output guidata dalla lista ha la forma:
WRITE (*,*) output_list
Dove output_list
è l'elenco degli elementi di dati (variabili, costanti o espressioni) da scrivere.
Se c'è più di un elemento, questi devono essere separati da virgole. Le parentesi (*,*)
contengono informazioni di controllo per l'output e hanno lo stesso significato che per l'input in formato libero. Li analizzeremo nel dettaglio nelle prossime lezioni.
Un'altra forma equivalente di istruzione di output guidata dalla lista è:
PRINT *, output_list
Questa istruzione è equivalente a WRITE (*,*)
ed è usata in alcuni programmi. La analizzeremo più avanti
Esempio
Il termine output in formato libero significa che i tipi dei valori nell'elenco di output determinano il formato dei dati in output.
Ad esempio, consideriamo il seguente programma:
PROGRAM output_example
INTEGER :: ix
REAL :: theta
ix = 1
test = .TRUE.
theta = 3.141593
WRITE (*,*) 'IX = ', ix
WRITE (*,*) 'THETA = ', theta
WRITE (*,*) 'COS(THETA) = ', COS(theta)
WRITE (*,*) REAL(ix), NINT(theta)
END PROGRAM output_example
L'output risultante sarà:
IX = 1
THETA = 3.141593
COS(THETA) = -1.000000
1.000000 3
Questo esempio illustra diversi aspetti dell'output in formato libero:
- L'elenco di output può contenere costanti (
'IX = '
), variabili, funzioni ed espressioni. In ogni caso, il valore viene scritto nel dispositivo di output standard (nella maggior parte dei casi è la console). - Il formato dell'output corrisponde al tipo del valore in output. Ad esempio,
theta
è un valore reale, maNINT(theta)
è un valore intero e produce3
come output (l'intero più vicino a3.141593
). - L'output generato da
WRITE (*,*)
non è particolarmente ben allineato. I valori non sono allineati in colonne nette e non vi è alcun controllo sul numero di cifre significative visualizzate per i numeri reali. Nelle prossime lezioni verranno illustrate tecniche per produrre output più leggibili e ben formattati.
In Sintesi
In questa lezione abbiamo studiato che:
- Le istruzioni di input e output in formato libero permettono di leggere e scrivere dati senza specificare esplicitamente il formato, basandosi sul tipo delle variabili.
- L'input deve rispettare l'ordine e il tipo delle variabili elencate nell'istruzione
READ (*,*)
per evitare errori di esecuzione. - Le istruzioni
READ (*,*)
eWRITE (*,*)
gestiscono rispettivamente la lettura e la scrittura di dati, eliminando la necessità di formattazione manuale. - I dati inutilizzati vengono scartati automaticamente, poiché ogni istruzione
READ
inizia da una nuova riga di input. - Ripetere i valori letti nell'output è una buona pratica, perché consente di verificare che i dati siano stati immessi correttamente.
- L'output generato con
WRITE (*,*)
può risultare poco leggibile, poiché non allinea i valori in colonne nette né controlla il numero di cifre significative nei numeri reali.