IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

COBOL - Chapitre 5 - Alternatives et débranchements

Date de publication : 24/01/2007 , Date de mise à jour : 07/02/2007

Par Guillaume Ventre (Développement Mainframe) (Blog)
 

Nous allons aborder dans ce chapitre les moyens COBOL traduisant les alternatives et débranchements algorithmiques.

1. L'alternative simple IF
1.1. Les conditions de relation
1.2. Les conditions de classes
1.2.1. Classes numériques et alphanumériques
1.2.2. Classes spécifiques à un programme
1.3. Les conditions de signe
1.4. Les conditions de nom-condition
1.4.1. Le niveau 88
1.4.2. L'instruction SET
1.5. L'instruction NEXT SENTENCE
1.6. L'instruction CONTINUE
2. Le débranchement inconditionnel GO TO
3. L'appel de module PERFORM
3.1. Syntaxe
3.2. Fonctionnement
3.3. Exemple 1
3.4. Exemple 2
3.5. L'instruction EXIT
4. L'alternative complexe EVALUATE
5. Les boucles: les autres formats du PERFORM
5.1. PERFORM ... TIMES
5.2. PERFORM ... UNTIL
5.3. PERFORM ... VARYING ... UNTIL
5.4. PERFORM ouvert
6. Remerciements


1. L'alternative simple IF

Elle permet de traduire la structure alternative Si ... sinon ... finsi de l'algorithmique.

Syntaxe
IF condition
        instruction-1
    [ELSE
        instruction-2]
END-IF
warning Le SCOPE-TERMINATOR END-IF n'existait pas en COBOL 74, c'est le point (.) qui fermait tous les IF ouverts.
L'imbrication des alternatives doit être manipulée avec discernement :

  • trop de niveaux (+ de 3) amènent de très sérieux problèmes de compréhension,
  • on peut limiter les niveaux en utilisant des appels à des modules internes (instruction PERFORM),
  • on peut remplacer des alternatives imbriquées par une succession d'alternatives simples comportant des conditionnements booléens. En contrepartie, on risque d'oublier certaines branches.

1.1. Les conditions de relation

Les opérateurs autorisés sont: >, >= , <, <= , =, NOT, OR et AND.

info Certains compilateurs accèptent l'opérateur "différent" écrit sous la forme: <>. Préférez l'utilisation de cette opérateur sous sa forme: NOT =, vous vous garantissez ainsi de prendre une habitude d'écriture qui sera acceptée partout... vous gagnerez du temps.
Quelques exemples:
IF A = 2
    MOVE B TO C
END-IF.
IF A > B
        ADD 2 TO B
    ELSE
        ADD 2 TO C
END-IF.

Les comparaisons se font selon la séquence ASCII ou EBCDIC:

  • en ASCII: espace < chiffres < lettres
  • en EBCDIC: espace < lettres < chiffres


Ce chapitre du cours COBOL n'a pas pour vocation de vous expliquer la théorie logique du calcul des propositions, mais nous allons toutefois faire un petit rappel important concernant la loi de Morgan car c'est un piège classique pour tout développeur débutant:

La négation d'une conjonction de deux propositions est équivalente à la disjonction des négations des deux propositions.
La négation d'une disjonction de deux propositions est équivalente à la conjonction des négations des deux propositions.


Autrement dit:
Loi de Morgan
NON (A ou B) = NON A et NON B
NON (A et B) = NON A ou NON B


Exemple: si vous souhaitez tester la non-condition Si situation familliale différente de célibataire OU différente de veuf OU différente de marié alors... finsi vous serez tenté de coder comme suit:
Codage erroné
IF SITU-FAMILLE NOT = 'C' OR
   SITU-FAMILLE NOT = 'V' OR
   SITU-FAMILLE NOT = 'M'
      [...]
END-IF.


En fait, avec la loi de Morgan, il faut coder ainsi:
Codage correct
IF SITU-FAMILLE NOT = 'C' AND
   SITU-FAMILLE NOT = 'V' AND
   SITU-FAMILLE NOT = 'M'
      [...]
END-IF.

1.2. Les conditions de classes


1.2.1. Classes numériques et alphanumériques

Syntaxe
NUMERIC
nom-donnée-1  [NOT]
                      ALPHABETIC


Cette condition permet de tester si le nom-donnée de la condition contient des chiffres ou des lettres.

Exemple:
IF MONTANT NUMERIC
        SUBTRACT MONTANT TO TOTAL GIVING NOUVEAU-SOLDE
    ELSE
        MOVE ANCIEN-SOLDE TO NOUVEAU-SOLDE
END-IF.

1.2.2. Classes spécifiques à un programme

En COBOL 85, il est possible de définir des classes spécifiques à un programme dans le paragraphe SPECIAL-NAMES (cf. chapitre 1 - Description générale du langage COBOL, §4.2.1 CONFIGURATION SECTION.

Syntaxe
CLASS nom [IS] littéral-1 [THRU littéral-2] littéral-3 [THRU littéral-4]...
.


Les classes ainsi définies peuvent ensuite être utilisées pour tester si le contenu d'une variable est valide.

Exemple:
CONFIGURATION SECTION.
SPECIAL-NAMES.
    CLASS DATE-AVEC-SEPARATEUR IS '0' THRU '9' '-' '/'.

...

PROCEDURE DIVISION.

    IF DATE-MVT DATE-AVEC-SEPARATEUR
            DISPLAY DATE-MVT
        ELSE
            DISPLAY 'LA DATE EST ERRONEE'
    END-IF.
warning Les classes ainsi définies ne sont utilisables que sur des variables alphanumériques.

Il faut un point unique pour clôturer le paragraphe SPECIAL-NAMES (il n'y a pas de point intermédiaire, même si plusieurs classes sont définies pour un programme).

1.3. Les conditions de signe

Syntaxe
POSITIVE
Opérande-1  [NOT]     NEGATIVE
                      ZERO


Cette condition permet de tester si un opérande de la condition est positif, négatif, égal ou différent de zéro.

Exemple:
IF SOLDE POSITIVE
        MOVE '+' TO SOLDE-AFFICH-SIGNE
END-IF.
IF SOLDE ZERO
        MOVE SPACE TO RESULT
END-IF.

1.4. Les conditions de nom-condition

Cette condition a l'avantage d'être très parlante. On l'utilise d'ailleurs très souvent pour positionner des "flags" ou des "tops" durant le déroulement d'un programme afin de mémoriser l'état d'une action à un moment "t".


1.4.1. Le niveau 88

Pour utiliser les conditions de nom-condition, il faut tout d'abord déclarer en DATA DIVISION (cf. chapitre 1 - Description générale du langage COBOL, §4.3 DATA DIVISION) autant de niveau 88 que de conditions à tester:

Syntaxe
88    nom-condition-1    VALUE    littérale-1 [THRU littérale-2] [,littérale-3 [THRU littérale-4]...].
warning La virgule est importante dans le cas où vous utilisez plus d'une valeur ou plage de valeur.
Premier exemple, vérification de la validité d'un compte:
DATA DIVISION.
01  COMPTES.
    05  NOM                 PIC X(20).
    05 PRENOM               PIC X(20).
    05 NUM-COMPTE           PIC 9(10).
        88 COURANT          VALUE 1000000000 THRU 1999999999.
        88 PEL              VALUE 2000000000 THRU 2999999999.
        88 CODEVI           VALUE 3000000000 THRU 3999999999.
        88 TITRE            VALUE 4000000000 THRU 4999999999.
        88 COMPTE-CORRECT   VALUE 1000000000 THRU 4999999999.

[...]

PROCEDURE DIVISION.

    IF NOT COMPTE-CORRECT
        DISPLAY '*** ERREUR TYPE DE COMPTE INCONNU: ' NUM-COMPTE
        DISPLAY '*** CLIENT: ' NOM ' ' PRENOM
    END-IF.


Deuxième exemple, positionnement d'un flag pour mémoriser le fait qu'une personne a été traiter en amont du programme:
DATA DIVISION.
01  FLAG-PERSONNE     PIC X(2).
    88 PERS-OK        VALUE 'OK'.
    88 PERS-KO        VALUE 'KO'.    

[...]

PROCEDURE DIVISION.

[...]

    MOVE 'OK' TO FLAG-PERSONNE.

[...]

    IF PERS-OK
            PERFORM TRAIT-COMPLET-PERSONNE
        ELSE
            PERFORM TRAIT-LIGHT-PERSONNE
    END-IF.
info Notez que les niveaux 88 qualifient toujours le niveau hiérarchique supérieur. Dans le premier exemple, les niveaux 88 qualifient le niveau 05 NUM-COMPTE, dans le deuxième exemple, ils qualifient le niveau 01 FLAG-PERSONNE.

1.4.2. L'instruction SET

Pour rendre le code encore plus "parlant", on peut utiliser l'instruction SET avec les niveaux 88.

Syntaxe
SET  nom-condition  TO  TRUE.

Cette instruction permet d'initialiser la zone groupe associée au nom-condition à la valeur de ce nom-condition.

En reprenant le deuxième exemple, au lieu de:
MOVE 'OK' TO FLAG-PERSONNE.

On aurait:
SET PERS-OK TO TRUE.

1.5. L'instruction NEXT SENTENCE

En COBOL 85, la structure suivante :
Si Condition-1
 |   Si Condition-2
 |    |   Traitement-1
 |   Fin si
Sinon
 |   Traitement-2
Fin si

Peut s'écrire ainsi:
IF condition-1
        IF condition-2        
            PERFORM TRAITEMENT-1 THRU FIN-TRAITEMENT-1
        END-IF
    ELSE
        PERFORM TRAITEMENT-2 THRU FIN-TRAITEMENT-2
END-IF.

En COBOL 74, du fait de l'absence du SCOPE-TERMINATOR END-IF, cette structure est intraduisible directement.

Le compilateur interprète le ELSE comme se rapportant au dernier IF, d'où l'obligation de coder une branche vide au deuxième IF à l'aide de NEXT SENTENCE:
IF condition-1
        IF condition-2        
                PERFORM TRAITEMENT-1 THRU FIN-TRAITEMENT-1
            ELSE
                NEXT-SENTENCE
    ELSE
        PERFORM TRAITEMENT-2 THRU FIN-TRAITEMENT-2
.
warning NEXT SENTENCE provoque un débranchement après le prochain point.

1.6. L'instruction CONTINUE

CONTINUE est une instruction que l'on peut également coder dans une branche vide d'un test. CONTINUE diffère de NEXT SENTENCE du fait que cette instruction a pour conséquence un débranchement au prochain ordre cobol et non à la prochaine phrase (soit après un point).


2. Le débranchement inconditionnel GO TO

GO TO permet de traduire l'instruction de débranchement inconditionnel "Aller à".

Dans une programmation structurée, on doit éviter l'usage du GO TO. D'ailleurs sur certains sites, les compilateurs sont paramétrés pour empêcher l'usage du GO TO et renvoient un code d'erreur sévère (12).

Sans faire un délire paranoïde sur le GO TO, son usage peut se justifier pour une sortie de programme du type "ALLER A LA FIN".
Syntaxe
GO [TO] nom-paragraphe

Le débranchement s'effectue à un nom de paragraphe (une étiquette) codée en colonne 8 avant ou après l'instruction GO TO. Exemple:
IF TRAITEMENT-KO
        GO TO FIN-PROGRAMME
    END-IF.

[...]

FIN-PROGRAMME.
    DISPLAY 'FIN DE PROGRAMME'.
    STOP RUN.

3. L'appel de module PERFORM


3.1. Syntaxe

Syntaxe
PERFORM  nom-paragraphe-1 [THRU nom-paragraphe-2]

3.2. Fonctionnement

PERFORM  A  →  A.
               ↓
               B.
On exécute toutes les instructions du paragraphe A jusqu'au prochain paragraphe.

PERFORM  A  THRU  C  →  A.
                        ↓
                        B.
                        ↓
                        C.
                        ↓
                        D.
On exécute toutes les instructions des paragraphes A, B et C inclus.


3.3. Exemple 1

PROCEDURE DIVISION.
FO-DEBUT.
    PERFORM  F1-INIT.
    STOP RUN.
	
F1-INIT.
    MOVE  ZERO  TO  A.
    MULTIPLY  C  BY  6  GIVING  D.
    ADD  D  5  TO  B.

F2-SUIT.

Les instructions du paragraphe F1-INIT sont exécutées en séquence jusqu'au paragraphe suivant.

info Vous pouvez vous abstenir de mettre un point après chaque phrase COBOL, mais un point est obligatoire à la fin d'un paragraphe.

3.4. Exemple 2

PROCEDURE  DIVISION.
01-PAR-A.
    PERFORM 02-PAR-B THRU 02-FIN
    STOP RUN
    .
	
02-PAR-B.
    MULTIPLY NUM-A BY NUM-B GIVING NUM-C ROUNDED
        ON SIZE ERROR
            DISPLAY 'ZONE NUM-C TROP PETITE'
            PERFORM 02-FIN
    END-MULTIPLY
    ADD NUM-C 2 TO NUM-A
    .
	
02-FIN.
    ADD 3 TO NUM-B
    ADD 1 TO I
    MOVE NUM-B TO NUM-C
    .
	
03-PAR-C.
On exécute toutes les instructions de 02-PAR-B et toutes celles de 02-FIN.


3.5. L'instruction EXIT

Syntaxe
nom-paragraphe. EXIT.

L'instruction EXIT indique qu'un paragraphe est vide. EXIT doit être le seul ordre d'un paragraphe. Exemple:
PROCEDURE  DIVISION.
    PERFORM DEBUT-PARAGRAPHE-1 THRU FIN-PARAGRAPHE-1.

DEBUT-PARAGRAPHE-1.
    ADD 1 TO I
    MOVE I TO WS-INDEX
    DISPLAY 'OK'
    .
    
FIN-PARAGRAPHE-1. EXIT.

DEBUT-PARAGRAPHE-2.
[...]

4. L'alternative complexe EVALUATE

C'est l'instruction COBOL qui permet de traduire le "choix selon" du pseudo-code et dont la représentation sous forme d'ordinogramme est la suivante :
|
                            ________|_______
                           |                |
                           |  CODE PRODUIT  |
                           |________________|
                                    |
                                    |
        ____________________________|___________________________
       |                  |                  |                  |
       | A                | B                | C                |  Autre
 ______|_______     ______|_______     ______|_______     ______|_______ 
|              |   |              |   |              |   |              |   
| traitement-A |   | traitement-B |   | traitement-C |   |   erreurs    |   
|______________|   |______________|   |______________|   |______________|   
       |                  |                  |                  |
       |                  |                  |                  |
       |__________________|__________________|__________________|
                                    |
                                    |
                                    |

En COBOL 74, cette structure complexe doit être découpée en une série de structures alternatives simples:
COBOL 74
PROCEDURE DIVISION.

    IF CODE-PRODUIT = 'A'
        PERFORM TRAIT-A THRU F-TRAIT-A
        PERFORM SUITE
    .

    IF CODE-PRODUIT = 'B'
        PERFORM TRAIT-B THRU F-TRAIT-B
        PERFORM SUITE    
    .

    IF CODE-PRODUIT = 'C'
        PERFORM TRAIT-C THRU F-TRAIT-C
        PERFORM SUITE    
    .

    PERFORM TRAIT-ERREUR THRU F-TRAIT-ERREUR.

SUITE.
    
	[...]

En COBOL 85, on peut traiter cette figure algorithmique en une seule instruction à l'aide d'EVALUATE:
COBOL 85
PROCEDURE DIVISION.

    EVALUATE CODE-PRODUIT
        WHEN A      PERFORM TRAIT-A THRU F-TRAIT-A
        WHEN B      PERFORM TRAIT-B THRU F-TRAIT-B
        WHEN C      PERFORM TRAIT-C THRU F-TRAIT-C
        WHEN OTHER  PERFORM TRAIT-ERREUR THRU F-TRAIT-ERREUR.

    END-EVALUATE.

SUITE.
    
	[...]

La syntaxe de l'instruction EVALUATE est la suivante:
Syntaxe
nom-donnée-1           nom-donnée-2
EVALUATE  expression-1    [ALSO  expression-2     ]...
          TRUE/FALSE             TRUE/FALSE


          ANY                    ANY
          littéral-1             littéral-4
          condition-1            condition-2
WHEN      TRUE/FALSE      [ALSO  TRUE/FALSE       ]...
          nom-donnée-3           nom-donnée-4
          littéral-2             littéral-5
          THRU littéral-3		 THRU littéral-6 		            


          ordre(s)-1
          
[WHEN...]...

[WHEN OTHER
          ordre(s)-2]

END-EVALUATE.

Lorsque les mots-clés TRUE et FALSE sont utilisés, cela suppose que des conditions ou des expressions sont utilisées dans les WHEN suivants.

ALSO permet de séparer plusieurs séries de tests.

Des exemples valent mieux qu'un long discours:
Exemple 1: EVALUATE TRUE
DATA DIVISION.
    05  RESULTAT         PIC 9V9.
        88  EXCELLENT    VALUE 5,0.
        88  BON          VALUE 4,0 THRU 4,9.
        88  MOYEN        VALUE 2,5 THRU 3,9.
        88  INSUFFISANT  VALUE 1,9 THRU 2,4.
        88  NUL          VALUE 0 THRU 1,8.				        

PROCEDURE DIVISION.

    EVALUATE TRUE
        WHEN EXCELLENT  PERFORM TRAIT-1 THRU F-TRAIT-1
        WHEN NUL        PERFORM TRAIT-2 THRU F-TRAIT-2
        WHEN OTHER      PERFORM TRAIT-3 THRU F-TRAIT-3
    END-EVALUATE.
Exemple 2: EVALUATE nom-donnée
DATA DIVISION.
    05  RESULTAT         PIC 9V9.
        88  EXCELLENT    VALUE 5,0.
        88  BON          VALUE 4,0 THRU 4,9.
        88  MOYEN        VALUE 2,5 THRU 3,9.
        88  INSUFFISANT  VALUE 1,9 THRU 2,4.
        88  NUL          VALUE 0 THRU 1,8.				        

PROCEDURE DIVISION.

    EVALUATE RESULTAT
        WHEN 5,0         PERFORM TRAIT-1 THRU F-TRAIT-1
        WHEN 0 THRU 1,8  PERFORM TRAIT-2 THRU F-TRAIT-2
        WHEN OTHER       PERFORM TRAIT-3 THRU F-TRAIT-3
    END-EVALUATE.
Exemple 3: EVALUATE expression
DATA DIVISION.
    05  RESULTAT         PIC 9V9.
        88  EXCELLENT    VALUE 5,0.
        88  BON          VALUE 4,0 THRU 4,9.
        88  MOYEN        VALUE 2,5 THRU 3,9.
        88  INSUFFISANT  VALUE 1,9 THRU 2,4.
        88  NUL          VALUE 0 THRU 1,8.				        

PROCEDURE DIVISION.

    EVALUATE RESULTAT <= 1,8
        WHEN TRUE        PERFORM TRAIT-2 THRU F-TRAIT-2
        WHEN FALSE       PERFORM ...
    END-EVALUATE.
Exemple 4: EVALUATE avec ALSO
PROCEDURE DIVISION.

    EVALUATE  A = B  ALSO  C > D  ALSO  TRUE
        WHEN  TRUE   ALSO  TRUE   ALSO  E = F + 15
              PERFORM TRAIT-1 THRU F-TRAIT-1
        WHEN  TRUE   ALSO  TRUE   ALSO  E > 12
              PERFORM TRAIT-2 THRU F-TRAIT-2
        WHEN  TRUE   ALSO  FALSE  ALSO  ANY
              PERFORM TRAIT-3 THRU F-TRAIT-3              
        WHEN  FASLE  ALSO  TRUE   ALSO  ANY
              PERFORM TRAIT-4 THRU F-TRAIT-4
        WHEN  OTHER
              PERFORM TRAIT-5 THRU F-TRAIT-5
    END-EVALUATE.

5. Les boucles: les autres formats du PERFORM

Dans sa syntaxe simple, nous avons vu que le PERFORM permettait d'appeler un module, puis de reprendre l'exécution en séquence. D'autres syntaxes du PERFORM permettent d'effectuer ces appels un certain nombre de fois et/ou de préciser des conditions d'arrêt de boucle.


5.1. PERFORM ... TIMES

C'est l'instruction Cobol qui permet de traduire le "répeter ... fin-répéter" du pseudo-code.
Syntaxe
PERFORM nom-paragraphe-1 [THRU nom-paragraphe-2] n TIMES
n peut être une constante ou une variable numérique entière.

Exemple:
PERFORM TRAIT-CLIENT 3 TIMES.
Le paragraphe TRAIT-CLIENT est exécuté 3 fois d'affilé.


5.2. PERFORM ... UNTIL

Syntaxe
PERFORM  nom-paragraphe-1  [THRU nom-paragraphe-2]
                           [WITH TEST BEFORE]
                           [WITH TEST AFTER]
         UNTIL condition

La clause WITH TEST BEFORE ou WITH TEST AFTER permet de préciser la position du test. Par défaut, la clause est WITH TEST BEFORE.

La condition spécifiée après le UNTIL peut prendre toutes les formes autorisées dans l'instruction IF. C'est une condition d'arrêt de la boucle.

Exemples:
WITH TEST BEFORE
PERFORM TRAITEMENT UNTIL A = 15
PERFORM WITH TEST BEFORE
WITH TEST AFTER
PERFORM TRAITEMENT WITH TEST AFTER UNTIL A = 15
PERFORM WITH TEST AFTER
warning La structure algorithmique "tant-que ... fin-tant-que" n'est pas traduisible en COBOL au sens strict car dans le "tant-que", la condition exprimée est une condition de continuation.

En inversant la condition du "tant-que" de l'algorithmique et en utilisant le PERFORM WITH TEST BEFORE, on obtient un "tant-que" à la sauce COBOL !

La structure "répéter ... jusqu'à" est traduisible en utilisant WITH TEST AFTER.

5.3. PERFORM ... VARYING ... UNTIL

Syntaxe
PERFORM  nom-paragraphe-1  [THRU nom-paragraphe-2]
         VARYING nom-donnée FROM valeur-initiale BY pas
         UNTIL condition

En plus des fonctionnalités du PERFORM ... UNTIL, le PERFORM ... VARYING ... UNTIL permet d'incrémenter une variable numérique à chaque débranchement.

  • nom-donnée permet de préciser le nom de la variable à incrémenter.
  • valeur-initiale indique la valeur d'initialisation de cette variable (valeur prise au premier débranchement).
  • pas précise la valeur d'incrémentation prise par la variable à chaque itération; la valeur spécifiée peut être négative.
Exemple:
PERFORM TRAITEMENT VARYING I FROM 5 BY 1
                   UNTIL I > 20.
PERFORM ... VARYING ... UNTIL
I prendra successivement les valeurs 1, 2, 3, 4 ... 20, 21. Pour cette dernière valeur le débranchement ne sera pas effectué, le test d'arrêt de boucle étant vérifié.

Cet exemple permet de mettre en valeur 3 points importants:

  1. Attention à la déclaration de la variable I. Dans l'exemple précédent I doit être déclaré au moins sur deux caractères numériques sinon la boucle est une boucle infinie.
  2. A la sortie de la boucle, I vaut le premier nombre pour lequel le test a été vérifié. Dans l'exemple précédent l'instruction DISPLAY I après le PERFORM donnerait le résultat 21.
  3. Il est fortement déconseillé de modifier la valeur de I à l'intérieur du PERFORM. Dans l'exemple précédent si I est réinitialisé dans le paragraphe TRAITEMENT, la boucle est infinie.

5.4. PERFORM ouvert

Les différentes syntaxes du PERFORM que nous venons d'étudier sont utilisées pour exprimer un débranchement à un module donné.

Il est possible de ne pas générer de débranchement et de coder les instructions à exécuter à l'intérieur du PERFORM, c'est-à-dire entre le verbe PERFORM et le SCOPE-TERMINATOR END-PERFORM. On parle alors de PERFORM in-line ou PERFORM ouvert.

Exemple:
PERFORM VARYING I FROM 1 BY 1 UNTIL I > 10
    MOVE ZERO  TO NUM (I)
    MOVE SPACE TO ALPHA (I)
END-PERFORM.

6. Remerciements




Valid XHTML 1.1!Valid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2006-2007 Guillaume Ventre. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.