7. Entrées-Sorties▲
7-1. Introduction▲
On appelle entrée-sortie, un transfert d'informations entre la mémoire de l'ordinateur et l'un de ses périphériques (un disque le plus souvent).
Une entrée se traduit par une lecture d'informations du périphérique vers la mémoire, tandis qu'une sortie implique une écriture de la mémoire vers le périphérique.
Ces informations sont stockées dans un fichier qui possède un nom.
L'unité de transmission entre la mémoire et le périphérique s'appelle le bloc. Il permet d'effectuer le traitement en passant par une zone intermédiaire dite zone tampon (buffer) permettant ainsi de limiter le nombre de transferts entre la mémoire et le périphérique : opération coûteuse.
L'unité de traitement est l'enregistrement logique : il correspond à la longueur des données traitées lors d'une opération de lecture-écriture.
L'exploitation d'un fichier au sein d'un programme nécessite au préalable son ouverture qui, en Fortran, est faite au moyen de l'instruction OPEN.
Cette instruction permet notamment :
- de connecter le fichier à un numéro d'unité logique : c'est celui-ci que l'on indiquera par la suite pour toute opération de lecture-écriture ;
- de spécifier le mode désiré : lecture, écriture ou lecture-écriture ;
- d'indiquer le mode de transfert : avec ou sans conversion en caractères ;
- d'indiquer le mode d'accès au fichier : séquentiel ou direct.
Si l'ouverture du fichier est fructueuse, des lectures-écritures pourront être lancées à l'aide des instructions READ
/WRITE
par l'intermédiaire du numéro d'unité logique.
Une fois le traitement du fichier terminé, on le fermera au moyen de l'instruction CLOSE
.
7-2. Accès séquentiel▲
On dit qu'un fichier est séquentiel lorsqu'il est nécessaire d'avoir traité les enregistrements précédant celui auquel on désire accéder.
Pour un fichier en lecture le paramètre IOSTAT de l'instruction READ
permet de gérer la fin de fichier, celui-ci fait référence à une variable entière qui est valorisée à l'issue de la lecture comme suit :
- à 0 si la lecture s'est bien déroulée ;
- à une valeur positive si une erreur s'est produite ;
- à une valeur négative si la fin de fichier ou une fin d'enregistrement à été rencontrée.
On prendra soin de tester la valeur de cette variable immédiatement après chaque lecture.
7-2-1. Fichier binaire séquentiel▲
On appelle fichier binaire un fichier dans lequel on stocke les informations telles qu'elles sont représentées en mémoire.
C'est au moment de l'ouverture du fichier que l'on indique le type de fichier à traiter.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
real
, dimension
(100) :: tab
integer
:: i
real
:: r
integer
:: ios
OPEN
( UNIT=1, &
FILE="data_bin_seq"
, &
FORM="unformatted"
, &
ACCESS="sequential"
, &
ACTION="read"
, &
POSITION="rewind"
, &
IOSTAT=ios )
if
( ios /=
0 ) stop
"Problème à l'ouverture"
READ
( UNIT=1, IOSTAT=ios ) tab, i, r
do
while
( ios ==
0 )
...
READ
( UNIT=1, IOSTAT=ios ) tab, i, r
end
do
CLOSE
( UNIT=1 )
On demande l'ouverture du fichier dont le nom est data_bin_seq. C'est un fichier binaire séquentiel (unformatted, sequential) que l'on désire lire depuis le début (rewind
).
Ce fichier est connecté à l'unité logique dont le numéro est 1. C'est ce numéro que l'on indique au moment de la lecture des variables tab, i, r, ainsi qu'à la fermeture du fichier.
L'entier ios contient le code retour de l'OPEN
: il est nul si tout s'est bien passé, non nul sinon. Il est vivement conseillé de le tester avant toute opération de lecture ou d'écriture.
Ce même entier est utilisé au sein de l'instruction READ
afin de connaître l'état de la lecture.
7-2-2. Fichier texte séquentiel▲
Dans un fichier texte, les données sont stockées sous forme de caractères. De ce fait :
- lors d'une lecture, elles sont converties en binaire avant d'être rangées en mémoire ;
- lors d'une écriture, elles sont converties en caractères avant d'être écrites dans le fichier.
Cette opération de conversion est signalée au sein des instructions READ
/WRITE
:
- à l'aide d'une chaîne de caractères appelée format d'édition (paramètre FMT=) ;
- ou bien en utilisant un nom de liste (NAMELIST) regroupant les variables que l'on désire exploiter (paramètre NML=).
7-2-2-a. Formats d'édition▲
Pour que la conversion puisse être faite, il est nécessaire de connaître le type de la donnée à convertir.
Pour cela le format d'édition contient des descripteurs :
- descripteur I pour le type
INTEGER
; - descripteurs F, E pour le type
REAL
; - descripteur L pour le type
LOGICAL
; - descripteur A pour le type
CHARACTER
.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
PROGRAM
texte_sequentiel
real
, dimension
(10) :: tab
integer
:: i
real
:: r
integer
:: ios
OPEN
( UNIT=1, &
FILE="data_txt_seq"
, &
FORM="formatted"
, &
ACCESS="sequential"
, &
STATUS="old"
, &
ACTION="write"
, &
POSITION="rewind"
, &
IOSTAT=ios )
if
( ios /=
0 ) then
! Problème à l'ouverture
...
else
WRITE
( UNIT=1, &
FMT='(10F8.4,I3,F6.3)'
) tab, i, r
...
endif
...
CLOSE
( UNIT=1 )
END
PROGRAM
texte_sequentiel
Dans cet exemple, on demande l'ouverture du fichier dont le nom est data_txt_seq. C'est un fichier texte séquentiel (formatted, sequential) existant (old) que l'on désire écraser (rewind
).
Comme précédemment, à l'issue de l'OPEN
on teste la valeur de retour contenue dans l'entier ios.
Si l'ouverture s'est bien passée on lance, à l'aide de l'instruction WRITE
, l'écriture en caractères d'un enregistrement comportant un tableau de réels (tab) suivi d'un entier puis d'un réel (i, r).
Le format d'édition spécifié sous la forme d'une constante chaîne de caractères ('(10F8.4,I3,F6.3)'
) permet de convertir en caractères les variables ci-dessus :
- 10F8.4 : écriture des 10 éléments du tableau tab.
Chacun a un gabarit de 8 caractères avec 4 chiffres en partie décimale,
- I3 : écriture de l'entier i sur 3 caractères ;
- F6.3 : écriture du réel r sur 6 caractères avec 3 chiffres en partie décimale.
7-2-2-b. Formats d'édition en lecture▲
- Iw permet la conversion des w caractères suivants dans le type
INTEGER
. - Fw.d : permet la conversion des w caractères suivants dans le type
REAL
. Si le point décimal n'est pas présent alors lesd
derniers caractères désignent la partie fractionnaire. - Ew.d : permet la conversion des w caractères suivants (interprétés comme un nombre réel en notation exponentielle) dans le type
REAL
. - Lw : permet la conversion des w caractères suivants dans le type
LOGICAL
. - A[w] : permet de lire des caractères.
Exemples
Dans ce qui suit le caractère ^ représente l'espace. Les différentes entrées présentées sont supposées figurer dans un fichier texte séquentiel connecté à l'unité 1 après un OPEN
.
Format d'édition I en lecture
2.
3.
4.
INTEGER
i, j
...
READ
( UNIT=1, FMT='(I5,I4)'
) i, j
...
Entrées |
Affectations |
---|---|
^^45^^^9^ |
i=45, j=9 |
^-24^10^^ |
i=-24, j=10 |
À noter : dans un champ en entrée, l'espace est ignoré.
Formats d'édition F, E et D en lecture
Ce format a la forme générale : Fw.d , Ew.d ou bien Dw.d.
Le nombre réel à lire peut être soit en notation virgule fixe, soit exponentielle avec, dans ce dernier cas, l'exposant préfixé de la lettre E ou D
.
Le point décimal peut ne pas figurer :
- s'il est spécifié alors le nombre indiqué par
d
est ignoré, c'est le nombre de décimales figurant en entrée qui est pris en compte ; - s'il est omis c'est le nombre indiqué par
d
qui est considéré.
2.
3.
4.
REAL
x, y
...
READ
( UNIT=1, FMT='(F4.1,F6.2)'
) x, y
...
Entrées |
Affectations |
---|---|
^3.1-3.141 |
x=3.1, y=-3.141 |
^123^^5678 |
x=12.3, y=56.78 |
2.
3.
4.
5.
6.
REAL
x
...
READ
( UNIT=1, FMT='(E12.6)'
) x
! ou bien
READ
( UNIT=1, FMT='(F12.6)'
) x
...
Entrées |
Affectations |
---|---|
2.718281^^^^ |
x=2.718281 |
2718281^^^^^ |
x=2.718281 |
27.18281d-1^ |
x=2.718281 |
.2718281e+1^ |
x=2.718281 |
.2718281^e^1 |
x=2.718281 |
^^^^^2718281 |
x=2.718281 |
^^^^^^^^^271 |
x=0.000271 |
Format d'édition L en lecture
Ce format a la forme générale : Lw.
Ce type de format permet la lecture de valeurs logiques.
Le caractère w indique comme précédemment la largeur du champ en entrée. Celui-ci doit comporter comme premier caractère non blanc l'une des lettres F, f, T ou t éventuellement précédée du caractère '.'
. N'importe quels caractères peuvent compléter le champ.
2.
3.
4.
LOGICAL
l1, l2
...
READ
( UNIT=1, FMT='(L6,L7)'
) l1, l2
...
Entrées |
Affectations |
---|---|
.true..false. |
l1=.TRUE., l2=.FALSE. |
^^^^t..FACILE |
l1=.TRUE., l2=.FALSE. |
t^^^^^F^^^^^^ |
l1=.TRUE., l2=.FALSE. |
Format d'édition A en lecture
Ce format a la forme générale : A[w].
Ce type de format permet la lecture de caractères. La valeur w indique le nombre de caractères que l'on désire traiter en entrée :
- si la valeur de w est plus grande que la longueur l de la chaîne réceptrice, ce sont les l caractères les plus à droite qui seront lus ;
- si elle est plus petite, w caractères seront lus et stockées dans la chaîne réceptrice qui sera complétée à droite par des blancs ;
- si elle n'est pas précisée, c'est la longueur spécifiée lors de la déclaration de la chaîne de caractères qui indiquera le nombre de caractères à lire. Si la fin de l'enregistrement est atteinte avant la fin de la lecture, la chaîne est complétée par des blancs.
2.
3.
4.
5.
6.
CHARACTER
(len
=7) :: ch1, ch2
...
READ
( UNIT=1, FMT='(A6,A8)'
) ch1, ch2
READ
( UNIT=1, FMT='(A6,A8)'
) ch1, ch2
READ
( UNIT=1, FMT='(A,A)'
) ch1, ch2
...
Entrées |
Affectations |
---|---|
BACH^^^^BACH^^ |
ch1=« BACH^^^ »,ch2=« ^BACH^^ » |
MOZARTHAENDEL^ |
ch1=« MOZART^ »,ch2=« AENDEL^ » |
MOZARTHAENDEL^ |
ch1=« MOZARTH »,ch2=« AENDEL^ » |
7-2-2-c. Formats d'édition en écriture▲
- Iw [.d] : permet l'édition d'une variable de type
INTEGER
sur w caractères. S'il est présentd
indique le nombre minimum de chiffres édités : si nécessaire des 0 apparaîtront en tête du nombre. - Fw.d : permet l'édition d'une variable de type
REAL
sur w caractères comprenant le point décimal suivi ded
chiffres pour la partie fractionnaire. - Ew.d : idem format F, mais la sortie est faite en notation exponentielle.
- Lw : permet l'édition d'une variable de type
LOGICAL
sur w caractères. - A[w] : permet l'édition d'une variable de type
CHARACTER
.
Format d'édition I en écriture
2.
3.
4.
5.
6.
7.
8.
INTEGER
i, j, k
i = -125
j = 1756
k = 1791
WRITE
( UNIT=1, FMT='(I4,I4,I4)'
) i, j, k
WRITE
( UNIT=1, FMT='(I5,I6,I6)'
) i, j, k
WRITE
( UNIT=1, FMT='(I6.5,I6.6,I6.6)'
) i, j, k
Sorties |
---|
-12517561791 |
^-125^^1756^^1791 |
-00125001756001791 |
Format d'édition F en écriture
2.
3.
4.
5.
6.
7.
8.
9.
REAL
x, y, z
x = 3.14159
y = -15.137
z = 799.7432
WRITE
( UNIT=1, &
FMT='(F7.5,F8.3,F9.4)'
) x, y, z
WRITE
( UNIT=1, &
FMT='(F6.2,F9.4,F10.5)'
) x, y, z
Sorties |
---|
3.14159^-15.137^799.7432 |
^^3.14^-15.1370^799.74323 |
Remarque
En ce qui concerne les formats(1) d'écriture I, B, O, Z et F, lorsque le gabarit de la zone réceptrice est insuffisant celle-ci est remplie par le caractère *
. Depuis la norme Fortran 95, il est possible d'éviter cela en indiquant 0 comme largeur de zone.
2.
3.
4.
5.
6.
7.
8.
9.
10.
PROGRAM
gabarit
INTEGER
I
REAL
R
I = 129876
R = -2345.78
WRITE
( UNIT=1, FMT='(I4, F6.3)'
) I, R
WRITE
( UNIT=1, FMT='(I0, F0.3)'
) I, R
END
PROGRAM
gabarit
Sorties |
---|
********** |
129876-2345.780 |
Format d'édition E et D en écriture
Avec les formats Ew.d, Dw.d on obtiendra en sortie le motif :
S0.XXXXXXXESXX, S0.XXXXXXXDSXX
<--d--> <--d-->
<-----w------> <-----w------>
Le caractère S indique une position pour le signe.
Un facteur d'échelle peut précéder ce type de format. Il s'écrit sous la forme kP et permet d'éditer le nombre avec kitxmlcodeinlinelatexdvpkfinkitxmlcodeinlinelatexdvp chiffres avant le point décimal (modifie en conséquence la valeur de l'exposant).
Si kitxmlcodeinlinelatexdvp−d < k \le 0finkitxmlcodeinlinelatexdvp, la partie décimale sera constituée de kitxmlcodeinlinelatexdvp|k|finkitxmlcodeinlinelatexdvp zéros suivis de kitxmlcodeinlinelatexdvpd − |k|finkitxmlcodeinlinelatexdvp chiffres significatifs.
Si kitxmlcodeinlinelatexdvp0 < k < d + 2finkitxmlcodeinlinelatexdvp, le nombre en sortie sera constitué de kitxmlcodeinlinelatexdvpkfinkitxmlcodeinlinelatexdvp chiffres significatifs avant le point décimal et de kitxmlcodeinlinelatexdvpd − k + 1finkitxmlcodeinlinelatexdvp chiffres significatifs en partie décimale.
Toute autre valeur de kitxmlcodeinlinelatexdvpkfinkitxmlcodeinlinelatexdvp est invalide : dans ce cas, la zone en sortie sera remplie par le caractère ∗.
Celui-ci s'applique à tous les formats E qui suivent. Pour retrouver le comportement par défaut, il suffit de préciser le facteur 0P.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
REAL
x, y, z
DOUBLE
PRECISION
xd, yd, zd
x = 3.14159; xd = 3.14159d0
y = -15.137; yd = -15.137d0
z = 799.74328; zd = 799.74328d0
WRITE
( UNIT=1, &
FMT='(D12.6,E13.5,E15.8)'
) x, y, z
WRITE
( UNIT=1, &
FMT='(4P,D12.6,E13.5,0P,E10.3)'
) x, y, z
WRITE
( UNIT=1, &
FMT='(D12.6,E13.5,E15.8)'
) xd, yd, zd
WRITE
( UNIT=1, &
FMT='(4P,D12.6,E13.5,0P,E15.8)'
) xd, yd, zd
Sorties |
---|
0.314159D+01^-0.15137E+02^0.79974329E+03 |
3141.590D-03^-1513.70E-02^0.800E+03 |
0.314159D+01^-0.15137E+02^0.79974328E+03 |
3141.590D-03^-1513.70E-02^0.79974328E+03 |
Il existe deux variantes du format E qui correspondent aux descripteurs EN et ES. Le facteur d'échelle kP ne peut être appliqué dans ce contexte.
Le descripteur EN permet la sortie d'un réel en notation dite ingénieure. Dans ce type de représentation, la valeur absolue de la partie entière est supérieure ou égale à 1 et inférieure à 1000 et l'exposant est divisible par 3.
2.
3.
4.
5.
6.
7.
REAL
x, y, z, t
x = 6.421
y = -.5
z = .00217
t = 4721.3
WRITE
( UNIT=1, &
FMT='(EN12.3,EN12.3,EN12.3,EN12.3)'
) x, y, z, t
Sorties |
---|
^^^6.421E+00-500.000E-03^^^2.170E-03^^^4.721E+03 |
Le descripteur ES permet la sortie d'un réel en notation dite scientifique. Dans ce type de représentation, la valeur absolue de la partie entière est supérieure ou égale à 1 et inférieure à 10.
2.
3.
4.
5.
6.
7.
REAL
x, y, z, t
x = 6.421
y = -.5
z = .00217
t = 4721.3
WRITE
( UNIT=1, &
FMT='(ES12.3,ES12.3,ES12.3,ES12.3)'
) x, y, z, t
Sorties |
^^^6.421E+00^^-5.000E-01^^^2.170E-03^^^4.721E+03 |
Par défaut, la présence du signe + pour les données numériques positives dépend du compilateur. Il existe des descripteurs permettant de forcer sa présence ou bien de le supprimer :
- SS (sign suppress) : le signe + n'apparaît pas ;
- SP (sign print) : le signe + précède la donnée ;
- S : restauration du mode par défaut.
2.
3.
4.
5.
6.
7.
8.
INTEGER
i, j
REAL
x, y
i = 1756
j = -69
x = 6.421
y = .00217
WRITE
( UNIT=1, &
FMT='(SP,F7.3,SS,ES12.3,I4,SP,I6)'
) x, y, j, i
Sorties |
---|
^+6.421^^^2.170E-03^-69^+1756 |
Format d'édition L en écriture
Ce format a la forme générale : Lw.
Ce type de format permet l'écriture de valeurs logiques.
En sortie on obtiendra w-1 blancs suivis de la lettre T pour une valeur .true.
et F pour une valeur .false.
.
2.
3.
4.
LOGICAL
l1/.true.
/, l2/.false.
/
...
WRITE
( UNIT=1, FMT='(L6,L7)'
) l1, l2
...
Sorties |
---|
^^^^^T^^^^^^F |
Format d'édition A en écriture
Le format A[w] permet la sortie de chaînes de caractères. La valeur w est facultative. Si elle est précisée, elle indique la largeur de la zone réceptrice :
- si la valeur de w est plus grande que la longueur l de la chaîne, en sortie celle-ci apparaîtra précédée de w-l blancs ;
- si elle est plus petite, seuls les w caractères les plus à gauche de la chaîne seront écrits ;
- si la valeur w est absente, c'est la longueur de la chaîne spécifiée à la déclaration qui indique la largeur du champ en sortie.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
CHARACTER
(len
=9) :: ch1, ch2, ch3
...
ch1 = "BEETHOVEN"
ch2 = "PUCCINI"
ch3 = "VERDI"
WRITE
( UNIT=1, FMT='(A9,A8,A6,A)'
) ch1, &
ch2, &
ch3, &
ch3
WRITE
( UNIT=1, FMT='(A10)'
) ch3
ch1 = "Ludwig"
ch2 = " Van"
ch3 = "BEETHOVEN"
WRITE
( UNIT=1, FMT='(A,A,A,A)'
) trim(ch1), &
trim(ch2), &
' '
, &
ch3
...
Sorties |
---|
BEETHOVENPUCCINI^VERDI^VERDI^^^^ |
^VERDI^^^^ |
Ludwig^Van^BEETHOVEN |
Format d'édition : Litteral string
Si une constante littérale de type chaîne de caractères est spécifiée dans un format, celle-ci est reproduite telle quelle en sortie.
2.
3.
4.
5.
6.
7.
8.
9.
CHARACTER
(len
=9) :: ch1, ch2, ch3
...
ch1 = "Ludwig"
ch2 = " Van"
ch3 = "BEETHOVEN"
WRITE
( UNIT=1, &
FMT='("NOM : ",A,", PRÉNOM : ",A,A)'
) &
ch3, trim(ch1), trim(ch2)
...
Sortie |
---|
NOM^:^BEETHOVEN,^PRéNOM^:^Ludwig^Van |
7-2-2-d. Descripteurs de contrôle▲
-
Descripteurs de positionnement :
- nX : ignore (en entrée), saute (en sortie) les ncaractères suivants ;
- Tc : permet de se positionner au caractère de rang
c
; - TLn : permet de se positionner au caractère situé n positions à gauche par rapport à la position courante ;
- TRn : permet de se positionner au caractère situé n positions à droite par rapport à la position courante.
-
Descripteurs de gestion des blancs dans les champs numériques en entrée :
- BN (Blank Null) : ignore les blancs ;
- BZ (Blank Zero) : interprète le caractère blanc comme un 0.
2.
3.
4.
5.
INTEGER
i, j, k, l
...
READ
( UNIT=1, &
FMT='(I4,3X,I2,T12,I3,TL4,I1)'
) i, j, k, l
...
Entrées |
Affectations |
---|---|
1901^1254^4361 |
i=1901,j=54,k=361,l=4 |
2.
3.
4.
5.
INTEGER
i, j, k
...
READ
( UNIT=1, &
FMT='(I3,BZ,I2,BN,I3)'
) i, j, k
...
Entrées |
Affectations |
---|---|
^8^2^4^^ |
i=8,j=20,k=4 |
Un autre descripteur, /, provoque le passage à l'enregistrement suivant :
- en entrée : abandon de l'enregistrement courant et positionnement au début du suivant,
2.
INTEGER
i, j
READ
( UNIT=1, FMT='(I4,/,I4)'
) i, j
Entrées |
Affectations |
---|---|
1756^1254 |
i=1756,j=1791 |
1791 |
- en sortie : écriture du caractère newline.
2.
3.
4.
5.
6.
7.
CHARACTER
(len
=9) :: ch1, ch2, ch3
ch1 = "Ludwig"
ch2 = " Van"
ch3 = "BEETHOVEN"
WRITE
( UNIT=1, &
FMT='("NOM : ",A,/,"PRÉNOM : ",A,A)'
) &
ch3, trim(ch1), trim(ch2)
Sortie |
---|
NOM^^^^:^BEETHOVEN |
PRéNOM^:^Ludwig^Van |
7-2-2-e. Facteur de répétition▲
Lorsqu'une liste de descripteurs identiques figure dans un format, il est possible de les regrouper au moyen d'un facteur de répétition indiqué sous la forme d'une constante littérale entière.
2.
3.
4.
5.
6.
7.
INTEGER
i, j, k
INTEGER
t(3)
...
READ
( UNIT=1, FMT='(I4,I4,I4)'
) i, j, k
READ
( UNIT=1, FMT='(3I4)'
) t
...
WRITE
(6, '(3(1X,I4))'
) t
Entrées |
Affectations |
---|---|
^^45^^^9^^10 |
i=45, j=9, k=10 |
^-24^10^^^99 |
t(1)=-24, t(2)=10, t(3)=99 |
Sortie |
---|
^^-24^^^10^^^99 |
7-2-2-f. Réexploration d'un format▲
L'ensemble des variables spécifiées dans une instruction READ
/WRITE
s'appelle la liste d'entrée-sortie. Chaque élément de cette liste est associé à un descripteur du format :
- si le nombre de descripteurs correspond au nombre de variables de la liste, ceux-ci s'appliquent aux éléments successifs de cette liste ;
- s'il est plus grand, les suivants sont ignorés (le format est abandonné) ;
- s'il est plus petit, le format est réexploré. Cette réexploration entraîne le passage à l'enregistrement suivant.
Conclusion : en Fortran la liste d'entrée-sortie est toujours satisfaite.
La règle de réexploration est la suivante :
- si le format ne contient aucun groupe de descripteurs entre parenthèses, alors il est réexploré depuis son début ;
- sinon, la réexploration est faite à partir du groupe de niveau 1 le plus à droite. S'il est précédé d'un facteur de répétition, il est pris en compte.
Exemples
Le caractère | indique l'endroit à partir duquel la réexploration est effectuée.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
'( I6, 10X,I5, 3F10.2 )'
|-------------------
'( I6, 10X,I5, (3F10.2) )'
|--------
'( I6,(10X,I5), 3F10.2 )'
|----------------
'( F6.2, (2F4.1,2X,I4, 4(I7,F7.2)) )'
|--------------------------
'( F6.2, 2(2F4.1,2X,I4), 4(I7,F7.2) )'
|----------
'( F6.2,(2(2F4.1,2X,I4), 4(I7,F7.2)) )'
|-----------------------------
Exemples
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
INTEGER
i/100/, &
j/200/, &
k/300/, &
l/400/
REAL
t(3,4)
DATA
t/ 1., 4., 9., &
16., 25., 36., &
49., 64., 81., &
100., 121., 144. /
WRITE
(6, '( 4i5, (t25,4f8.2) )'
) &
i, j, k, l, &
((t(i,j),j=1,4),i=1,3)
Sorties |
---|
^^100^^200^^300^^400^^^^^^^^1.00^^^16.00^^^49.00^^100.00 |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^4.00^^^25.00^^^64.00^^121.00 |
^^^^^^^^^^^^^^^^^^^^^^^^^^^^9.00^^^36.00^^^81.00^^144.00 |
7-2-2-g. Format libre▲
En Fortran, il existe un format implicite appelé format libre (list-directed formatting).
Dans l'instruction READ
/WRITE
, on spécifie alors le caractère *
à la place du format.
Dans ce contexte, les enregistrements sont interprétés comme une suite de valeurs séparées par des caractères appelés séparateurs. C'est le type des variables auxquelles ces valeurs vont être affectées qui détermine la conversion à effectuer.
Les caractères interprétés comme des séparateurs sont :
- la virgule (,) ;
- le blanc (espace).
Une chaîne de caractères contenant un caractère séparateur doit être délimitée soit par des quotes (') soit par des guillemets (").
En entrée, plusieurs valeurs identiques peuvent être regroupées à l'aide d'un facteur de répétition sous la forme n*valeur.
Une constante complexe est codée comme 2 nombres réels entre parenthèses séparés par une virgule. Les parenthèses ainsi que la virgule peuvent être suivies ou précédées de blancs.
Une fin d'enregistrement (newline) a le même effet qu'un blanc. Elle peut apparaître :
- au sein d'une chaîne de caractères (délimitée par des quotes (') ou par des guillemets (")) ;
- entre la partie réelle et la virgule ou entre la virgule et la partie imaginaire d'une constante complexe.
Si une chaîne de caractères a été déclarée avec une longueur plus petite que celle de la valeur lue alors seuls les caractères les plus à gauche de la valeur seront stockés dans la chaîne. Sinon, celle-ci est complétée par des blancs.
Si dans l'enregistrement en entrée apparaissent deux virgules à la suite (éventuellement avec des blancs entre) alors l'élément correspondant de la liste ne sera pas modifié.
2.
3.
4.
5.
6.
7.
8.
9.
10.
INTEGER
i/100/, &
j/200/, &
k/300/
REAL
t(3)
COMPLEX
c
CHARACTER
(len
=8) ch
...
READ
( UNIT=1, FMT=* ) i, j, k, t, c, ch
WRITE
( UNIT=2, FMT=* ) i, j, k, c, ch
WRITE
( UNIT=2, FMT=* ) t
Entrées |
Affectations |
---|---|
150 |
i=150 |
260,, |
j=260 |
3*2.718 |
t=(/ 2.718,2.718,2.718 /) |
(^2. |
c=(2.,3.) |
,^3.^)^^^'Wolfgang Amadeus Mozart' |
ch='Wolfgang' |
Sorties |
---|
^150^260^300^(2.000000000,3.000000000)^Wolfgang |
^2.717999935^2.717999935^2.717999935 |
7-2-2-h. namelist▲
On peut regrouper les variables que l'on désire lire ou écrire au sein d'une liste à laquelle on donne un nom.
Ce regroupement s'effectue au moyen de l'instruction NAMELIST :
NAMELIST/nom_liste/liste_variables
- nom_liste est le nom de la NAMELIST ;
- liste_variables est une liste de variables précédemment déclarées.
Au niveau de l'instruction READ
/WRITE
la namelist remplace le format ainsi que la liste de variables qui, dans ce contexte, devient inutile.
L'enregistrement correspondant (lu ou écrit) respecte le format suivant :
&
nom_liste liste d'affectations /
La liste d'affectations concerne les variables de la namelist qui peuvent apparaître dans n'importe quel ordre, certaines pouvant être omises. Les différentes affectations sont séparées par des caractères séparateurs (, ou blancs).
Le caractère / indique la fin de la namelist. En entrée, les éventuels caractères qui suivent sont ignorés. En entrée, les chaînes de caractères doivent être délimitées à l'aide du caractère ' ou ".
En sortie, celles-ci apparaissent par défaut sans délimiteur. C'est le paramètre DELIM= de l'instruction OPEN
qui permet de le définir.
Dans l'instruction READ
/WRITE
, la namelist est indiquée à l'aide du paramètre NML= (à la place de FMT=).
L'utilisation des namelist est un moyen très commode d'effectuer des entrées-sorties sans avoir à définir de format.
2.
3.
4.
5.
6.
7.
8.
INTEGER
i/100/, j/200/, k/300/
INTEGER
t(3)
CHARACTER
(len
=11) ch
NAMELIST/LISTE/i,j,k,t,ch
...
READ
( UNIT=1, NML=liste )
WRITE
( UNIT=2, NML=liste )
...
Entrées |
Affectations |
---|---|
&LISTE t=3*2,i=1, k=4 ch=« Rythm&Blues » / |
i=1,k=4,t(1)=t(2)=t(3)=2,ch=« Rythm&Blues » |
Sorties |
---|
^&LISTE |
^I=1,^J=200,^K=4,^T=2,^2,^2,^CH=Rythm&Blues |
^/ |
7-3. Accès direct▲
À la différence d'un fichier séquentiel, il est possible d'accéder à un enregistrement d'un fichier à accès direct sans avoir traité les précédents.
Chaque enregistrement est repéré par un numéro qui est son rang dans le fichier. Leur taille est fixe. Au sein de l'instruction OPEN
:
- le paramètre RECL= est obligatoire, sa valeur indique la taille des enregistrements (en caractères pour les fichiers textes, dépend du processeur pour les fichiers binaires) ;
- le paramètre POSITION= est invalide ;
- si le paramètre FORM n'est pas précisé, c'est la valeur unformatted qui est prise en compte.
Le rang de l'enregistrement que l'on désire traiter doit être spécifié à l'aide du paramètre REC= de l'instruction READ
/WRITE
. Un enregistrement ne peut pas être détruit, mais par contre, il peut être réécrit. Dans ce contexte, les namelist ainsi que le format libre sont interdits.
7-3-1. Fichier binaire à accès direct▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
real
, dimension
(100) :: tab
integer
ios, n
OPEN
( UNIT=1, &
FILE="data_bin_direct"
, &
ACCESS="direct"
, &
ACTION="read"
, &
STATUS="old"
, &
RECL=400, &
IOSTAT=ios )
if
( ios /=
0 ) then
! Problème à l'ouverture
...
else
OPEN
( UNIT=2, FILE="data_txt_seq"
, &
ACTION="read"
, STATUS="old"
, &
IOSTAT=ios )
...
READ
( UNIT=2, FMT=* ) n
READ
( UNIT=1, REC=n, IOSTAT=ios ) tab
if
( ios >
0 ) stop
"erreur à la lecture."
...
CLOSE
( UNIT=2 )
end
if
CLOSE
( UNIT=1 )
Le fichier dont le nom est data_bin_direct est connecté à l'unité logique numéro 1. C'est un fichier binaire à accès direct (ACCESS="direct"
et paramètre FORM absent donc considéré égal à unformatted). Chaque enregistrement fait 400 octets (RECL=400).
On accède à l'enregistrement de rang n, valeur préalablement lue dans le fichier texte séquentiel de nom data_txt_seq connecté à l'unité logique numéro 2. Le paramètre IOSTAT de l'instruction READ
permet de récupérer l'état de la lecture dans l'entier ios : une valeur non nulle positive signale une erreur du type enregistrement inexistant par exemple.
7-3-2. Fichier texte à accès direct▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
real
, dimension
(100) :: tab
integer
ios, n
OPEN
( UNIT=1, &
FILE="data_txt_direct"
, &
FORM="formatted"
&
ACCESS="direct"
, &
ACTION="read"
, &
STATUS="old"
, &
RECL=800, &
IOSTAT=ios )
if
( ios /=
0 ) stop
"Problème à l'ouverture!"
OPEN
( UNIT=2, &
FILE="data_txt_seq"
, &
ACTION="read"
, &
STATUS="old"
, &
IOSTAT=ios )
...
READ
( UNIT=2, FMT=* ) n
READ
( UNIT=1, REC=n, &
IOSTAT=ios, FMT='(100F8.4)'
) tab
if
( ios >
0 ) stop
"erreur à la lecture."
...
CLOSE
( UNIT=2 )
CLOSE
( UNIT=1 )
On a adapté l'exemple précédent à un fichier texte à accès direct : le paramètre FORM="formatted"
a donc été précisé.
La valeur du paramètre RECL correspond à la taille en caractères de chacun des enregistrements qui correspond ici au format indiqué au niveau de l'instruction READ
(100*8 = 800).
Notes :
- il n'est pas permis de lire un fichier texte à accès direct au moyen d'un format libre ;
- un fichier dans lequel on écrit un seul enregistrement de rang n, contiendra en réalité n enregistrements avec les n-1 premiers ayant un contenu indéterminé. Lors de la lecture d'un tel fichier, se pose le problème de la reconnaissance de la nature de celui-ci. On pourra résoudre ce problème en adjoignant aux données une marque sous la forme d'une variable logique par exemple.
Dans l'exemple suivant, des enregistrements de rang aléatoire sont créés. Pour les repérer, on ajoute en tête des données une variable logique flag.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
program
dir
implicit
none
integer
, parameter
:: n = 100, m = 1000
real
, dimension
(n,m) :: matrice
real
, dimension
(n) :: vec
integer
i,j, rang, ios, size
logical
flag
inquire
( iolength=size ) flag, matrice(:,1)
open
( unit=1, &
file="direct.file"
, &
form="unformatted"
, &
access="direct"
, &
action="readwrite"
, &
status="unknown"
, &
recl=size, &
iostat=ios )
if
( ios /=
0 ) stop
"Erreur à l'ouverture"
flag = .false.
do
j=1,m
write
( unit=1, rec=j ) flag
end
do
call
random_number( matrice )
flag = .true.
do
j=1,m
if
( matrice(1,j) >
matrice(n,j) ) &
write
( unit=1, rec=j ) flag, matrice(:,j)
end
do
do
print
*,"Entrez un rang : "
read
( *, *, iostat=ios ) rang
if
( ios <
0 ) exit
if
( ios >
0 ) then
print
*,"Erreur de saisie. Veuillez recommencer."
cycle
end
if
read
( unit=1, rec=rang, iostat=ios ) flag, vec
if
( ios >
0 ) then
print
*,"Erreur lors de la lecture."
; cycle
end
if
if
( flag ) then
print
*,"vec(1) = "
, vec(1), "vec(n) = "
, vec(n)
else
print
*,"Enregistrement "
, rang, " indéfini."
end
if
end
do
close
(1)
end
program
dir
Notes :
- l'instruction
inquire
( iolength=size ) ... permet de récupérer dans l'entier size la taille de la liste de variables fournies qui servira à renseigner, par la suite, le paramètre RECL de l'instructionOPEN
. Comme cette valeur est exprimée dans une unité dépendant du compilateur (pour les fichiers binaires en accès direct), cette nouvelle forme de l'instructioninquire
(2), introduite par la norme Fortran 90, permet de la calculer en s'affranchissant de l'unité ; - l'instruction
call
random_number( matrice ) fait appel à la procédure intrinsèque Fortran 90 RANDOM_NUMBER qui valorise le tableau transmis à l'aide de nombres aléatoires générés dans l'intervalle [0., 1.].
7-4. Fichier temporaire▲
Si à l'ouverture d'un fichier on positionne le mot-clé STATUS à la valeur "scratch"
alors celui-ci sera temporaire et détruit à sa fermeture. Un tel fichier est anonyme : le paramètre FILE de l'instruction OPEN
ne doit donc pas être spécifié dans ce contexte.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
real
, dimension
(100) :: tab
integer
ios
OPEN
( UNIT=1, &
FORM="formatted"
&
ACCESS="direct"
, &
ACTION="write"
, &
STATUS="scratch"
, &
RECL=1200, &
IOSTAT=ios )
if
( ios /=
0 ) then
! Problème à l'ouverture
...
end
if
...
CLOSE
( UNIT=1 )
7-5. Destruction d'un fichier▲
L'instruction CLOSE
admet le paramètre à mot-clé STATUS qui par défaut (pour un fichier non temporaire) prend la valeur KEEP permettant ainsi de conserver le fichier après fermeture. Si on désire le supprimer, il suffira de préciser la valeur DELETE pour ce paramètre.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
real
, dimension
(100) :: tab
integer
ios
OPEN
( UNIT=1, &
FILE="data_seq"
, &
ACTION="read"
, &
STATUS="old"
, &
IOSTAT=ios )
if
( ios /=
0 ) then
! Problème à l'ouverture
...
end
if
...
if
( condition ) then
CLOSE
( UNIT=1, STATUS="delete"
)
else
CLOSE
( UNIT=1 )
end
if
7-6. Fichier interne▲
On appelle fichier interne un fichier dont les enregistrements sont en mémoire. Ce type de fichier induit des échanges entre zones de la mémoire et non plus entre un support externe et la mémoire.
Ces fichiers sont préconnectés : il n'y a donc aucune ouverture ni fermeture à effectuer.
Dans les instructions READ
/WRITE
, à la place du numéro d'unité logique, on indique une variable de type chaîne de caractères. C'est celle-ci qui fait référence à l'enregistrement en mémoire.
Seul l'accès séquentiel formaté est permis dans ce cas. Les namelist sont interdites.
Lors d'une écriture, il faut s'assurer que la chaîne de caractères réceptrice est de taille suffisante.
Lors d'une lecture, la fin de fichier est atteinte lorsqu'on essaie d'accéder aux caractères situés au-delà de la chaîne qui fait référence à l'enregistrement.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
INTEGER
, PARAMETER
:: n = 4, m = 6
REAL
, DIMENSION
(n,m) :: tab
CHARACTER
(LEN
=8) :: fmt = "( F8.3)"
INTEGER
:: i, j, ios
WRITE
( fmt(2:3), '(I2)'
) n ! fichier interne
OPEN
( UNIT=1, &
FILE="data_txt_seq"
, &
POSITION="rewind"
, &
ACTION="write"
, &
STATUS="new"
, &
IOSTAT=ios )
if
( ios /=
0 ) then
! Problème à l'ouverture
...
else
WRITE
( UNIT=1, FMT=fmt ) &
((tab(i,j),i=1,n),j=1,m)
end
if
CLOSE
( UNIT=1 )
Dans un format le facteur de répétition doit obligatoirement être précisé à l'aide d'une constante littérale. Cet exemple montre comment le générer dynamiquement en utilisant un fichier interne.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
PROGRAM
fichier_interne
CHARACTER
(len
=80) enreg
INTEGER
ios
REAL
x, y, z
NAMELIST/liste/x, y, z
OPEN
( UNIT=1, FILE="data_txt_seq"
, &
FORM="formatted"
, ACTION="read"
, &
STATUS="old"
, POSITION="rewind"
, &
IOSTAT=ios )
IF
( ios /=
0 ) STOP
4
READ
( UNIT=1, FMT='(a)'
, IOSTAT=ios ) enreg
DO
WHILE
( ios ==
0 )
IF
( VERIFY( enreg, &
" ,+-0123456789.eEdD"
) ==
0 ) THEN
READ
( enreg, FMT=*, iostat=ios ) x, y, z
!----------------------------------------
WRITE
( UNIT=*, NML=liste )
END
IF
READ
( UNIT=1, FMT='(a)'
, iostat=ios ) enreg
END
DO
CLOSE
( UNIT=1 )
END
PROGRAM
fichier_interne
Dans cet exemple, on lit un fichier en ne traitant que les enregistrements constitués de réels et en ignorant tous les autres.
7-7. Instructions de positionnement▲
Toute opération de lecture-écriture dans un fichier est effectuée par rapport à la position courante dans ce fichier, à l'ouverture celle-ci peut être précisée à l'aide du paramètre POSITION. Dans un fichier séquentiel, toute lecture-écriture d'un enregistrement de rang n implique le positionnement à l'enregistrement de rang n+1.
Trois instructions BACKSPACE
, REWIND
et ENDFILE
permettent de modifier la position :
BACKSPACE
force la position au début de l'enregistrement précédent ;REWIND
force la position au début du fichier ;ENDFILE
écrit un enregistrement de type fin de fichier. Il est alors nécessaire d'exécuter ensuite l'une des deux instructions précédentes.
Ces instructions admettent en paramètre le numéro de l'unité logique auquel le fichier est connecté.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
program
troncature
REAL
, dimension
(100) :: tab
INTEGER
ios
LOGICAL
flag/.false.
/
...
OPEN
( UNIT=1, &
FILE="data_txt_seq"
, &
ACTION="readwrite"
, &
POSITION="append"
, &
STATUS="old"
, &
IOSTAT=ios )
IF
( ios /=
0 ) then
! Problème à l'ouverture
...
ELSE
tab(:) = acos
(-1.)
WRITE
( UNIT=1, FMT='(100F6.3)'
) tab
REWIND
( UNIT=1 )
END
IF
Le fichier dont le nom est data_txt_seq est ouvert avec un positionnement en fin de fichier (POSITION="append"
). Après écriture d'un enregistrement, on se repositionne en tête (REWIND
).
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
READ
( UNIT=1, FMT='(100F6.3)'
, IOSTAT=ios ) tab
DO
WHILE
( ios ==
0 )
if
( flag ) then
BACKSPACE
( UNIT=1 )
ENDFILE
( UNIT=1 )
BACKSPACE
( UNIT=1 )
END
IF
...
READ
( UNIT=1, FMT='(100F6.3)'
,IOSTAT=ios ) tab
END
DO
CLOSE
( UNIT=1 )
end
program
troncature
Ensuite, on relit le fichier et si la variable flag contient la valeur .TRUE.
on le tronque avant le dernier enregistrement lu. (Instructions BACKSPACE
et ENDFILE
).
7-8. Instruction INQUIRE▲
L'instruction d'interrogation INQUIRE
permet de récupérer un certain nombre d'informations concernant un fichier ou un numéro d'unité logique.
Elle permet par exemple de tester si un fichier existe, s'il est connecté et dans ce cas de connaître les valeurs des paramètres positionnés lors de son ouverture via OPEN
.
Cette interrogation peut être faite en indiquant soit le numéro d'unité logique soit le nom du fichier.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
program
inquire
LOGICAL
existe
INTEGER
ios
CHARACTER
(len
=3) :: form
CHARACTER
(len
=10) :: acces
INQUIRE
( FILE="data_txt_seq"
, EXIST=existe )
if
( existe ) then
OPEN
( UNIT=1, &
FILE="data_txt_seq"
, &
POSITION="rewind"
, &
ACTION="read"
, &
IOSTAT=ios )
if
( ios /=
0 ) then
! erreur à l'ouverture
...
else
INQUIRE
( UNIT=1, &
FORMATTED=form, &
ACCESS=acces )
end
if
...
CLOSE
( UNIT=1 )
end
if
end
program
inquire
Dans les variables caractères form et acces on récupère respectivement les valeurs YES et SEQUENTIAL (si le fichier data_txt_seq existe).
7-9. Remarques▲
Les spécificateurs de format Bw[.d], Ow[.d] et Zw[.d] permettent la conversion de données entières sous forme binaire, octale et hexadécimale respectivement.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
PROGRAM
boz
INTEGER
I, J, K
I = 1415; J = 1515; K = 1715
WRITE
( UNIT = 1, &
FMT = "(B32.32,'|',O11.11,'|',Z8.8)"
&
) I, J, K
I = -1415; J = -1515; K = -1715
WRITE
( UNIT = 1, FMT='(B32.32)'
) I
WRITE
( UNIT = 1, FMT='(O11.11)'
) J
WRITE
( UNIT = 1, FMT='(Z8.8)'
) K
END
PROGRAM
boz
Sorties |
---|
00000000000000000000010110000111|00000002753|000006B3 |
11111111111111111111101001111001 |
37777775025 |
FFFFF94D |
Les fichiers associés au clavier et à l'écran d'une session interactive sont préconnectés en général aux numéros d'unités logiques 5 et 6 respectivement : en lecture pour le premier, en écriture pour le second.
Dans un souci de portabilité, on préférera utiliser dans les instructions READ
/WRITE
le caractère *
à la place du numéro de l'unité logique pour référencer l'entrée standard (READ
) ou la sortie standard (WRITE
). C'est la valeur par défaut du paramètre UNIT. L'instruction PRINT
remplace l'instruction WRITE
dans le cas où celui-ci n'est pas précisé.
Formes équivalentes
2.
3.
4.
CHARACTER
(LEN
=8) :: fmt = "(F8.3)"
READ
( UNIT=5, FMT=fmt) ...
READ
( UNIT=*, FMT=fmt) ...
READ
fmt, ...
2.
3.
WRITE
( UNIT=6, FMT=fmt) ...
WRITE
( UNIT=*, FMT=fmt) ...
PRINT
fmt, ...
Le format d'édition peut être défini en dehors des instructions d'entrées-sorties READ
/WRITE
. Dans ce cas le paramètre FMT= est positionné à un numéro (étiquette) renvoyant à une instruction de définition de format (FORMAT
).
2.
3.
4.
5.
6.
7.
8.
REAL
, DIMENSION
(5,6) :: tab
INTEGER
n, i
CHARACTER
(len
=10) :: ch
...
PRINT
'( I4,A,(T20,F8.3) )'
, &
n, ch, (tab(i,:),i=1,5)
PRINT
100, n, ch, (tab(i,:),i=1,5)
100 FORMAT
( I4,A,(T20,F8.3) )
En Fortran l'ouverture d'un fichier séquentiel est facultative. à défaut, l'ouverture du fichier est faite implicitement lors de l'exécution de la première instruction d'entrée-sortie. Le compilateur attribue au fichier un nom de la forme fort.i (i étant le numéro de l'unité logique indiqué dans l'instruction READ
/WRITE
). L'ouverture est faite en mode formatted ou unformatted suivant qu'un format a été ou non précisé.
Le paramètre END
de l'instruction READ
offre un autre moyen de tester une fin de fichier pour un accès séquentiel. On lui indique le numéro (étiquette) de l'instruction à laquelle on désire poursuivre le traitement. Ce paramètre n'est pas valide dans le cas d'un fichier à accès direct.
De même, le paramètre ERR permet de se débrancher à une instruction dans le cas d'une erreur de lecture (problème de format pour un fichier formaté, enregistrement inexistant pour un fichier à accès direct…).
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
INTEGER
:: date
do
print
*, "Saisie d'une date :"
read
( *, '(i4)'
, END
=1, ERR=2 ) date
print
'(i4)'
, date
cycle
2 print
*, "Saisie invalide. Veuillez recommencer."
end
do
1 print
*, "Arr^et de la saisie."
...
Remarque : au clavier, la saisie du caractère Ctrl-D après le caractère newline (touche Enter) indique une fin de fichier.