Fortran: Fortran 95: Ein- und Ausgabe
<<< zur Fortran-Startseite | |
<< Fortran 95 | Fortran 2003 >> |
< Unterprogramme | Zeiger > |
read
[Bearbeiten]Die read
-Anweisung dient dem Einlesen von Daten. Typisches Beispiel ist die Dateneingabe mittels Tastatur. Formal sieht eine read
-Anweisung so aus:
read([unit=]unit, [fmt=]fmt [, iostat=iostat] [, advance=advance]) [eingabeliste] |
- unit ... Nummer der Eingabeeinheit (ist systemabhängig), Sternoperator oder auch die einer Datei mittels
open
-Anweisung zugeordnete Nummer. - fmt ... Anweisungsnummer zu einer
format
-Anweisung, Sternoperator oder Formatliste - iostat ... read-Status
- advance ... siehe write
Listengesteuerte Eingabe auf der Standardeingabe (normalerweise die Tastatur):
read (*,*) a, b, c
Alternativ kann das auch so geschrieben werden:
read (unit=*, fmt=*) a, b, c
Beim Intel Fortran Compiler, gfortran und g95 ist auch unit = 5
als stdin
(Tastatur) vorbelegt. Das Einlesen aus Dateien und die Einstellung des Formates werden später erläutert.
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none integer :: i(5) ! Einlesen in ein Feld (unit ... Standardeingabe, fmt ... listengesteuert) read (*,*) i ! ... end program bsp |
Kurze Erläuterung zu iostat
:
Wert | Erläuterung |
---|---|
0 | kein Fehler |
positiver Wert (systemabhängig) | Fehler |
negativer Wert (systemabhängig) | End Of File und kein Fehler |
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none integer :: i, st ! Einlesen eines Wertes read (*, *, iostat=st) i ! Ausgabe des IO-Status write (*,*) 'IO-Status:', st end program bsp |
- Ausgabe:
- Für Eingabe: 5 → 0
- Für Eingabe: 5.3 → Positiver Wert = Fehler
Das Einlesen aus Dateien und die Einstellung des Formates werden später erläutert.
write
[Bearbeiten]Die write
-Anweisung dient der Datenausgabe. Typisches Beispiel ist die Anzeige von Daten auf dem Bildschirm. Formal sieht eine write
-Anweisung so aus:
write([unit=]unit, [fmt=]fmt [, iostat=iostat] [, advance=advance]) [ausgabeliste] |
- unit ... Nummer der Ausgabeeinheit (ist systemabhängig), Sternoperator oder auch die einer Datei mittels
open
-Anweisung zugeordnete Nummer. - fmt ... Anweisungsnummer zu einer
format
-Anweisung, Sternoperator oder Formatliste - iostat ... write-Status
- advance ... nur bei sequentieller formatierter I/O. Formatspezifizierer muss explizit gegeben sein.
'no'
... kein Vorschub des file position pointers zum nächsten Datensatz (z.B. kein Zeilenvorschub).'yes'
... mit Vorschub des file position pointers zum nächsten Datensatz (voreingestellt)
Listengesteuerte Ausgabe auf der Standardausgabe (normalerweise der Bildschirm):
write (*,*) a, b, c
Alternativ kann das auch so geschrieben werden:
write (unit=*, fmt=*) a, b, c
Beim Intel Fortran Compiler, gfortran und g95 sind auch
unit
=0 als stderr (Bildschirm) undunit
=6 als stdout (Bildschirm)
vorbelegt. Bezüglich iostat
gilt auch hier der im vorigen Abschnitt kurz geschilderte Sachverhalt.
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none integer :: i(5) = (/ 5, 4, 1, -1, -7 /) ! ... ! Ausgabe der Feldwerte (unit ... Standardausgabe, fmt ... listengesteuert) write (*,*) i ! ... end program bsp |
Beispiel: advance
Fortran 90/95-Code (free source form) |
program bsp implicit none character(10) :: ch integer :: st write(*, '(A)', advance='YES') "Hallo" write(*, '(A)', advance='YES') "Welt" write(*, *) "ABCDEFGHIJKLMN" end program bsp |
Ausgabe:
advance='YES' | advance='NO' |
---|---|
Hallo Welt ABCDEFGHIJKLMN |
HalloWelt ABCDEFGHIJKLMN |
Die Ausgabe in Dateien und die Einstellung des Formates werden etwas später erläutert.
Kürzer: print
, read
, write
und Namenslisten
[Bearbeiten]Für die listengesteuerte Ein- und Ausgabe existieren auch vereinfachte Formen. Für Eingaben wird wieder der read
-Befehl verwendet, für Ausgaben gibt es die print
-Anweisung.
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none integer :: a, b real :: r complex :: z character( len = 10 ) :: str read *, a, b, r, z, str ! Eingabe per Tastatur: ! 10, 30, 55.5, (10.8,7.0), Hallo print *, str, a, b, r, z ! Ausgabe am Bildschirm: ! Hallo 10 30 55.5 (10.8,7.) end program bsp |
Bei mehrfachem Aufruf gleicher Ein- bzw. Ausgabeanweisungen kann durch Verwendung von Namenslisten der Programmcode kürzer gestaltet werden. Die Dateneingabe wird dadurch aber etwas komplizierter:
- eingeleitet wird die Eingabe durch ein &-Zeichen, unmittelbar gefolgt vom Namenslistenbezeichner
- danach folgen ein oder mehrere Leerzeichen
- es folgen die Zuweisungen von Werten zu den Variablennamen
- abgeschlossen wird die Eingabe durch einen Slash /
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none integer :: a, b real :: r complex :: z character( len = 10 ) :: str namelist / LISTEA / a, b, r, z, str namelist / LISTEB / str, r, z read( *, nml = LISTEA ) ! Eingabe per Tastatur: ! &LISTEA b = 30, a = 10, r = 55.5, z = (10.8,7.0), str = "Hallo" / write( *, nml = LISTEB ) ! Ausgabe auf dem Bildschirm (Intel 9.1): ! &LISTEB ! STR = Hallo , ! R = 55.50000 , ! Z = (10.80000,7.000000) ! / end program bsp |
Formatierung
[Bearbeiten]Die Ein- und Ausgabeformatierung kann beeinflusst werden. Zu diesem Zweck gibt es die format
-Anweisung.
... (..., fmt = marke, ...) ... marke format (formatliste) |
Alternativ kann die Formatliste auch direkt in die read
- oder write
-Anweisung eingebunden werden
... (..., fmt = '(formatliste)', ...) ... |
Formatlistenelemente
[Bearbeiten]Formatspezifizierer | Kommentar |
---|---|
Ix[.z] | Ganzzahl mit einer Feldlänge von x Zeichen. z gibt die Mindestanzahl der auszugebenden Zeichen an (Feld wird, wenn nötig, mit führenden Nullen aufgefüllt). |
Bx[.z] | Ganzzahl, Ausgabe als Binärzahl. |
Ox[.z] | Ganzzahl, Ausgabe als Oktalzahl. |
Zx[.z] | Ganzzahl, Ausgabe als Hexadezimalzahl. |
Fx.y | Fixkommazahl mit einer Gesamtfeldlänge von x Zeichen. y ist die Anzahl der Nachkommastellen (Vorzeichen und Dezimalpunkt müssen in der Gesamtfeldlänge berücksichtigt werden). F0.y führt zu einer variablen Feldlänge in Abhängigkeit vom minimalen Platz der für die Vorkommastellen nötig ist. |
Ex.y | Gleitkommazahl mit einer Gesamtfeldlänge von x Zeichen. y ist die Anzahl der Nachkommastellen. (Vorzeichen, Dezimalpunkt und die Zeichen für den Exponenten müssen in der Gesamtfeldlänge berücksichtigt werden). |
Dx.y | Gleitkommazahl, doppelte Genauigkeit |
A | Eine Zeichenkette. |
Ax | Eine Zeichenkette mit x Zeichen. |
Lx | Ein logischer Wert, T (wahr) bzw. F (falsch). |
xX | x Leerzeichen. |
/ | Zeilenvorschub |
Tx | Tabulator (an der Position x) |
Obige Tabelle der Formatlistenelemente ist nicht vollständig; es gibt z.B. noch »G« für ein »generelles« Ausgabeformat, das aber wenig gebräuchlich ist. Die Ausgabe erfolgt normalerweise rechtsbündig. Reicht die Gesamtfeldlänge bei numerischen Werten nicht aus, so werden anstelle einer Zahl Sternchen angezeigt.
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none integer :: a a = 999 write(*, 3333) a ! Ausgabe: 999 a = -999 write (*, 3333) a ! Ausgabe: *** 3333 FORMAT (I3, /, /) ! / ... nach jeder 3333-write-Anweisung werden zwei Leerzeilen eingefügt end program bsp |
Alternativ könnte die Formatliste auch so in die write
-Anweisung eingebaut werden:
write(*, '(I3, /, /)') a
Oder mittels benannter Konstante auch so:
character(*), parameter :: fs = '(I3, /, /)' print fs, a
Hier wurde statt der write
-Anweisung der print
-Befehl verwendet. Der Effekt ist derselbe, es erfolgt eine formatierte Ausgabe.
Weitere Formatierungsbeispiele:
Code | Ausgabe |
---|---|
WRITE(*, 999) 1234 WRITE(*, 999) 1234567 WRITE(*, 999) 1234567890 999 FORMAT(I9.6) |
001234 1234567 ********* |
WRITE(*, 999) 555.6666 WRITE(*, 999) +5.6 WRITE(*, 999) -55.666E7 WRITE(*, 999) -55555.666 999 FORMAT(F9.3) |
555.667 5.600 ********* ********* |
WRITE(*, 999) 555.6666 WRITE(*, 999) +5.6 WRITE(*, 999) -55.666E7 WRITE(*, 999) -55555.666 999 FORMAT(E9.3) |
0.556E+03 0.560E+01 -.557E+09 -.556E+05 |
WRITE(*, 999) 'Hallo' WRITE(*, 999) 'ABCDEFGHIJKL' WRITE(*, 888) 'ABCDEFGHIJKL' 888 FORMAT(A) 999 FORMAT(A10) |
Hallo ABCDEFGHIJ ABCDEFGHIJKL |
WRITE(*, *) 'FORTRAN', '77' WRITE(*, 999) 'FORTRAN', '77' 999 FORMAT(A, 1X, A) |
FORTRAN77 FORTRAN 77 |
WRITE(*, 888) 'FORTRAN', '77' WRITE(*, 999) 'FORTRAN', '77' 888 FORMAT(A, T3, A) 999 FORMAT(A, T20, A) |
FO77RAN FORTRAN 77 |
WRITE(*, 999) 'FORTRAN', '77' 999 FORMAT(A, /, A) |
FORTRAN 77 |
WRITE(*, 999) 34.56 WRITE(*, *) 34.56 C SP ... Sign Plus (+) 999 FORMAT(SP, F12.3) |
+34.560 34.56 |
Wiederholung von Formatteilen
[Bearbeiten]Beispiel:
write(*, 100) 'abc', 10.3, 'xxx', 23.4 100 format (2(A3, F6.1))
write etwas anders
[Bearbeiten]Beispiel:
write (*, 100) 100 format ('Hallo', X, 'Welt!')
Dynamische Mehrfachformatierung
[Bearbeiten]Formatierungsanweisungen können auch als String bearbeitet werden, indem man z.B. die Anzahl der auszugebenden Variablen per write-Befehl in die Formatierung schreibt.
Mehrfachformatierung - Beispiel:
character(5) :: formatierung integer, dimension(1:4) :: einsen = 1 integer :: anzahl anzahl = 4 formatierung = '( I1)' write(formatierung(2:2), '(I1)') anzahl write(*, formatierung) einsen
Dateien
[Bearbeiten]Datensatz
[Bearbeiten]Datensätze können in folgender Form auftreten:
- Formatierter Datensatz: Textdatensatz
- Unformatierter Datensatz: Datensatz in einer maschineninternen Form.
- Dateiendesatz
Datei
[Bearbeiten]Für Fortran ist alles eine Datei, das durch read
oder write
bearbeitbar ist.
Zugriffsmethoden:
- Sequentieller Zugriff: Lesen ab Beginn der Datei (file) und dann immer den nächsten Datensatz einlesen. Geschrieben wird jeweils ans Dateiende. Auf interne Dateien kann nur sequentiell zugegriffen werden.
- Direkter Zugriff: Bearbeiten in beliebiger Reihenfolge durch Angabe der Satznummer.
- Binärer Zugriff: Bearbeiten von Dateien, die binäre Daten enthalten, z. B. Bilder von CCD-Kamera, Scilab/Matlab
save
-Dateien
Dateitypen:
- Externe Datei: Eine konventionelle Datei
- Interne Datei: character-Variable oder -Feld.
Dateien haben im Betriebsystem einen Dateinamen. In Fortran wird eine Datei über eine Dateinummer (unit) angesprochen. Die Zuordnung erfolgt mit dem Befehl open
.
open
[Bearbeiten]Zum Öffnen einer externen Datei dient die open
-Anweisung.
open (liste) |
mit folgender liste
Element | Kommentar |
---|---|
[unit =] x | x ist eine Dateinummer (Ganzzahl, sollte über 10 liegen, da oft Nummern unter 10 fix zugeordnet sind, z.B. der Standardein-, ausgabe). |
file = x | x ist der externe Dateiname |
iostat = x | x ist 0 wenn open fehlerfrei ausgeführt wurde, ansonsten eine systemabhängige Fehlernummer |
status = x | Dateistatus: 'old' ... Datei existiert bereits 'new' ... Datei wird neu erzeugt 'scratch' ... namenlose temporäre Datei 'unknown' ... System bestimmt Dateistatus selbst 'replace' ... der Inhalt einer bereits vorhandenen Datei wird gelöscht. |
access = x | Zugriffsmethode: 'sequential' ... Sequentielle Datei 'direct' ... direkter Zugriff 'stream' ... binärer Zugriff |
position = x | Den Dateisatzzeiger beim Öffnen der Datei an eine bestimmte Position setzen. ('asis', 'rewind', 'append') |
form = x | Format: 'formatted' oder 'unformatted' |
action = x | 'read' ... nur Lesezugriff 'write' ... nur Schreibzugriff 'readwrite' ... Lesen und Schreiben |
recl = x | Datensatzlänge (positive Zahl, access='direct', in Bytes) |
err = x | Im Fehlerfall Sprung zur Marke x |
blank = x | 'null' oder 'zero' (nur für form='formatted') |
delim = x | 'apostrophe' 'quote' 'none' |
pad = x | 'yes' oder 'no' (nur für form='formatted') |
Eingestellte Vorgabewerte sind:
- status = 'unknown'
- position = 'asis'
- access = 'sequential'
- form = 'formatted'
Wird access='direct'
gesetzt, so gilt form='unformatted'
als Vorgabewert.
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none integer :: stat character(80) :: str open(20, file='/tmp/testdatei.txt', iostat=stat) if(stat == 0) then write(*,*) 'Das Öffnen der Datei war ein voller Erfolg' do read(20, '(A)', iostat=stat) str ! Bei EOF wird stat /= 0 if (stat /= 0) exit write(*,*) str end do else write(*,*) 'Datei konnte nicht geöffnet werden' end if close(20) end program bsp |
close
[Bearbeiten]Geschlossen wird die Verbindung zur externen Datei mit dem close
-Befehl.
close (liste) |
liste:
Element | Kommentar |
---|---|
[unit =] x | wie bei open |
iostat = x | wie bei open |
err = x | wie bei open |
status = x | 'keep' ... Datei erhalten (voreingestellt) 'delete' ... Datei löschen |
Lesen und Schreiben
[Bearbeiten]Gelesen oder geschrieben wird mit den bereits bekannten read
- und write
-Anweisungen.
Element | Kommentar |
---|---|
[unit =] x | Dateinummer bzw. CHARACTER-Variable oder Feld (interne Datei) |
[fmt =] x | siehe Formatierung |
[nml] = x | x ... namelist-group-name |
rec = x | Datensatznummer bei Direktzugriff (siehe Abschnitt Direktzugriff) |
iostat = x | wie bei read
|
err = x | Bei Fehler Sprung zur Anweisungsnummer x |
end = x | Bei Dateiende Sprung zur Anweisungsnummer x (nicht erlaubt bei Direktzugriff, nicht bei write) |
advance = x | 'yes' oder 'no' |
eor = x | Bei End of Record Sprung zur Marke x (nicht bei write) |
size = x | x ... Zeichenzähler (nicht bei write, advance='no') |
Es existiert eine Menge von Einschränkungen, wann welche Elemente erlaubt sind, bzw. welche nur kombiniert auftreten sollen, z.B.
- wenn der
rec
-Spezifizierer Verwendung findet, dann darf keinend
-Element angegeben werden - Bei Dateneingabe nur dann ein
size
-Spezifizierer, wennadvance='no'
gesetzt ist.
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none character (len = 80) :: a integer :: st = 0 open (20, file='/tmp/testdatei.txt', status='OLD', iostat=st) if (st /= 0) then stop "open-Fehler!" end if ! Aus Datei lesen do read (20, 888, iostat=st) a ! Auf Standardausgabe schreiben if (st == 0) then write (*, 888) a else if (st > 0) then write (*,*) "read-Fehler!" exit else if (st < 0) then exit end if end do close(20) 888 format(A) end program bsp |
Direktzugriff
[Bearbeiten]OPEN:
Element | Kommentar |
---|---|
access = x | x ... 'DIRECT' |
recl = x | x ... Datensatzlänge (positive Zahl, access='DIRECT', in Bytes bzw. bei formatierten Dateien in Characters) |
fmt = x | x ... Formatangabe (wird eine Datei 'FORMATTED' geöffnet, dann muss auch eine konkrete Formatliste angegeben werden, ansonsten tut's auch der Sternoperator) |
READ/WRITE:
Element | Kommentar |
---|---|
REC = x | x ... Satznummer bei Direktzugriff |
Beispiel: Gegeben ist die Textdatei /tmp/testdatei.txt
mit dem Inhalt
Die WRITE-Anweisung dient der Datenausgabe aus einem FORTRAN-Programm auf ein externes Gerät. Typisches Beispiel ist die Anzeige von Daten auf dem Bildschirm. Formal sieht eine WRITE-Anweisung so aus:
Fortran 90/95-Code (free source form) |
program bsp implicit none character (len = 10) :: c integer :: st open (20, file='/tmp/testdatei.txt', status='OLD', form='FORMATTED', & access='DIRECT', recl=15, iostat=st) if (st /= 0) then stop "open-Fehler!" end if read (20, fmt='(A)', rec=4, iostat=st) c if (st /= 0) then write (*,*) "read-Error" else write (*,*) c end if close (20) end program bsp |
Ausgabe:
s einem FO
Positionieren bei sequentiellen Dateien
[Bearbeiten]Datensatzzeiger um einen Datensatz zurücksetzen:
backspace ([unit=]x [,iostat=y] [,err=z]) |
Positionieren an den Dateibeginn:
rewind ([unit=]x [,iostat=y] [,err=z]) |
Schreiben eines Dateiendsatzes:
endfile ([unit=]x [,iostat=y] [,err=z]) |
Beispiel:
Fortran 90/95-Code (free source form) |
program bsp implicit none character (len = 100), dimension(3) :: c integer :: st = 0 open (20, file='/tmp/testx.txt', status='NEW', iostat=st) call checkStatus(st, "open-") write (20,*) 'Das ist eine Testdatei' write (20,*) 'Dies ist Zeile 2 der Testdatei' write (20,*) 'Jenes die Zeile 3 der Testdatei' write (20,*) "Jetzt ist's aber genug" endfile (20) rewind (20, iostat=st) call checkStatus(st, "rewind-") read (20, fmt=555, iostat=st) c call checkStatus(st, "read-") write (*, fmt=555) c backspace (20, iostat=st) call checkStatus(st, "backspace-") read (20, fmt=555, iostat=st) c(1) call checkStatus(st, "read-") write (*, fmt=555) c(1) close (20) 555 format (A) end program bsp subroutine checkStatus(st, ch) integer, intent (in) :: st character (*), intent (in) :: ch if (st /= 0) then close(20) write (*,*) ch // "Fehler!" stop end if end subroutine checkStatus |
Ausgabe:
Das ist eine Testdatei Dies ist Zeile 2 der Testdatei Jenes die Zeile 3 der Testdatei Jenes die Zeile 3 der Testdatei
inquire
[Bearbeiten]Die Anweisung inquire
dient der Abfrage einiger Eigenschaften von Dateien oder I/O-Units.
inquire (file = x, liste) |
mit x ... Dateiname (inkl. Pfad)
inquire ([unit =] x, liste) |
mit x ... Nummer der I/O-Unit.
liste:
Element | Kommentar |
---|---|
access = x | x:
|
action = x | x:
|
blank = x | x:
|
delim = x | x:
|
direct = x | x:
|
err = x | Bei Fehler Sprung zur Anweisungsnummer x |
exist = x | x:
|
form = x | x:
|
formatted = x | x:
|
iostat = x | x ist 0 wenn OPEN fehlerfrei ausgeführt wurde, ansonsten eine systemabhängige positive Fehlernummer |
name = x | Der Dateiname wird der Zeichenketten-Variablen x zugewiesen. Hat die Datei keinen Namen, dann ist das Ergebnis undefiniert. |
named = x | x:
|
nextrec = x | x ... Nummer des nächsten Datensatzes |
number = x | x ... Nummer der mit einer externen Datei verbundenen I/O-Unit. |
opened = x | x:
|
pad = x | x:
|
position = x | x:
|
read = x | x:
|
readwrite = x | x:
|
recl = x | x ... Datensatzlänge bei Direktzugriff |
sequential = x | x:
|
unformatted = x | x:
|
write = x | x:
|
Beispiel: Datei vorhanden?
Fortran 90/95-Code (free source form) |
program bsp implicit none logical :: l integer :: st inquire (file='/tmp/testdatei.txt', exist=l, iostat=st) if (st == 0) then write (*,*) "Datei existiert?", l else write(*,*) "Fehler!" end if ! wenn Datei existiert: Datei existiert? T ! wenn Datei nicht existiert: Datei existiert? F ! wenn aus irgendeinem ein inquire-Fehler auftrat: Fehler! end program bsp |
Beispiel: Infos zu einer geöffneten Datei
Fortran 90/95-Code (free source form) |
program bsp implicit none logical :: ex character (15) :: di, fo, ac, se integer :: nu, st open (25, file='/tmp/testdatei.txt', status='old', iostat=st) if(st /= 0) stop "open-Fehler!" inquire (25, exist = ex, direct = di, sequential = se, formatted = fo, & access = ac, number = nu, iostat=st) if(st == 0) then write (*,*) 'EXIST? ', ex write (*,*) 'DIRECT? ', di write (*,*) 'SEQUENTIAL? ', se write (*,*) 'FORMATTED? ', fo write (*,*) 'ACCESS? ', ac write (*,*) 'NUMBER? ', nu else write (*,*) "inquire-Fehler!" end if close(25) ! Ausgabe, z.B. ! EXIST? T ! DIRECT? YES ! SEQUENTIAL? YES ! FORMATTED? YES ! ACCESS? SEQUENTIAL ! NUMBER? 25 end program bsp |
Interne Dateien
[Bearbeiten]- Interne Dateien sind vom Datentyp
character
(Zeichen oder Zeichenketten) - Das Lesen aus bzw. das Schreiben in interne Dateien erfolgt immer sequentiell
Beispiel: Schreiben in eine interne Datei
Fortran 90/95-Code (free source form) |
program bsp character(15) :: ch real :: r = 12.5678 ! Interne Datei "ch" write (ch, *) r write (*,*) 'r lexikalisch groesser als Buchstabe "A"? ', lge(ch, 'A') end program bsp |
Beispiel: Lesen aus einer internen Datei
Fortran 90/95-Code (free source form) |
program bsp character(15) :: ch = '12.5678' real :: r ! Interne Datei "ch" read (ch, '(F15.5)') r write (*,*) 'r = ', r write (*,*) 'r**2 = ', r**2 end program bsp |
<<< zur Fortran-Startseite | |
<< Fortran 95 | Fortran 2003 >> |
< Unterprogramme | Zeiger > |