lundi 7 janvier 2008

Formats en Fortran

En Fortran 90, la gestion des entrées-sorties est assez spartiate. Il est possible d'utiliser le format libre pour écrire ou lire ses données, mais l'emploi des formats est vivement recommandé si l'on veut être précis avec ses valeurs numériques (pour les flottants notamment) ou si l'on souhaite printer des choses d'une manière "fixe" (pas de décalage de colonne pour un tableau, par exemple). Le code ci-dessous illustre la plupart des descripteurs de format disponibles en Fortran (hormis les caractères de contrôle d'impression pour imprimante : "+", "0", "1", ... --> pour votre santé mentale, n'imprimez pas de Fortran !).

Note :

J'ai toujours codé en Fortran 90. Le code et les commentaires suivants sont donc au moins valables pour cette version et les suivantes (95 et 2003). Cependant, je ne peux pas assurer leur validité pour les versions antérieures de Fortran (77 et avant).

Code :



! Gestion des formats en fortran
PROGRAM main
INTEGER :: entier
REAL*8 :: flott
CHARACTER(LEN = 8) :: chaine
LOGICAL :: vamosalaplaya

entier = 4568
flott = 56.456
chaine = "truites"

vamosalaplaya = .TRUE.

! Sans format
PRINT*, "-----Sans format-----"
PRINT*, entier
PRINT*, flott
PRINT*, chaine
PRINT*, vamosalaplaya

! Avec formats
PRINT*, "-----Avec formats-----"
PRINT '(I6)', entier
PRINT '(F6.3)', flott
PRINT '(A7)', chaine
PRINT '(L3)', vamosalaplaya

! Combinaisons
PRINT*, "-----Combinaisons-----"
PRINT '(I4,3X,F5.2)', entier, flott
PRINT '(2(I4,1X,F5.2,2X))', &
entier,flott,&
2*entier,flott-1.5
PRINT '("N = ",I4,/,"x = ",F6.3)',&
entier, flott
PRINT '(T20,I4,T1,A7)',entier, chaine

! Notation exponentielle
PRINT*, "-----Exponentielle-----"
PRINT '(E8.2)', flott
PRINT '(E9.3)', flott
PRINT '(E10.4)', flott

! Erreurs
PRINT*, "-----Erreurs-----"
PRINT '(I3)', entier
!PRINT '(I4)', flott
! --> erreur a l'exe
PRINT '(E6.2)', flott
PRINT '(I4,1X,T3,F6.3)', entier, flott

END PROGRAM main


Résultats :

 -----Sans format-----
4568
56.4560012817383
truites
T
-----Avec formats-----
4568
56.456
truites
T
-----Combinaisons-----
4568 56.46
4568 56.46 9136 54.96
N = 4568
x = 56.456
truites 4568
-----Exponentielle-----
0.56E+02
0.565E+02
0.5646E+02
-----Erreurs-----
***
******
4556.456


Descripteurs :

Un format en fortran se présente entre quotes et parenthèses. Il est utilisable en écriture (comme ici avec PRINT, ou avec WRITE dans un fichier), et en lecture (READ). On utilise "*" pour indiquer un format libre (pas de format en fait !). Attention, il est nécessaire d'utiliser le même format en lecture que celui employé en écriture lors de la relecture de données (sans quoi les castors mutants prendront le contrôle de nos cerveaux). Passons en revue les descripteurs utilisés :
  • Entiers : Iw, avec w le nombre d'emplacements.
  • Réels, notation flottante : Fw.d avec w emplacements et d chiffres décimaux.
  • Réels, notation exponentielle : Ew.d avec w emplacements (penser au "E+" !) et d décimaux pour la mantisse (pas l'exposant, l'autre...).
  • Booléens : Lw avec w emplacements (intérêt d'écrire des booléens ?).
  • Chaîne : Aw
  • Espaces : wX pour w espaces (à noter que le w se met ici avant).
  • Changement de ligne : / ('(/,/)' pour un saut de ligne donc).
  • Facteur de répétition : exemple : '(2(I4,1X))' équivaut à '(I4,1X,I4,1X)'
  • Positionneur de tampon : Tw, avec w la position absolue dans la chaîne.
  • Libellés : entre double-quotes.

Commentaires :

Oui, c'est lourd. Oui, c'est une source intarissable d'erreurs. En particulier le coup du déplacement de tampon (à éviter à mon avis), les flottants et le facteur de répétition en cas d'inattention... Le A pour les chaînes ne prend pas obligatoirement d'argument (w dans notre notation). A noter qu'il est souvent conseillé de laisser le premier caractère d'impression libre (un espace, quoi) pour éviter tout soucis avec une sortie moyennement standard (avec caractère de contrôle notamment : vous noterez que c'est le comportement par défaut en format libre pour les chaînes de caractères).

En cas d'erreur de ma part ou autre, n'hésitez pas à poster.

4 commentaires:

Sébastien a dit…

Merci bien pour ce panorama des formats en Fortran. Juste une petite question supplémentaire : comment faire pour laisser un espace ou un signe moins suivant que le nombre flottant soit positif ou négatif ? Avec Octave (clône libre de Matlab), il suffit de laisser un espace :
printf("% 10.6f\n",x);
Mais avec Fortran, aucune idée.

Sobe a dit…

Aïe, question pas évidente...
Il existe un code de sortie spécial pour forcer l'affichage du signe '+' devant les flottants (source).
Certes, ça ne répond pas exactement à ta question, mais ça évite déjà les décalages de colonnes...

Une autre solution bien plus moche serait la suivante : comme il est possible de cibler un format via une étiquette (warning, crypto-goto spotted), il est possible de placer avant son 'print' une condition sur la positivité de son flottant et utiliser le format qui va bien en modifiant la valeur de l'étiquette (entier).

On voit bien là l'horreur que ça peut devenir de manipuler de simples sorties en Fortran...

Mini Sayen a dit…

Ou alors, laisser un caractère de marge ... il restera un espace si pas de "-"

Anonyme a dit…

Ou brûler le fortran.


Qu'il aille en ENFER!