Fortran: Fortran 95: Ein- und Ausgabe
| <<< zur Fortran-Startseite | |
| << Fortran 95 | Fortran 2003 >> |
| < Unterprogramme | Zeiger > |
read
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
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
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
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
| 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
Beispiel:
write(*, 100) 'abc', 10.3, 'xxx', 23.4 100 format (2(A3, F6.1))
write etwas anders
Beispiel:
write (*, 100)
100 format ('Hallo', X, 'Welt!')
Dynamische Mehrfachformatierung
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
Datensatz
Datensätze können in folgender Form auftreten:
- Formatierter Datensatz: Textdatensatz
- Unformatierter Datensatz: Datensatz in einer maschineninternen Form.
- Dateiendesatz
Datei
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
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
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
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
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
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
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
- 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 > |