Next Previous Contents

1. Le langage Fortran 77

1.1 Objets de base du Fortran 77

Jeu de caractères

Èléments du langage

Noms d'instructions, mots réservés

     INTEGER REAL CHARACTER DOUBLE PRECISION COMPLEX LOGICAL DO GOTO 
     IF THEN ELSE ELSEIF STOP END COMMON SUBROUTINE CALL RETURN FUNCTION 
     READ WRITE FORMAT OPEN CLOSE REWIND BACKSPACE DATA ...

Noms symboliques

Opérateurs

Expressions

Identificateurs et constantes reliés par des opérateurs. Exemples :

         A + B * ( C ** D )
         (1.LE.K).AND.(K.LE.MAX)                 
         PATH // '/' // NOM // '.' // EXT

Types de données, constantes

Autres types de données : Réels double-précision, Complexes (simple et double précision), Fractionnels, Virgules fixes, etc ...

Variables, scalaires, tableaux

Variables

Une variable est une grandeur dont la valeur peut changer au cours de l'exécution d'un programme. Une variable est désignée par un identificateur. Un type est associé à chaque variable

Toute variable dont le nom commence par I, J, K, L, M ou N et qui n'a pas été déclarée explicitement est par défaut de type INTEGER. Les autres variables non déclarées sont de type REAL.

Scalaires

Scalaire : donnée unique désignée par un nom.

Tableaux

Tableau : collection d'objets du même type.

Une déclaration de tableau se fait en mentionnant - après son nom - la liste des intervalles de ses indices.

Exemple :

        REAL TAB(5:12,3,0:20)  
déclare un tableau à 3 dimensions dont les éléments sont de type REAL. Le premier indice peut varier entre 5 et 12, le second entre 1 et 3, et le troisième entre 0 et 20. On peut utiliser jusqu'à 7 dimensions.

Elément de tableau : donnée élémentaire désignée par l'identificateur du tableau suivi par une liste d'indices placés entre parenthèses et séparés par des virgules. Le nombre d'indices doit correspondre au nombre de dimensions déclarées. Exemple : TAB(6,2,0).

Pendant l'exécution, si un indice déborde des bornes indiquées, le résultat est indéfini.

Unités de programme

Un programme est composé d'une ou plusieurs unités de programme :

La fin de toute unité de programme est indiquée par la présence d'une instruction END .

La portée des identificateurs de variables et des étiquettes est limitée à une unité de programme.

Les noms des sous-programmes, fonctions et zones communes (COMMON) sont accessibles à partir de toute unité.

1.2 Présentation des programmes

Une instruction particulièrement longue peut s'écrire sur plusieurs lignes consécutives; dans ce cas seule la première ligne peut comporter une étiquette, et les « lignes-suite » sont identifiées par un caractère quelconque différent du blanc et du zéro (on met en général un S, ou un chiffre).

Un exemple de programme FORTRAN :

          1         2         3         4         5         
123456789012345678901234567890123456789012345678901234567890
-----S------------------------------------------------------
          PROGRAM DEGRAD
C
C Imprime une table de conversion degrés -> radians   
C
          INTEGER DEG
          REAL    RAD,COEFF
C
C En-tête
          WRITE (*,10)
10        FORMAT (' ',20('*') / 
     S              ' * Degres * Radians *' /
     S              ' ',20('*') )
C Corps
          COEFF = (2.0 * 3.1416) / 360.0         
          DO 100 DEG = 0,90
               RAD = DEG * COEFF
               WRITE (*,20) DEG,RAD
20             FORMATF (' *  ',F4.1,'  * ',F7.5,' *')
100       CONTINUE
C
C Fin du tableau
C         WRITE(*,30)
30        FORMAT (' ',20('*') )
C
          STOP
          END

1.3 Instructions

Les déclarations de variables

Une variable est déclarée en citant : son type, son nom et, (pour les tableaux) les bornes des indices.

Principaux types :

Exemple :

               INTEGER*4      A(20,3),B
               CHARACTER*1O   C(0..9)
               LOGICAL        D(3,4,8:12)

Ces instructions déclarent :

Initialisation statique des variables

Il est possible de donner une valeur initiale aux variables d'une unité de programme pendant le chargement du programme. C'est ce qu'on appelle l'initialisation statique d'une variable, par opposition à l'initialisation dynamique qui se fait à l'exécution au moyen d'une instruction d'affectation.

Exemples :

          REAL           PI,E
          DATA           PI,E / 3.14159 , 2.718 /

          CHARACTER*1    SPACE,BELL,ESCAPE
          DATA           SPACE,BELL,ESCAPE / ' ',Z'07',Z'1B' /

          CHARACTER*10   NAMES(10)
          DATA           NAMES / 3*'AAAAAAAAAA',7*'XXXXXXXXXX' /

Le dernier exemple utilise des facteurs de répétition : les 3 premiers élements de NAMES contiendront 'AAAAAAAAAA', les 8 autres 'XXXXXXXXXX'.

1.4 Les déclarations d'unités de programmes

Rappelons que les noms d'unités de programmes sont limités à 6 caractères, et que le texte d'une unité de programme se termine sur une instruction END.

Programme principal.

Cette unité de programme commence par la ligne :

               PROGRAM nom 
Exemple 1 :
               PROGRAM ESSAI
               INTEGER  I
          C
               DO  1000 I=1,10
                    WRITE  (*,*) ' Bonjour !'
          1000 CONTINUE
          C
               STOP
               END

Sous-programmes et fonctions

Exemple 2 : définition d'un sous-programme

               SUBROUTINE  ECHANG ( X,Y )
               INTEGER X,Y,INTER
          C
               INTER = X
               X = Y
               Y = INTER
          C
               RETURN
               END

Les sous-programmes sont appelés par l'ordre CALL. Exemple :

                CALL ECHANG( T(I) , T(I+1) )

Exemple 3 : Définition de fonction

               INTEGER FUNCTION  MAX (N1,N2)
               INTEGER  N1, N2
          C
               IF (N1 .GE. N2) THEN
                    MAX = N1
               ELSE
                    MAX = N2
               ENDIF
          C
               RETURN
               END

Les fonctions sont appelées à partir des expressions. Elles retournent toujours une valeur.

Exemple d'appel de fonction :

          I12 = 2 * MAX(A+1,B+2) - MAX (C,10)

Exemple 4 : passage d'un tableau formel

          INTEGER FUNCTION INDEX (T,N,V)
          INTEGER  N, T(N), V, K
 C
 C Cette fonction calcule l'index de la première occurence de V
 C dans le tableau T. (Retourne 0 si cette valeur est absente)
 C
          DO  100 K = 1,N
               IF ( T(K) E.EQ. FV ) THEN
                    INDEX = K
                    RETURN
               ENDIF F
 100      CONTINUE
 C
          INDEX = 0
          RETURN
          END

IMPORTANT : lors de l'appel d'une unité de programme, les paramètres effectifs doivent être conformes - en nombre et en type - aux paramètres formels. (Chose que les compilateurs FORTRAN ne vérifient en général pas, et qui provoque des gags plutôt difficiles à déceler).

Exemple typique d'erreur :

          REAL FUNCTION F (X)
          REAL F, X
               F = X + 1.0
          RETURN
          END

Si l'on exécute alors l'instruction Y=F(0) (au lieu de F(0.0)), on récupère dans Y quelque chose qui est tout-à-fait différent de la valeur attendue 1.0. Essayez !

Autre source d'erreurs : ne pas oublier de déclarer le type d'une fonction appelée dans l'unité appelante. Exemple d'erreur :

          INTEGER FUNCTION CARRE (N)
          INTEGER N
               CARRE = N * N
          RETURN
          END

          INTEGER FUNCTION P4 (N)
          INTEGER  N
               P4 = CARRE ( CARRE ( N ) )
          RETURN
          END

Dans P4 la fonction CARRE est considérée comme rendant un résultat de type REAL (d'après la règle IJKLMN), ce qui n'est pas cohérent avec la définition de la fonction CARRE. Il faut donc ajouter dans P4 (et dans toute unité de programme qui appelle CARRE) la déclaration « INTEGER CARRE ».

Block Data

Cette unité de programme un peu spéciale sert uniquement à l'initialisation statique (par DATA) des zones communes. Elle commence par la ligne :

               BLOCKDATA nom
et ne peut contenir que : Une zone commune ne peut être citée que dans un seul BLOCKDATA. Il est d'ailleurs conseillé de n'avoir qu'un seul BLOCKDATA par programme.

(Pour plus d'informations se reporter à l'annexe sur l'utilisation des zones communes).

Instructions de contrôle

Affectation

Exemple : PAS ( N , P ) = PAS ( N-1 , P-1 ) + PAS ( N , P )

Le déroulement d'une affectation « var = expression » est le suivant :

Ainsi, si les variables I et R sont respectivement de type INTEGER et REAL, les instructions :

 
          I = 1 
          R = I / 2.0
provoquent l'affectation de la valeur 0.5 à R, tandis que :
          I = 1
          R = I / 2
met 0.0 dans R (l'expression I/2 étant de type entier, la division est une division entière de résultat nul, converti ensuite en valeur réelle).

CONTINUE

C'est une «non-opération», qui sert uniquement à poser une étiquette (en particulier dans les boucles DO).

Exemple :

          DO 1000 K=1,N
               A(K) = B(K) + 1
     1000 CONTINUE

STOP

Provoque l'arrêt complet du programme en cours.

GOTO

Exemple : GOTO 1234

Provoque un saut (branchement) à l'instruction (de la même unité de programme) qui porte l'étiquette 1234.

GOTO calculé

Exemple : GOTO (1010,2000,3000,1515),I+1

Si l'expression I+1 a pour valeur 1, alors saut à l'étiquette 1010. Si la valeur est 2, saut à 2000; etc.

Si la valeur calculée estt inférieure à 1 ou supérieure au nombre d'étiquettes citées, on passe simplement à l'instruction suivante.

IF logique

Instruction de la forme : IF ( condition ) instruction

Exemple :

               IF  ( M .LT. FT(K) ) M = T(K)
               K = K + 1

Si la condition citée (M plus petit que T(K)) est vraie, l'instruction située sur la même ligne est exécutée, puis on passe à la suivante (K = K + 1). Dans le cas contraire, l'instruction suivante est exécutée directement (on ne fait pas l'affectation M = T(K) ).

Le « IFlogique » est très souvent employé en compagnie de l'instruction GOTO, c'est-à-dire sous la forme :

          IF( condition ) GOTO etiquette
C'est le « GOTO conditionnel ».

Bloc IF

Forme générale :

          IF ( condition1 ) THEN
               bloc 1
          ELSE IF ( condition2 )  THEN
               bloc 2
          ELSE IF ( condition3 )  THEN
               bloc 3
          ....
          ELSE
               bloc-else
          ENDIF

Si la condition 1 est vraie, le bloc 1 (suite d'instructions) est exécuté et on passe à l'instruction qui suit le ENDIF. Sinon, si la condition 2 est vraie on exécute le bloc 2, etc ...

Si les conditions sont toutes fausses, c'est le bloc-else qui est exécuté.

Le nombre de parties ELSE IF n'est pas limité (on peut ne pas en mettre). La partie ELSE est également facultative.

Exemples :


          PROGRAM CHOIX      
          CHARACTER*1 CODE
C
C on demande le caractere CODE
C
1         WRITE (*,*) ' Tapez A,B,C,? ou X'            
          READ (*,100) CODE
100       FORMAT F (A1)
C
C au besoin, on transforme les minuscules en majuscules.
C
          IF(  ('a'.LE.CODE).AND.(CODE.LE.'z')  THEN 
               CODE  = CHAR ( ICHAR ( CODE ) - 32 )
          ENDIF
C
C selon CODE, on appelle FA,FC,FC,MENU et on recommence.
C si CODE=X on arrête tout.
C
          IF (CODE.EQ.'?') THEN
              CALL MENU
          ELSE IF ( CODE.EQ.'A' ) THEN
              CALL FA
          ELSE IF ( CODE.EQ.'B' ) THEN
              CALL FB
          ELSE IF ( CODE.EQ.'C' ) THEN
              CALL FC
          ELSE IF ( CODE.EQ.'X' ) THEN
               WRITE  (*,*) ' C''est tout !'
               STOP
          ELSE
               WRITE (*,*) ' Quoi ?'
          END IF
C
          GOTO 1
          END

« IF arithmétique »

Tout manuel FORTRAN qui se respecte se doit de citer ce vénérable vestige de la préhistoire informatique, période FORTRAN I ! Cette chose est appelée vulgairement « IF à trois pattes », d'après sa forme générale qui est :

          IF ( Expression ) Etiquette1,Etiquette2,Etiquette3

Cette forme est utile (et encore ...) uniquement si on a vraiment trois traitements distincts à effectuer dans chaque cas. L'exemple classique est la recherche des solutions d'une équation du second degré ... qui ne marche pas puisque les opérations réelles fournissent rarement un résultat exactement nul, à cause de la précision limitée. En réalité il faut faire une comparaison «à epsilon près».

Quoi s'il en soit, on fait exactement la même chose avec un GOTO conditionnel mille fois plus clair.

Cette chose a malheureusement survécu à toutes les révisions du langage FORTRAN, parce que beaucoup de programmes FORTRAN l'utilisaient, et que personne n'a le courage de les refaire. Notamment on rencontre des choses du genre :

     IF (M-T(K)) 100,200,200
     100   M = T(K)
     200   K = K + 1
Le devoir sacré de tout programmeur FORTRAN est de remplacer illico tous les « IF arithmétiques » qu'il rencontre par des « IF logiques ». Ne pas corriger une faute, c'est là la véritable faute (Confucius).

DO

Exemple : DO 100 K=1,N

L'instruction DO sert à indiquer qu'un certain « bloc » d'instructions (le corps de la boucle) est à répéter pour plusieurs valeurs de l'indice de boucle (ici K), cet indice variant entre une borne inférieure (ici 1) et une borne supérieure (ici N).

Le corps de la boucle est composé des instructions quisuivent l'instruction DO jusqu'à (et y compris) l'instruction dont l'étiquette est indiquée (ici 100). Une bonne habitude consiste à utiliser une instruction CONTINUE pour poser cette étiquette, et à indenter (décaler) le corps de boucle.

Exemple

          SUBROUTINE  PROMAT (A,B,C,N,M,P)
C
          INTEGER   N,M,P
          REAL      A(N,M),B(M,P),C(N,P)
C
          INTEGER   I,J,K           
          REAL S
C
          DO 300  I=1,N
               DO 200 J=1,P
                    S = 0.0
                    DO 300 K=1,M
                         S = S + A(I,K)*B(K,J)
100                 CONTINUE
                    C(I,J)=S
200            CONTINUE
300       CONTINUE
C
          RETURN
          END

Quelques remarques :

Entrées-Sorties séquentielles

Le point important est qu'un ordre d'entrée-sortie FORTRAN (lecture ou écriture) mentionne (au moins) trois choses :

Il est également possible de préciser ce qu'il faut faire si l'ordre d'entrée-sortie se déroule mal, ou si on détecte une fin de fichier

WRITE

Exemples :

          WRITE  ( 6,100 ) A,B,C
          WRITE  ( 6,123 ) A, B+1 , ( T(K), K=1,N ) 

Le premier exemple signifie « Ecrire sur l'unité logique numéro 6 les contenus des variables A,B et C en utilisant la description d'enregistrement donnée par l'instruction FORMAT d'étiquette100 (située dans la même unité de programme) »

Le second exemple montre une « boucle DO implicite », qui parcourt les N premiers élements du tableau T.

Autre exemple de boucle DO implicite :

          WRITE (6,421) (  ((10*I+J), J=1,I) , I=1,9 )
qui imprime la suite de nombre 11,21,22,31,32,33,41...99 sur l'unité logique et dans le format que vous devinez.

Le numéro d'unité logique 6 désigne -en général- la « sortie standard » (votre écran), on peut mettre une étoile * si on ne s'en souvient pas.

Si on ne désire pas spécifier de manière précise le format d'écriture, on met aussi une étoile à la place de l'étiquette de format.

Dans ce cas le compilateur se débrouille pour fabriquer un format convenable (de son point de vue !). C'est bien pratique lorsqu'on fait de la mise au point par « espionnage », du style :

          SUBROUTINE XYZ (A,B)
          WRITE (*,*) ' Je rentre dans XYZ avec A=',A,'et B=',B
               ...
          WRITE (*,*) ' Je sors de XYZ avec A=',A,' et B=',B
          RETURN
          END
et aussi pour les programmes « quick'n dirty ».

READ

Exemples :

          READ (5,100) X,Y,Z
          READ (5,100,END=123) A,B,C
          READ (5,100,END=123,ERR=987) U,V,W

Il n'est guère difficile de deviner la signification du premier exemple : « lire sur l'unité logique numéro 5 les nouvelles valeurs des variables X,Y et Z, selon le format 100 ».

Dans le second exemple l'option « END=123 » signifie qu'en cas de fin de fichier il faut se dérouter à l'instruction portant l'étiquette 123.

Le troisième exemple montre l'option « ERR=987 » qui indique :« si une erreur se produit pendant la lecture (par exemple une lettre dans une zone censément numérique) alors aller en 987 ».

Le numéro 5 est affecté à l'entrée standard (votre clavier) ; on peut mettre une étoile à la place. On peut aussi mettre une étoile au lieu du numéro de format, la lecture s'effectue alors en « format libre » ; c'est-à-dire que l'utilisateur tapera ses données séparées par des blancs ou des virgules, les chaines de caractères étant entourées par des quotes « ' ».

L'usage des formats libres est :

FORMAT

Exemple :

          WRITE (*,100) I,J,K         
          ...
100       FORMAT ( 5X ,'Le ppcm de ',I2,' et ',I2,' vaut ',I4)

Dans cet exemple l'ordre WRITE provoque l'écriture (sur la sortie standard) d'une ligne composée de :

L'instruction FORMAT (en fait c'est une déclaration) n'a de sens qu'utilisée par un ordre READ ou WRITE. Il y a donc nécessairement un numéro d'étiquette devant.

Quelques spécifications de format

Répétition de FORMAT

Exemple : « 5(I3,X) » équivaut à « I3,X,I3,X,I3,X,I3,X,I3,X ».

Il y a une règle très amusante qui s'applique au cas où l'on veut faire écrire plus de choses que le format n'en spécifie. Exemple :

          WRITE  (*,100) A,B,C
100       FORMAT  (2I4)

Cette règle dit :

Si la parenthèse finale est rencontrée alors qu'il reste des données à traiter :
En réfléchissant un peu, c'est finalement très simple.

OPEN

       OPEN  (1)
       OPEN  (1,FILE='FICH.ABC')
       OPEN  (1,FILE='TOTO.X',STATUS='OLD',ERR=123)

Le premier exemple est une ouverture simple du fichier numéro 1. Dans le second, on précise le nom du fichier que l'on veut associer au numéro d'unité logique 1 (ici FICH.ABC). Dans le troisième, on précise que le fichier que l'on veut ouvrir (TOTO.X) est censé exister déjà (OLD), et qu'en cas d'erreur (si fichier absent, donc) il faut aller à l'étiquette 123.

On peut donner comme STATUS la chaîne 'NEW', qui signifie que le fichier n'existait pas préalablement, ou 'UNKNOWN' ...

Il existe des quantités d'autres clauses, voir en particulier l'annexe relative à l'utilisation des fichiers en accès direct.

Il n'est pas nécessaire d'ouvrir les fichiers 5 et 6.

CLOSE

     CLOSE (1)
ferme le fichier - préalablement ouvert - indiqué.

Il est inutile de fermer les fichiers standards 5 et 6.


Next Previous Contents