Tous les articles par Mr COBOL

Cobol : un vieux langage terriblement à la mode

Serdar Yegulalp –31 Mai 2020

Le langage de programmation Cobol a beau avoir 60 ans, il fait tourner une grande partie des systèmes d'entreprise les plus critiques dans le monde. Et la demande en programmeurs Cobol ne faiblit pas.
Dans les années 60, les programmes Cobol étaient encodés sur des cartes perforées (Photo sous licence Creative Commons CC0 de l’architecte logiciel Rainer Gerhards).

Certaines technologies ne meurent jamais, elles se fondent simplement dans le décor. Evoquer Cobol – Common Business Oriented Language – avec le développeur moyen vous vaudra d’être regardé comme si vous parliez du papier carbone, de l’essence au plomb ou du disque 78 tours. Comparé aux langages modernes tels que Go ou Python, ou même Pascal ou C, Cobol semble massif, verbeux, démodé. Mais il a résisté. Loin d’être une technologie obsolète que nous aurions abandonnée, Cobol est devenu une institution. Des bases de code Cobol massives sont toujours utilisées à travers le monde, nombre d’entre elles fonctionnant presque exactement comme elles le faisaient lorsqu’elles ont été créées. Donc, oui, Cobol est toujours pertinent et opportun, il l’est même douloureusement en fait. Ces derniers mois, Cobol a réintégré la conscience publique quand des états comme le New Jersey ont lancé un appel aux programmeurs pour les aider à transférer leurs applications Cobol dans le 21ème siècle. Qu’est-ce qui fait que ce langage se démarque encore aujourd’hui et qu’est-ce qui le rend si tenace ?

Petit historique

Cobol est apparu à la fin des années 1950 et au tout début des années 1960. Son développement était un projet soutenu par le département américain de la Défense (DoD) qui incluait un consortium de fournisseurs informatiques dont IBM, Honeywell, Sperry Rand et Burroughs. L’objectif était de créer un langage de programmation ayant les attributs suivants. Premièrement, une portabilité entre systèmes informatiques afin de faciliter la migration du logiciel à la fois entre les générations de matériels et entre les fabricants de matériels. Deuxièmement, une syntaxe plus proche de l’anglais que les autres langages de l’époque (par exemple le Fortran) pour encourager une plus large audience à y recourir, même si cela devait se faire au détriment d’une certaine vitesse opérationnelle. Troisièmement, il devait pouvoir s’adapter aux changements. 

Les premières spécifications officielles sont sorties en 1960. Durant la décennie suivante, et à la consternation de ses détracteurs, Cobol devint de choix par défaut pour écrire les applications commerciales. Sa rapide propagation a résulté d’un effet de réseau. IBM, l’un des collaborateurs d’origine sur le langage, l’a adopté de façon précoce et vigoureuse et sa présence dominante dans le monde de l’informatique a contribué à l’adoption de Cobol. A cause de ses avantages de conception et de l’énorme soutien industriel dont il bénéficiait, Cobol a survécu, et de loin, aux systèmes pour lesquels il avait été élaboré à l’origine. Selon diverses estimations, en 1970, Cobol était le langage de programmation le plus utilisé dans le monde. En 1997, il devait faire tourner près de 80% des applications d’entreprise.

Le langage lui-même

Les concepteurs de Cobol ont rompu avec la syntaxe lapidaire des autres langages du moment (Fortran, encore lui). L’idée était qu’il puisse être lu et compris par des non-programmeurs, en particuliers des professionnels de la comptabilité, de la finance, de l’assurance et d’autres métiers. Prenons l’exemple d’une simple séquence « Hello World » écrite dans un des premiers dialectes de COBOL :

Pour des développeurs actuels habitués à la concision de langages tels que Python, ce code est verbeux. Mais la verbosité de Cobol vient du fait que le code est lu bien plus souvent qu’il n’est écrit, il doit donc être écrit pour être lisible. Une séquence similaire dans une version plus moderne de Cobol pourrait ressembler à cela :

Alors que cet exemple est plus concis, les mêmes principes de base s’appliquent : le code s’efforce d’être explicite sur ce qui se passe à chaque étape. Cobol a des règles strictes sur la syntaxe et sur l’organisation interne des programmes. Un programme Cobol est explicitement divisé en sections, ou divisions, qui aident à trouver et à comprendre ses composants d’un seul coup d’oeil :

– Identification division : essentiellement une section de métadonnées, contenant des détails sur le programme, son auteur, etc.

– Environnement division : contient des détails sur l’environnement de runtime, par exemple les alias pour les équipements externes, qui peuvent avoir besoin d’être modifiés lorsque le programme est exécuté sur un matériel différent. Cela aide à la portabilité entre systèmes quand, par exemple, les entrées/sorties peuvent être gérées de façon totalement différente.

– Data division : contenant les sections file et working storage, la division Data décrit les fichiers et les variables utilisés dans le programme.

– Procedure division : c’est ici que l’on trouve le véritable code du programme, séparé en unités logiques appelées sections, paragraphes, sentences et statements. Il est tentant de rapprocher, par analogie, aux modules ou fonctions, parce qu’elles remplissent à peu près les mêmes fonctions (elles divisent le code en blocs avec des contraintes sur les entrées et les sorties), mais elles sont beaucoup moins flexibles.

Des règles de formatage très strictes

Cobol a également des règles de formatage extrêmement strictes pour le code, allant jusqu’au nombre d’espaces précédant une commande. (Les utilisateurs de Python ne seront pas dépaysés) Certaines de ces restrictions sont un corollaire du passage à l’âge adulte de Cobol pendant l’ère mainframe des années 60, quand les programmes étaient encodés sur des cartes perforées et qu’il était important de respecter le respect du formatage à 80 colonnes. Mais les autres restrictions de formatage renforce la lisibilité.

Carte perforée provenant d’un réel programme Cobol mis au point pour un système Univac 90/30. (Photo sous licence Creative Commons CC0 de l’architecte logiciel Rainer Gerhards qui rappelle qu’en l’absence de numéros de lignes sur les cartes, il pouvait être assez problématique de les remettre dans l’ordre lorsqu’on en laissait tomber accidentellement un jeu). Agrandir l’image.

L’objectif de cette discipline stricte est de rendre les programmes Cobol aussi auto-documentés que possible. Après tout, ils allaient probablement rester en place pendant des années ou des décennies. L’intention (même si le résultat final ne l’atteignait pas toujours) était de faire de chaque programme Cobol un artefact que tout développeur Cobol pourrait comprendre, même des années plus tard, sans l’aide de celui qui l’avait créé.

Les challenges de Cobol

La permanence – et l’inertie – de Cobol vient en grande partie du fait que les applications qu’il a permis de générer, ont tendance, une fois écrite, à rester en place indéfiniment, avec juste quelques modifications mineures. Plus l’application est grosse et critique pour l’activité d’une entreprise, moins on cherche à la perturber. Les mainframes, centrés aujourd’hui sur l’offre d’IBM, jouent un rôle clé. Ils ont été construits pour être hautement rétrocompatibles et pour exécuter les logiciels existants tels que les applications Cobol sur plusieurs générations de machines avec des modifications minimales. Il en résulte que des milliards de lignes de code Cobol fonctionnent depuis des décennies, pratiquement sans aucun changement.

Au fil des années, Cobol a néanmoins évolué, même si ce fut lentement. Il existe même une variante orientée objet, OO-Cobol, qui inclut le support de fonctionnalités modernes telles que Unicode, des paramètres régionaux, et des types de données plus avancées au-delà des strings (chaînes de caractères) et integers (entiers). Mais il a farouchement conservé sa rétrocompatibilité. Donc, même ces améliorations et extensions collent à cette mission visant à continuer à faire fonctionner les applications Cobol existantes. Les choix de conception retenus n’ont pas tous été populaires auprès des programmeurs Cobol. Certains ont conduit à des programmes trop complexes qui se sont révélés difficiles à comprendre ou à déboguer, et ont découragé les réécritures ou les améliorations. La commande Go To, comme son équivalent en C, a permis aux programmeurs de se déplacer librement au sein un programme et ainsi d’écrire des applications plus puissantes. Mais l’utilisation indisciplinée de Go To peut transformer un programme Cobol en noeud de références croisées difficiles à suivre.

Programmer en Cobol aujourd’hui

Cobol survit aujourd’hui dans quelques incarnations. IBM maintient activement ses propres mises en oeuvre Cobol et gère de nombreuses applications qui les exploitent. Micro Focus Cobol est une édition commerciale qui s’exécute sur Windows de Microsoft, compile les applications Cobol vers Java et .Net et se déploie même dans des environnements clouds comme Azure. On trouve aussi des mises en oeuvre open source de Cobol, telles que GnuCobol, qui est disponible gratuitement et compile vers le code machine source. Toutefois, elles peuvent ne pas disposer des fonctionnalités de déploiement ou de débogage les plus avancées des Cobol commerciaux. Bien que Cobol reste largement utilisé, les expertises approfondies sur le langage deviennent de plus en plus difficiles à trouver au fil des années.

Il en résulte que de nombreux programmeurs Cobol à la retraite sont sollicités pour faire basculer les anciennes applications dans le 21ème siècle. Souvent, ce ne sont pas les connaissances dans le langage proprement dit qui sont les plus importantes, mais la compréhension intime des environnements mainframe dans lesquels Cobol s’exécute. De nombreuses applications fonctionnent étroitement avec des technologies telles que la base de données hiérarchique IMS et le gestionnaire de transactions CICS d’IBM, qui requièrent une expertise de plus en plus rare. Ainsi, aussi vieux jeu que Cobol peut apparaître, le besoin d’expertise pour ce langage et son environnement de développement s’est accru d’année en année. Les offres d’emploi qui recherchent ce type d’expertises abondent. En mars 2020, l’état américain du New Jersey a lancé un appel d’urgence aux programmeurs Cobol pour l’aider à améliorer les systèmes de prestations chômage en pleine crise de Covid-19. 

Apprendre Cobol

Compte-tenu de la demande croissante dont bénéficie Cobol, les développeurs modernes qui veulent se familiariser avec ce langage inoxydable ont plusieurs options. En Irlande, l’Université de Limerick propose un cours complet de programmation Cobol en ligne, avec l’aimable autorisation de son département des sciences informatiques et systèmes d’informations. Ce cours n’est pas aussi à jour que d’autres ressources, mais étant donné le peu de changement intervenu sur Cobol avec le temps, ce n’est pas nécessairement un défaut.

L’Open Mainframe Project propose également des ressources Cobol dont un cours de programmation complet, co-sponsorisé par IBM. Celui-ci est bien sûr plus actuel que le cours de l’Université de Limerick et il est adapté à la mise en oeuvre de Cobol sur zOS ( système d’exploitation des mainframes du constructeur) qui constitue une version largement déployée du langage. Cobol est un incontournable de l’informatique d’entreprise depuis des décennies et la demande de profils le connaissant ne cesse de croître. Si le maintien ou la modernisation des programmes Cobol vous intéresse, c’est plus que jamais le bon moment pour vous y mettre.

Article rédigé par
Serdar Yegulalp, Infoworld (adapté par Maryse Gros)


Article récupéré du site :
Le Monde Informatique


16. LA LINKAGE SECTION

Le programme principal et le sous-programme COBOL étant compilés séparément, il est nécessaire que la description des zones de données communes apparaisse dans les DATA DIVISION respectives des programmes.

Mais il est exclu de réserver 2 fois ces zones en mémoire centrale, c’est pourquoi une LINKAGE SECTION a été créée en DATA DIVISION.

Une zone de données commune “TRANSFERT” sera donc décrite normalement dans le programme principal soit en FILE SECTION soit en WORKING-STORAGE SECTION, et sa correspondance dans le sous-programme en LINKAGE SECTION.

L’ordre d’appel de sous-programmes CALL, aura donc pour effet d’attribuer les mêmes adresses mémoire à ces deux zones de données.

Remarque : rien n’oblige le programmeur à utiliser des descriptions de zones rigoureusement identiques entre le programme principal et le sous-programme. Les noms ne doivent pas être les mêmes ainsi que les descriptions de données.

La terminaison d’un sous-programme :

Dans un sous-programme, la terminaison est réalisée par GOBACK.

15. LES SOUS-PROGRAMMES EXTERNES

Le branchement du traitement depuis le programme principal COBOL vers les sous-programmes est réalisé par l’instruction CALL.

CALL 'Nom du sous programme' USING nom de donnée1 …

CALL 'Nom du point d'entrée' USING nom de donnée1 …


‘Nom du sous programme’ : désigne le nom du sous-programme appelé, nom doit être de maximum 8 caractères de long.

‘Nom du point d’entrée’ : désigne une adresse d’entrée dans un sous-programme, son nom doit être différent de celui du sous-programme et doit correspondre à un ENTRY.

Exemple :
CALL "SOUSPROG" USING ZON1 ZON2.
CALL "ENTREE" USING ZON1

LE SOUS-PROGRAMME COBOL

Le sous-programme en COBOL est construit comme tout programme COBOL avec ses 4 Divisions.
La différence avec le programme principal réside dans l’introduction de clauses USING et de la LINKAGE SECTION nécessaire à l’établissement d’une liaison entre les variables du programme principal et du sous-programme.

Cette correspondance est établie au moyen du USING (sous-programme) et du CALL (programme).

La clause USING dans le sous-programme :

PROCEDURE DIVISION USING nom-de-donnée-1 nom-de-donnée-2 …

Au moment de l’appel du sous-programme la correspondance entre les nom-de-donnée-1, nom-dedonnée-2 … est établie et le sous-programme démarre en utilisant les valeurs transférées par le programme principal.

Si l’entièreté du sous-programme ne doit pas être utilisée, nous disposons d’une option ENTRY pour indiquer au sous-programme l’endroit ou le sous-programme doit débuter.

Format :
ENTRY "nom-symbolique" USING nom-donnée-1 nom-donnée-2

Le même système opératoire sera activé et les nom-donnée-1 nom-donnée-2… seront mis en correspondance.

14. LES DECLARATIVES

Cobol a prévu un traitement particuliers en cas d’erreurs des E/S sur les fichiers. Ces traitements doivent être réalisés sous forme de séquences indépendantes regroupées dans une section de la PROCEDURE DIVISION sous le nom de DECLARATIVES.

Les DECLARATIVES sont importantes dans le cas où le programmeur n’aurait pas prévu de traitement dans le cas des erreurs d’E/S. En effet le système d’exploitation de l’ordinateur mettra fin à l’exécution du programme.

Forme générale :

PROCEDURE DIVISION.
DECLARATIVES.
Nom-de-section SECTION. USE ………….
Nom-de-paragraphe.
      Instructions Cobol
END DECLARATIVES.

Les DECLARATIVES commencent toujours par le mot DECLARATIVES, immédiatement après PROCEDURE DIVISION, sont toujours dans une SECTION et se terminent toujours par END DECLARATIVES.

FORMAT :

Si nom-de-fichier est spécifié les DECLARATIVES ne s’appliquent que pour ce ou ces fichiers.

INPUT indique que la section DECLARATIVES sera utilisée pour tous les fichiers ouverts en lecture.

OUTPUT indique que la section DECLARATIVES sera utilisée pour tous les fichiers ouverts en écriture.

I-O indique que la section DECLARATIVES sera utilisée pour tous les fichiers ouverts en lecture et en écriture.

L’instruction USE indique que le branchement n’a lieu qu’après que les routines du système d’exploitation aient été effectuées.

L’option AFTER peut être remplacée par BEFORE.

13. L’INSTRUCTION SET

Syntaxe de l’instruction SET :

SET

Un nombre entier est un entier numérique > 0 et non signé.
Les index-names sont définis par des clauses INDEXED BY.

Cette instruction signifie :

METTRE nom-index-1 A LA VALEUR CORRESPONDANT A index-name-3 avec le numéro d’occurrence nombre entier

Nombre entier représente un numéro d’occurrence de l’élément qu’on désire repérer.

Exemple : SET INDEX1 TO 5, signifie que nous voulons utiliser le 5ème élément de la table. Ce n’est pas la valeur 5 que nous retrouverons dans INDEX1 mais l’adresse correspondant au déplacement de l’élément par rapport au début de la table.
Lorsque index-name-3 est utilisé, il a ajustement de index-name-1 index-name-2 … sur indexname-3 et COBOL traduit le contenu de index-name-3 en occurrence avant de calculer les valeurs de index-1 index-2.

   01 TABLE.
      02 T1 OCCURS 20 INDEXED BY IND1.
         03 T2 OCCURS 30 INDEXED BY IND2.
            04 T3 OCCURS 40 INDEXED BY IND3 PIC 9.

Pour utiliser T3 (5,6,5),    SET IND3 TO 5
                      SET IND1 TO IND3
                      SET IND2 TO 6

Format 2 :

Cette instruction permet avec UP BY d’augmenter ou de diminuer DOWN BY la valeur de indexname-1 et de index-name-2 d’une valeur de nombre ou de index-3. INDEX-3 ne doit pas appartenir à la table de index-1 ou index-2 car le COBOL traduit sa valeur en nombre d’occurrences.

Il est à prévoir que durant l’exécution du programme nous devions retenir une valeur particulière d’index. Dans ce cas nous serons amenés à déclarer une zone particulière d’usage réservé aux INDEX.

01 INDEX-DE-RESERVE USAGE IS INDEX.

Cette clause est utilisée à n’importe quel niveau en DATA DIVISION. Il ne sera pas fait usage de la clause PICTURE puisque cette donnée contiendra une adresse pour notre index.
Lorsque cette clause est spécifiée pour un groupe, ce sont toutes les zones élémentaires du groupe qui sont considérées comme d’usage index.

Pour sauvegarder la valeur de IND2 :
SET INDEX-DE-RESERVE TO IND2

Pour lui retourner sa valeur plus tard :
SET IND2 TO INDEX-DE-RESERVE

12. L’INSTRUCTION STOP

Syntaxe de l’instruction STOP :

STOP RUN

Le format 1 indique la fin du traitement dans un programme puis à rendre le contrôle au superviseur. Il peut y avoir plusieurs STOP RUN dans un même programme mais en programmation structurée un seul est suffisant.

11. L’INSTRUCTION EXIT

Syntaxe de l’instruction EXIT :
Nom-de-paragraphe. EXIT.

Cette instruction sert à fournir un point unique de fin d’une série de paragraphes appelés par PERFORM. Ce paragraphe sert de délimiteur de fin et peut donc être utilisé par un GO TO éventuel à l’intérieur de ce bloc.

Le nom-de-paragraphe sera donc placé après l’option THRU du PERFORM.

Exemple :
    PERFORM P1 THRU P2.

P1.
    IF A > B GO TO P2.
P2. EXIT.

Si la logique du programme demande de sortir de P1 avant la fin de l’ensemble des instructions, le fait de passer via P2 ne rompt pas les liens de notre PERFORM.

10. L’INSTRUCTION PERFORM

Il arrive fréquemment qu’une même séquence d’instructions intervienne à différents endroits dans le cours du programme. Il vient alors à l’esprit de n’écrire cette séquence d’instructions qu’une seule fois et de s’y référer chaque fois que cela s’avère nécessaire.

Si une telle séquence est extérieure au programme et donc compilée séparément on l’appellera un sous-programme et son utilisation sera réalisée au moyen d’une instruction CALL.
Si au contraire cette séquence d’instructions fait partie du programme, il s’agira alors d’une séquence indépendante sur laquelle on se branche par une instruction PERFORM.

Format 1 :
PERFORM paragraphe-1 [THRU parapgraphe-2]

Exemple :
PERFORM PAR1.

Cette instruction PERFORM provoque le branchement au paragraphe portant le nom de PAR1, lorsque le traitement de la dernière instruction de PAR1 est terminé le contrôle du programme repasse à l’instruction qui suit immédiatement le PERFORM.

Exemple :
PERFORM P1 THRU P3.

Dans ce cas, il y a branchement vers le paragraphe P1 et toutes les instructions comprises entre P1 et la dernière instruction du paragraphe P3 sont exécutées. Entre P1 et P3 il peut y avoir d’autres paragraphes qui seront traités de la même manière. Dans ce cas une instruction de type GO TO limitée à ces paragraphes ne rompt pas les liens de la programmation structurée.
Il arrive aussi que dans ce cas la seule et unique instruction du dernier paragraphe soit une instruction EXIT, qui ne génère rien mais permet le transfert en fin de procédure.

Exemple:
PERFORM P1 THRU P5.
P1.

P3.
    GO TO P5.
P4.

P5. EXIT.

Un format particulier du PERFORM existe sous la forme
PERFORM
instructions Cobol
END-PERFORM

Ce qui est équivalent à un bloc dont le début est le mot clé PERFORM et la fin END-PERFORM.

Exemple :
IF A = B PERFORM
           Instructions Cobol
         END-PERFORM

Format 2 :

Nom-de-donnée (ou entier) représente le nombre de fois que le ou les paragraphes désignés par le PERFORM doivent être exécutés successivement avant de revenir à l’instruction suivant le PERFORM.

        PERFORM X TIMES
                Instructions COB
        END-PERFORM

Avec X comme variable ou constante numérique entière.

Exemple: PERFORM P3 5 TIMES.

Format 3 :

Exemple :

        PERFORM CALCUL UNTIL ECART < 0.01

        CALCUL.
                MOVE X TO X0.
                COMPUTE X = (X0 + (A / X0)) / 2
                SUBTRACT X0 FROM X GIVING ECART.
OU
        PERFORM UNTIL ECART < 0.01
                MOVE X TO X0
                COMPUTE X = (X0 + (A / X0)) / 2
                SUBTRACT X0 FROM X GIVING ECART
        END-PERFORM.

Le paragraphe ou les instructions seront exécutées jusqu’à ce que la condition soit satisfaite, en option on peut choisir d’effectuer le test de la condition avant de pénétrer dans la boucle ou en sortie de la boucle.

Format 4 :

Exemple :
PERFORM TOUR WITH TEST AFTER
        VARYING J FROM 1 BY 1 UNTIL J > 10

Dès que la condition J > 10 est satisfaite, le traitement passe à l’instruction qui suit le PERFORM, il en va de même pour le PERFORM sans paragraphe.

PERFORM VARYING I FROM –100 TO 100 BY 5 UNTIL I > 100

PERFORM RECHERCHE VARYING I FROM 1 BY 1 UNTIL I > 25
                    AFTER K FROM 1 BY 1 UNTIL K > 25
                    AFTER M FROM 1 BY 1 UNTIL M > 25.

Le Cobol autorise les indices négatifs.

Avec AFTER on considère qu’il y a 3 boucles imbriquées dont la dernière tourne le plus rapidement, lorsque sa condition est remplie, on remonte d’un niveau et la boucle inférieure recommence et ainsi de suite jusqu’à ce que toutes les boucles atteignent leur condition d’arrêt.

Pour mettre un tableau à 2 dimensions à ZERO.

01 TABLEAU.
    02 LIGNE OCCURS 20.
        03 COLL OCCURS 20 PIC 99.

PROCEDURE DIVISION.
DEB.
    PERFORM VARYING J FROM 1 BY 1 UNTIL J >20
            AFTER K FROM 1 BY 1 UNTIL K > 20
            MOVE 0 TO COLL( J, K)
    END-PERFORM.

Dans ce genre de PERFORM et selon les besoins du programmeur, on peut utiliser soit 1, soit 2 soit 3 indices de boucles.

Cette instruction peut également utiliser des valeurs INDEX plutôt que des variables numériques, ce qui en fait une instruction de choix pour la manipulation des tableaux avec indices ou index.

Exemple:
01 TABLE.
    02 NOM OCCURS 200 PIC X(25) INDEXED BY J.

PROCEDURE DIVISION.
DEBUT.
    PERFORM VARYING J FROM 1 BY 1 UNTIL J > 200
        MOVE SPACES TO NOM(J)
    END-PERFORM.

9. LES BRANCHEMENTS

Les instructions GO TO et ALTER

Format :

GO TO nom-de-paragraphe

ALTER nom-de-paragraphe TP PROCEED TO nom-de-paragraphe2

Le GO TO indique un branchement immédiat vers le nom de paragraphe spécifié, il rompt ainsi les liens que la programmation structurée a créés.

L’ALTER permet de modifier le nom du paragraphe vers lequel un GO TO renvoi. Ce GO TO doit être la seule instruction contenue dans le paragraphe nom-de-paragraphe et nom-de-paragraphe-2 est le nom de paragraphe auquel le GO TO doit brancher le programme.

P1. GO TO TRF.
P2. ……
    ……..
    ALTER P1 TO PROCEED TO P3.
P3.

Tout transfert vers P1 signifie GO TO P3. Il est possible de ne pas écrire TRF dans le GO TO de P1 mais alors le programmeur doit commencer par affecter un ALTER à ce paragraphe.

GO TO DEPENDING

Format :

GO TO paragraphe1 paragraphe2 paragraphe3 ... paragraphe-n
    DEPENDING ON nom-de-donnée.

Nom-de-donnée représente une zone de donnée numérique entière, quand il contient la valeur 1, le branchement est fait au premier paragraphe. Quand la valeur est 2 c’est le 2ème paragraphe qui est utilisé et ainsi de suite.

Exemple :
GO TO P1 P2 P3 P4 P5 DEPENDING ON VARTEST.

Si VARTEST contient une valeur incompatible avec le GO TO alors cette instruction est ignorée.

8. LA PROCEDURE DIVISION

8.1 LA GESTION DES FICHIERS – Les Entrées-Sorties

Un fichier est une collection de données répétitives analogues portant sur des individus ou des objets différents. Un fichier est un ensemble d’enregistrements différents mais contenant le même genre de structure.
Un tel ensemble pourrait très bien se trouver en mémoire centrale mais nous ne parlerons de fichier que lorsque l’ensemble des informations se trouve sur un périphérique externe disque ou bande.

On utilise des fichiers pour plusieurs raisons, tout d’abord par opposition avec la mémoire ou dés la fermeture de l’ordinateur toutes informations en mémoire est perdue, sur disque nous pouvons les conserver le temps nécessaire.
Les mémoires centrales sont limitées et la masse d’information à traiter peut être supérieure à l’espace disponible.
Les données contenues dans un fichier peuvent être utilisées par différents programmes et peuvent même être échangées entre ordinateurs.

Le COBOL permet 3 types d’organisations de fichier :
– l’organisation séquentielle
– l’organisation séquentiel indexée
– l’organisation relative.

Par organisation, il faut entendre la façon dont le fichier est organisé physiquement sur le support et l’accès à un enregistrement est la manière que nous utilisons pour atteindre cet enregistrement.

Un accès est dit séquentiel lorsque pour lire le 25ème
record du fichier, il est obligatoire de lire les 24 précédents. C’est ce type d’accès qui est utilisé sur bande magnétique.

Un accès est dit sélectif lorsqu’un record bien précis du fichier peut être atteint sans devoir lire tous ceux qui le précédent. Ce type d’accès oblige l’utilisation d’une clé permettant de retrouver la position de l’enregistrement dans le fichier. Ce type d’accès ne s’utilise que pour les périphériques disques.
Tous les ordres d’entrées-sorties ne concernent toujours qu’un seul enregistrement à la fois.
Cobol oblige le programmeur à ouvrir chaque fichier par un ordre OPEN avant de pouvoir lire ou écrire sur un fichier. De même, chaque fichier sera fermé par une instruction CLOSE en fin de travail.

OUVERTURE DES FICHIERS OPEN

Un ordre d’ouverture de fichiers OPEN doit être donné pour tous les fichiers utilisés dans le programme en séparant les fichiers ENTREE de lecture INPUT, des fichiers SORTIE en écriture OUTPUT et EXTEND. Cette instruction OPEN doit toujours précéder les instructions de lecture ou d’écriture.

              |  INPUT   nom-de-fichier-1  |
Format : OPEN |  OUTPUT  nom-de-fichier-2  |
              |  I-O     nom-de-fichier-3  |
              |  EXTEND  nom-de-fichier-4  |

Un fichier ne peut être cité qu’une seule fois dans une clause OPEN.
Il n’est pas obligatoire d’ouvrir tous les fichiers en même temps.

Un fichier ne doit être ouvert qu’une fois, un second passage dans la même instruction OPEN sans être passé par une instruction CLOSE pour ce fichier entraîne une erreur dans le programme.
L’ouverture d’un fichier positionne le pointeur d’enregistrement au début du fichier sauf pour l’ouverture en EXTEND.

La clause INPUT déclare que le fichier est ouvert uniquement pour être lu. Donc ce fichier doit déjà exister.

La clause OUTPUT déclare que le fichier est ouvert uniquement pour qu’on y écrive. Si le fichier existe déjà avec ses enregistrements, un OPEN OUTPUT les efface, le fichier est alors vidé de son contenu, et un nouveau fichier est créé.

La clause I-O déclare un fichier comme étant ouvert en même temps en lecture et en écriture.

La clause EXTEND déclare le fichier comme étant ouvert en écriture, le fichier n’est pas vidé de son contenu, le pointeur d’enregistrement se positionne à la fin du fichier. Seul un fichier à organisation séquentiel peut être ouvert en extend.

Un essai d’ouverture en lecture d’un fichier non existant génère une erreur d’exécution.

Exemple :
OPEN INPUT FICH1 FICH2
     OUTPUT IMPR FPCLIENT.

OPEN INPUT FICH1.
OPEN INPUT FICH2.
OPEN OUTPUT IMPR.
OPEN OUTPUT FPCLIENT.

Nous obtenons le même résultat dans les 2 cas mais le premier est plus rapide.

FERMETURE DES FICHIERS – CLOSE.

Format :
CLOSE nom-de-fichier1 nom-de-fichier2 ….

Un ordre de fermeture doit être donné pour tous les fichiers utilisés, donc ouverts et ceci avant l’instruction STOP RUN. Dans cette instruction on ne fait pas de distinction entre les fichiers INPUT ou OUTPUT, tous les fichiers peuvent être fermés en même temps.
Exemple : CLOSE FICH1 FICH2 IMPR FPCLIENT.

LECTURE DE FICHIERS SEQUENTIELS – READ

La description du fichier et celle de son enregistrement ont déjà été réalisées dans la DATA DIVISION, de ce fait pour le programme tout se déroule comme si le fichier n’était composé que d’enregistrements logiques qui lui sont délivrés les uns après les autres à chaque ordre de lecture.

Format :
READ nom-de-fichier | INTO nom-donnée | AT END ordre impératif.

Exemple : READ FPCLIEN INTO STRWSS AT END MOVE 1 TOSWFIN.

Remarque : si le fichier est composé d’enregistrements de différentes structures, ils seront délivrés dans la même zone déclarée en FILE SECTION. (pour rappel : redéfinition implicite)

READ InternalFilename [NEXT] RECORD
      [INTO Identifier]
      AT ENDStatementBlock
END-READ

AT END ordre impératif est toujours obligatoire et indique l’opération ou la série d’opération qui doivent être exécutées lorsque la fin du fichier est atteinte.

INTO nom-donnée signifie que le programmeur désire travailler dans une autre zone que celle définie sous le FD du fichier. Soit directement dans une autre structure de fichier soit dans une zone de la Working-storage section. INTO est équivalent à un MOVE de structure à structure.

PERFORM UNTIL StudentRecord = HIGH-VALUES
READ StudentRecords AT END MOVE HIGH-VALUES TO StudentRecord
END-PERFORM.

ECRITURE DE FICHIERS SEQUENTIELS – WRITE

L’instruction WRITE transfère le contenu de la mémoire dans le fichier à la position où l’on se trouve dans le fichier.

Format : WRITE nom-enregistrement [ FROM nom-de-donnée-1 ] .

FROM est équivalent à un MOVE d’une donnée vers la structure d’enregistrement.

Il faut prendre garde au fait que l’on lit un fichier mais que l’on écrit un enregistrement.

FICHIER IMPRIMANTE – WRITE

Format : WRITE nom-enregistrement [ FROM nom-donnée-1 ]

__                                                                                                                          __
| | BEFORE   |    ADVANCING   | nom-de-donnée-2 LINES | |
| | AFTER       |                                      | nombre entier          LINES | |
|                                                                  |                                                          | |
|                                                                  | PAGE                                            | |
L                                                                                                                              J

BEFORE signifie que l’écriture de la ligne sera faite avant le saut de ligne.

AFTER l’écriture sera faite après le saut de ligne.

Le nombre de lignes qu’il faut sauter est donné par la variable nom-de-donnée-2 ou par le nombre entier.

WRITE L80 FROM LIGNE1 AFTER 4.
WRITE L80 FROM LIGNE1 AFTER XLIG.

Nom-de-donnée-2 doit être une zone élémentaire < à 100. La position d’impression est alors avancée de la valeur donnée. Il est conseillé de ne pas mélanger les after et les before.

PAGE signifie que la ligne à imprimer, doit l’être sur la première ligne de la page suivante.

WRITE L80 FROM TITRE AFTER PAGE.

Une bonne organisation du programme consiste à déclarer et définir toutes les lignes d’impression en WORKING-STORAGE SECTION sous la forme suivante :

WORKING-STORAGE SECTION.
01 TITRE PIC X(80) VALUE "CECI EST LE TITRE DE LA PAGE".
01 STITRE PIC X(80) VALUE ALL "_".
01 LIGNE1.
   02 FILLER PIC X(25) VALUE " DATE LIBELLE ".
   02 FILLER PIC X(30) VALUE " DESCRIPTION ".
   02 FILLER PIC XXX VALUE "LE".
   02 JJ PIC 99.
   02 FILLER PIC X VALUE "/".
   02 MM PIC 99.
   02 FILLER PIC X VALUE "/".
   02 ANNEE PIC 9999.
PROCEDURE DIVISION.
DEB.
      ACCEPT MADATE FROM DATE.
      OPEN OUTPUT IMPR.
      WRITE LIMPR FROM TITRE.
      WRITE LIMPR FROM STITRE.
      MOVE JOUR TO JJ
      MOVE MOIS TO MM
      MOVE AN TO ANNEE
      WRITE LIMPR FROM LIGNE1.
      CLOSE IMPR.
      STOP RUN.

Dans le cas d’un fichier de données

    OPEN OUTPUT StudentFile.
    MOVE "9334567Frank Curtain LM051" TO StudentDetails.
    WRITE StudentDetails.
    MOVE "9383715Thomas Healy LM068" TO StudentDetails.
    WRITE StudentDetails.
    CLOSE StudentFile.
    STOP RUN.

STATUS KEY

Il est possible de contrôler le bon achèvement d’une instruction d’entrèe-sortie grâce à un indicateur comportant 2 caractères numériques.
Tout d’abord la clause FILE STATUS is nom-de-donnée dans l’ENVIRONMENT DIVISION au niveau de la clause SELECT doit être définie.
Nom-de-donnée doit être déclaré en WORKING-STORAGE SECTION sous la forme d’un PIC XX. Ensuite l’ordinateur fait le reste, à chaque OPEN – READ – WRITE – CLOSE – …. Il vérifie le bon fonctionnement de l’instruction utilisée et dans ce cas la variable nom-de-donnée est remplie d’un “00” ce qui signifie que l’instruction c’est bien déroulée. Dans le cas contraire il existe dans le manuel du compilateur utilisé une série de code 10 30 34 90 92 96 …. Qui indique le mauvais fonctionnement de l’opération, soit que le fichier n’est pas trouvé, que le EOF est rencontré ou une erreur sur la longueur ou sur la clé etc..

Exemple :

SELECT OPTIONAL FPCLIEN ASSIGN TO DISK
     FILE STATUS IS SKCLIEN.

WORKING-STORAGE SECTION
01 SKCLIEN PIC XX VALUE "00".

PROCEDURE DIVISION.
DEB.
     OPEN INPUT FPCLIEN.
     IF SKCLIEN NOT = "00" PERFORM ERREUROPEN.

L’INSTRUCTION ACCEPT

Le verbe ACCEPT est un verbe particulier de lecture de données à partir de l’écran. On lira toujours des blocs de 80 caractères, même si vous ne devez en lire que 16 par exemple.

Format : ACCEPT nom-de-donnée [ FROM nom-symbolique ]

Le nom-de-donnée représente une zone de donnée en WORKING-STORAGE SECTION dans laquelle seront transmis les octets transmis par le périphérique.

Le nom-symbolique permet de définir un système autre que l’écran pour l’introduction des données.

!!! Attention !!! : cette option est différente selon le compilateur ou l’ordinateur utilisé, référencez-vous auprès de votre manuel utilisateur du Labo

Format spécial de l’instruction ACCEPT

                          | DATE |
ACCEPT nom-de-donnée FROM | DAY  |
                          | TIME |

Ce format permet de transférer dans la zone nom-de-donnée le contenu de l’un de 3 compteurs spéciaux DATE DAY TIME.

DATE est un PIC 9(6) pour AA MM JJ sous la forme 990526

DAY est un PIC 9(5) pour AA JJJ sous la forme 99236

TIME est un PIC 9(8) pour HH MM SS CS

Exemple :

01 DATE-DU-JOUR.
   02 AN   PIC 99.
   02 MOIS PIC 99.
   02 JOUR PIC 99.
PROCEDURE DIVISION.
   ACCEPT DATE-DU-JOUR FROM DATE.

En version 2000
ACCEPT DATE-DU-JOUR FROM CENTURY-DATE
01 DATE-DU-JOUR.
   02 AN   PIC 9999.
   02 MOIS PIC 99.
   02 JOUR PIC 99

Ce verbe correspond à l’émission de données vers l’imprimante ou l’écran.

                | nom-de-donnée-1 | | nom-de-donné-2 |
Format : DISPLAY |                                              |    |                                            | …
                | littéral-1      | | littéral-2     |

               UPON nom-symbolique.

Exemple :
DISPLAY "FIN DU PROGRAMM".
DISPLAY MESSAGE1.

Le nom-symbolique PRINTER indique l’écriture sur l’imprimante.

Le nom-de-donnée peut être une structure.

8.2 LES INSTRUCTIONS ARITHMETIQUES

Ces instructions sont de 2 types:

  • les opérations simples :
    ADD
    SUBTRACT
    MULTIPLY
    DIVIDE
  • les opérations complexes :
    COMPUTE et ses opérateurs + – * / **

Ces instructions disposent d’options communes :

GIVING nom-de-donnée :
qui indique que le résultat de l’opération sera mémorisé dans nom-de-donnée.
ADD VAR1 VAR2 GIVING RESULTAT

ROUNDED :
après une opération le résultat tronque les décimales au-delà de ce qui
a été déclaré dans la PIC. Ainsi la quantité 234,478 sera de 234,4 si la
PIC de la variable résultat est de 999V9.
Avec ROUNDED, COBOL ajoute 5 au premier chiffre non significatif de droite pour réaliser l’arrondi à l’unité supérieure du chiffre le moins significatif si le premier chiffre non significatif de droite est >= 5.
Avec rounded notre exemple devient 234,5.

ON SIZE ERROR ordre impératif

Cette option permet de prévenir des incidents de calcul comme :
– la division par zéro
– les dépassements de capacité (pour rappel un numérique est limité à 18 chiffres)

exemple : DIVIDE A BY B ON SIZE ERROR MOVE ZERO TO B

!!!! Les calculs ne pourront se faire naturellement qu’avec des zones élémentaires numériques, il en ira de même pour les constantes. !!!!

L’ADDITION – ADD

Format n°1 :

    | nom-de-donnée-1      | | nom-de-donné-2       |
ADD |                                                         |     |                                                          |
    | littéral-numérique-1 | | littéral-numérique-2 |

    TO nom-de-donnée
[ ROUNDED].
     nom-de-donnée
-n [ ROUNDED].
   [ ON SIZE ERROR ordre-impératif
].

On ajoute nom-de-donnée-1 ou littéral-numérique-1 et nom-de-donnée-2 ou littéral-numérique-2 à la variable nom-de-donnée et le résultat peut être arrondi.

Exemple :

ADD 1000 QTE1 TO TOTAL ROUNDED ON SIZE ERROR MOVE 0 TO TOTAL

Ce qui signifie ajouter 1000 + QTE1 + TOTAL arrondir, transférer le résultat de l’opération dans TOTAL. En cas d’erreur mettre TOTAL à 0.

Format n° 2 :

    |nom-de-donnée-1| |nom-de-donné-2|     |nom-de-donné-n|
ADD |                                         |    |                                      | … |                                        |
    | littéral-1    | | littéral-2   |  | littéral-n   |

    GIVING nom-de-donnée
[ ROUNDED].
   [ ON SIZE ERROR ordre-impératif
].

Dans ce cas on ajoute nom-donnée-1 à nom-donnée-2 à….. nom-donnée-n le résultat est placé dans nom-de-donnée, éventuellement arrondi.

Exemple :
ADD TVA TOTHTVA GIVING TOTTVAC

Format n°3 :

ADD CORRESPONDING nom-de-groupe-1 TO nom-de-groupe2
[ ROUNDED ] [ ON SIZE ERROR ordre-imp. ]

Avec ce format, les zones élémentaires du groupe-1 sont additionnées aux données élémentaires du groupe-2 ayants des noms-données identiques, et les résultats sont placés dans les zones élémentaires du groupe-2.

L’abréviation COBOL de CORRESPONDING est CORR. Les clauses OCCURS et REDEFINES sont mal supportées.

Prenons par exemple un fichier paie mensuel d’enregistrement ENRMENS et le fichier ENRTOT.

De description :

01 ENRMENS.
   02 CODE-EMPLOYEE PIC 999.
   02 HEURE-P       PIC 999.
   02 SAL-BRUT      PIC 9(6).
01 ENRTOT.
   02 COD-EMPL      PIC 999.
   02 HEURE-P       PIC 999.
   02 SAL-BRUT      PIC 9(6).
   02 SAL-NET       PIC 9(6).

Le fait d’écrire ADD CORR ENRMENS TO ENRTOT, engendre les additions suivantes :

HEURE-P OF ENRTOT = HEURE-P OF ENRTOT + HEURE-P OF ENRMENS
SAL-BRUT OF ENRTOT = SAL-BRUT OF ENRTOT + SAL-BRUT OF ENRMENS

ADD identifier-1 TO identifier-2
         ROUNDED ON SIZE ERROR ordre-impératif-1
         NOT ON SIZE ERROR ordre impératif-2
END-ADD

ADD identifier-1 TO identifier-2
         GIVING identifier-3 ROUNDED
         ON SIZE ERROR ordre-impératif-1
         NOT ON SIZE ERROR ordre-impératif-2
END-ADD

Identifier-1 peut être une constante ou une variable numérique ou un ensemble des deux.
Les ordres impératifs 1 et 2 peuvent être constitués d’une ou de plusieurs instructions.
Avec l’option GIVING identifier-2 peut également être une constante numérique puisque le résultat est placé dans identifier-3.

LA SOUSTRACTION – SUBTRACT

Format 1 :

        |Identifier-1|
SUBTRACT|                                 |   FROM identifier-2 ROUNDED
        | littéral-1 |

        ON SIZE ERROR ordre-impératif-1

      NOT ON SIZE ERROR ordre-impératif-2

END-SUBTRACT

Format 2 :

        |Identifier-1|      |Identifier-2|
SUBTRACT|                                 |   FROM |            |
        | littéral-1 |      | littéral-2 |

      GIVING  identifier-3
 
    ROUNDED ON SIZE ERROR ordre-impératif-1

          NOT ON SIZE ERROR ordre-impératif-2

END-SUBTRACT

Format 3 :

SUBTRACT CORR identifier-1 FROM identifier-2 ROUNDED
ON SIZE ERROR ordre-impératif-1
NOT ON SIZE ERROR ordre-impératif-2
END-SUBTRACT

Remarques:
identifier-1 peut être une série de variables ou de constantes numériques.
Les options ROUNDED et ON SIZE ERROR ne sont pas obligatoires.
END-SUBTRACT ne s’applique que si les options SIZE ERROR sont utilisées.

Exemple :
SUBTRACT V1 V2 12 FROM TOTAL. (TOTAL = TOTAL – (V1 + V2 + 12))
SUBTRACT V1 V2 12 FROM TOTAL GIVING SOUSTOT.
(SOUSTOT = TOTAL – (V1 + V2 + 12))

Dans le 1er cas TOTAL doit être un numérique de travail, dans le 2ème cas SOUSTOT peut être un numérique d’édition car il n’intervient pas dans le calcul.

LA MULTIPLICATION – MULTIPLY

Format 1 :

        |Identifier-1|
MULTIPLY|                                 |   BY identifier-2 ROUNDED
        | littéral-1 |

        ON SIZE ERROR ordre-impératif-1

        NOT ON SIZE ERROR ordre-impératif-2

END-MULTIPLY

Format 2 :

         |Identifier-1|     |Identifier-2|
MULTIPLY |                                 |    BY |            |
         | littéral-1 |     | littéral-2 |

      GIVING  identifier-3
 
    ROUNDED ON SIZE ERROR ordre-impératif-1

          NOT ON SIZE ERROR ordre-impératif-2

END-MULTIPLY

Exemple :
MULTIPLY 12 BY V1.           ( V1 = V1 * 12)
MULTIPLY V1 BY V2 GIVING V3. ( V3 = V1 * V2)

LA DIVISION – DIVIDE

Format 1 :

       |Identifier-1|
DIVIDE |                                 |   INTO identifier-2 ROUNDED
       | littéral-1 |

        ON SIZE ERROR ordre-impératif-1

        NOT ON SIZE ERROR ordre-impératif-2

END-DIVIDE

Format 2 :

         |Identifier-1| |INTO| |Identifier-2|
DIVIDE   |                                 | |    | |            |
         | littéral-1 | | BY | | littéral-2 |

      GIVING  identifier-3
 
    ROUNDED ON SIZE ERROR ordre-impératif-1

          NOT ON SIZE ERROR ordre-impératif-2

END-DIVIDE

Format 3 :

         |Identifier-1| |INTO| |Identifier-2|
DIVIDE   |                                 | |    | |            |
         | littéral-1 | | BY | | littéral-2 |

      GIVING  identifier-3
      ROUNDED
REMAINDER identifier-4
 
    ON SIZE ERROR ordre-impératif-1

      NOT ON SIZE ERROR ordre-impératif-2

END-DIVIDE

Exemple :
DIVIDE 10 INTO V1. (V1 = V1 / 10)
DIVIDE V1 BY V2 GIVING V3. ( V3 = V1 / V2)
DIVIDE V1 BY V2 GIVING V3 REMAINDER RESTE.
(V3 = V1 / V2) et RESTE = V1 – (V2 * V3)

le tout en entier sans quoi il n’y a pas de reste

L’INSTRUCTION – COMPUTE

                        |expression-arithmétique|
COMPUTE  nom-item-1 =   |constant             |   
                        |nom-item               |

Les symboles arithmétiques valides sont :

+ pour l’addition
– pour la soustraction
* pour la multiplication
/ pour la division
** pour l’exposant

Un symbole arithmétique doit être précédé et suivi par au moins un espace.

Format :
COMPUTE identifier-1 ROUNDED = expression
ON SIZE ERROR ordre-impératif-1
NOT ON SIZE ERROR ordre-impératif-2
END-COMPUTE

L’expression : doit être composée de constantes et de variables numériques séparées par des opérateurs arithmétiques.

Les opérateurs sont : + – * / ** ( )

Avec + pour addition, – pour la soustraction, * pour la multiplication, le / pour la division et ** pour un exposant.

Exemple :
COMPUTE RESULTAT = A + (B – 3) * (G / 4) + ( E ** 2).

L’expression est analysée de la gauche vers la droite en tenant compte des priorités suivantes :
d’abord les exposants **, ensuite les * et / puis les + et -.
Il faut autant de ( gauches que de ) droites

8.3 LES MOUVEMENTS DE DONNEES – MOVE

Quels que soient les PICTURE et USAGE, il n’existe qu’un seul ordre de mouvement de données en mémoire centrale, l’ordre MOVE.

Format 1 :

     |nom-de-donnée-1|
MOVE | littéral               |   TO nom-de-donnée-2 nom-de-donnée-3

Exemple :
MOVE TVA TO TVAED. (TVAED = TVA)
MOVE "EXERCICE N° 1 " TO TITRE. ( TITRE = EXERCICE N° 1)
MOVE ZERO TO V1 V2 V3 V4 V5.
MOVE STRUCTURE1 TO STRUCTURE2.

Remarque : le fait d’avoir un seul verbe MOVE pour tous les types de données implique de veiller à ne pas mouvementer n’importe quel type de donnée sur n’importe quel type de zone de données.
Dans le cas des alphabétiques A : ne pourront être mouvementés que sur des zones élémentaires A ou X et sur des zones groupes ( les structures sont toujours considérées comme des PIC X).

Les alphanumériques X : ne pourront en principe être mouvementés que sur des zones PIC X ou sur des structures. Toutefois, le mouvement sur une zone numérique est autorisé, mais le programmeur doit être certain que la zone ne contient que des données numériques sans quoi il provoquera un arrêt du programme (MCH1202).

Les numériques, ne peuvent être mouvementés que vers des numériques ou des numériques d’édition. L’instruction MOVE convertit immédiatement n’importe quel usage en n’importe quel autre usage, pour passer d’un DISPLAY à un BINARY ou d’un PACKED-DECIMAL vers un DISPLAY aucune information ou instruction complémentaire n’est demandée au programmeur, la conversion est immédiate.

Principes de cadrage :

Les règles de cadrage sont toujours dictées par la zone réceptrice.

– Dans le cas des alphabétiques et alphanumériques :
La donnée est cadrée à gauche avec troncature à droite si la zone émettrice est trop grande ou complétée avec des caractères blancs à droite si la zone est plus courte.
MOVE " " TO L120 avec 01 L120 PIC X(120).
MOVE 120 blancs dans L120

– Dans le cas des numériques :
Les nombres sont alignés sur la partie décimale, si celle-ci est absente de la zone réceptrice elle est considérée comme étant à l’extrême droite.
Il a ensuite troncature éventuel ou complément de zéros à droite et à gauche si le nombre de chiffres désignés par la PIC de la zone réceptrice l’exige.
Si la zone réceptrice n’a pas de signe alors c’est la valeur absolue qui est transférée.
Si la zone émettrice n’est pas purement numérique le résultat est alors imprévisible.

Un INDEX est formellement interdit dans un MOVE.

Le contenu de la zone émettrice reste exactement le même après l’instruction MOVE.

MOVE et REDEFINES :

Dans le cas d’une redéfinition de zone
02 B……
02 C REDEFINES B…

Le fait d’exécuter un MOVE B TO C ou MOVE C TO B alors qu’il s’agit de la même zone mémoire entraîne un résultat inconnu!!

LE MOVE CORRESPONDING

Format :
MOVE CORR nom-de-groupe-1 TO nom-de-groupe-2

Le MOVE CORRESPONDING suit le même principe que l’option CORR des instructions arithmétiques. Les données de la zone groupe-1 sont mouvementées sur les zones de même nom de la zone groupe-2.

Toutefois, avec MOVE, il n’est pas exigé que les zones de même nom soient toutes deux élémentaires , mais qu’au moins l’une des deux zones le soit.

Mais, toute zone élémentaire décrite avec une clause OCCURS ou REDEFINES est ignorée.

Utilisation des constantes figuratives.

Les constantes figuratives SPACE(S) et ZERO(S) peuvent être utilisées dans un MOVE.

SPACE : pour mettre une zone PIC X ou PIC A à blanc, toute la zone est remplie de blancs, il peut également être question d’une structure.

Exemple :
MOVE SPACE TO VAR.
La variable VAR PIC XX ou PIC AA est remplie de blancs

MOVE SPACE TO STRUCTURE.
Ici toutes les variables contenues dans le groupe STRUCTURE sont mises à blancs. Il s’agit donc d’être très prudent, car si dans la description de structure nous avons une variable en PIC 9 son contenu sera un BLANC.

ZERO : permet de mettre n’importe quel variable PIC 9 usage…… à ZERO. Il en ira exactement de même avec un groupe et dans ce cas toutes les variables du groupe seront initialisées à 0.

Exemple :
MOVE ZERO TO VAR ——-> Dans ce cas VAR PIC 99.

MOVE ZERO TO STRUCTURE.
Et dans ce cas 01 STRUCTURE.
                                    02 A PIC 9999 BINARY.
                                    02 B PIC 9(5).

A et B sont mises à 0.

Remarque : l’usage d’un caractère de la chaîne est possible par l’option
MOVE CHAINE(i:j) TO A
Ou de l’hexadécimal : MOVE X"09" TO A

8.4 L’INSTRUCTION INITIALIZE

Format :

Identifier-1 est la variable ou la structure qui reçoit l’initialisation. Elle peut être tout ou partie de table mais ne peut jamais contenir les options DEPENDING ON POUR UN OCCURS. Les index sont interdits.

Identifier-2 ou litéral-1 représente le contenu d’initialisation, par défaut les numériques et les numériques édités sont initialisés à 0 et les alphabétiques les alphanumériques et les alphanumériques édités à blancs.

Si REPLACING est utilisé, identifier-2 ou litéral-1 doivent être compatible avec la catégorie indiquée (en respectant les règles du MOVE).

Lorsqu’une catégorie est indiquée après un REPACING, alors seulement les variables appartenant à identifier-1 et reprisent dans cette catégorie sont initialisées.

Exemple :
INITIALIZE VAR1.
INITIALIZE STRUCTURE1.
INITIALIZE VAR2 BY "*".

INITIALIZE STRUCTURE2 REPLACING NUMERIC BY VAR3.

8.5 L’INSTRUCTION INSPECT

Cette instruction permet de compter le nombre de fois qu’une configuration particulière de caractères apparaît dans une zone de données et/ou de remplacer ces caractères par d’autres. Cette instruction ne s’applique pas aux variables avec index même à un niveau 01.

Format 1 :

Nom-de-donnée-1 est la zone que l’on désire inspecter. Elle doit être en USAGE DISPLAY.

TALLYING signifie que l’on désire compter le nombre de fois qu’une configuration de caractères désignée par nom-de-donnée-3 ou litéral-3 apparaît dans nom-de-donnée-1 et que le résultat du comptage soit placé dans nom-de-donnée-2.

ALL signifie que toutes les occurrences doivent être comptées. Les caractères déjà utilisés dans un comptage ne sont jamais réutilisés.
Exemple: INSPECT VARA TALLYING COMPTEUR FOR ALL "NN".
Si VARA contient “NNNNN+NNN” COMPTEUR contiendra après l’opération de comptage 3, car le 5ème et le 9ème N ne peuvent pas être regroupés avec ceux déjà utilisés.

LEADING signifie que seules les premières apparitions contiguës doivent être comptées.
Exemple: INSPECT VARB TALLYING COMPTEUR FOR LEADING "N".
Si VARB contient “NN+NNN+NNN” COMPTEUR contiendra 2 puisqu’il y a 2 N en tête.
L’opération VARE contiendra “00000000”.

CHARACTERS compte le nombre de caractères contenu dans nom-de-donnée-1.
Exemple: INSPECT VARC TALLYING COMPTEUR FOR CHARACTERS.
Si VARC contient “N&N+MOI+123” COMPTEUR contiendra 11.
Pour rendre l’usage de cette instruction plus partiel nous disposons des options BEFORE et AFTER.

BEFORE INITIAL : (nom-de-donnée-4 ou litéral-4) signifie que le comptage doit s’arrêter dès que la première apparition du ou des caractères désignés est rencontrée.
Exemple:
INSPECT VARD TALLYING COMPTEUR FOR CHARACTERS
BEFORE INITIAL "+".

Si VARD contient “N&N+MOI++123” COMPTEUR contiendra 3.

AFTER INITIAL est l’inverse du BEFORE, on compte les caractères qui se trouvent après nom-dedonnée-4 ou litéral-4.
Exemple:
INSPECT VARDAF TALLYING COMPTEUR FOR CHARACTERS
AFTER INITIAL "+".

Si VARD contient “N&N+MOI++123” COMPTEUR contiendra 8.

REPLACING : indique que nous voulons remplacer certains caractères par d’autres.

CHARACTERS, tous les caractères de nom-de-donnée-1 doivent être remplacés par le caractère désigné par nom-de-donnée-5 ou litéral-5.
Exemple: INSPECT VARE REPLACING CHARACTERS BY "0".
Si VARE contient “N&N+MOI3” après l’opération VARE contiendra “00000000”.

ALL indique que toutes les occurrences désignées par nom-de-donnée-7 ou litéral-7 doivent être remplacées par nom-de-donnée-8 ou litéral-8. Il n’y a jamais réutilisation de caractères déjà utilisés dans une occurrence préalable.
Exemple: INSPECT VARF REPLACING ALL "N" BY "0".
Si VARF contient “NN+NT23N” après l’opération VARF contiendra “00+0T230”.

LEADING indique que le remplacement s’arrêtera dés qu’un autre caractère que nom-de-donnée-7 est rencontré.

FIRST indique que le remplacement ne doit être effectué que pour la première apparition de nom-dedonnée-7.
Exemple: INSPECT VARG REPLACING FIRST "N" BY "0".
Si VARG contient “NN+NT23N” après l’opération VARG contiendra “0N+NT23N”.

Les options BEFORE et AFTER sont utilisées de la même manière que dans TALLYING.

Les clauses TALLYING et REPLACING peuvent être utilisées en même temps.
Exemple:
INSPECT VARTOT TALLYING COMPTE FOR CHARACTERS
BEFORE “+” REPLACING ALL “N” BY ““.
Si VARTOT contient “NN+NT23N” après l’opération VARTOT contiendra “+T23*” et COMPTE contiendra 2.

!!!!Le programmeur doit initialiser nom-de-donnée-2 à zéro car TALLYING additionne sans remettre à zéro.!!!!

Format 2:

Exemple:
INSPECT VAR11 CONVERTING "ABCD" TO "WXYZ"
AFTER QUOTE BEFORE "=".

Si VAR11 contient (AC”AEBDFBCD=AB”D) alors le résultat est (AC”WEXZFXYZ=AB”D)

INSPECT CHAINE CONVERTING MIN TO MAX
Avec MIN pic x(26) value ‘abc…yz’.
Et Max pic x(26) value ‘A Z’.

Remarque :
Inspect ZONE TALLYING CPT1 FOR ALL ‘A’
                                                         CPT2 FOR ALL ‘E’
                                                         CPT3 FOR ALL ‘I

8.6 L’INSTRUCTION STRING

Les zones de données émettrices et réceptrices doivent être alphanumériques et les transferts de données suivent les règles correspondantes. Si la zone réceptrice est plus grande il n’y a pas remplissage par des blancs à droite. De même nom-de-donnée-résultat n’est jamais réinitialisée à blanc, c’est le travail du programmeur.

DELIMITED BY permet de spécifier une limite de transfert de données, soit en fonction de la taille “SIZE”, soit en fonction du ou des caractères de nom-de-donée-3 ou litéral-3. Ces caractères là ne sont pas transmis.

POINTER permet de préciser la position de gauche du début du transfert dans la zone résultat. La variable nom-de-pointeur est un numérique. Normalement cette valeur est incrémentée de 1 par caractère transféré.
OVERFLOW en option avec POINTER indique l’ordre impératif à exécuter.

Exemple :

STRING "CECI EST LE TITRE " GROUPE BLANC "1999"
DELIMITED BY SIZE INTO L80.

STRING INFO DELIMITED BY SIZE INTO L80
WITH POINTER PT ON OVERFLOW
PERFORM PAR-ERREUR.

String A delimited by size B delimited by space C delimited by ‘*’ into …

8.7 L’INSTRUCTION UNSTRING

Le but de cette instruction est d’éclater une variable DISPLAY en plusieurs morceaux. La règle d’éclatement est donnée par DELIMITED BY.

Format :

Les mêmes règles que pour le STRING sont d’application. ALL est destiné à éliminer les redondances d’un caractère délimiteur. Par exemple ALL “AB” signifie que AB ou même ABABAB sont délimiteurs.

NOM-DE-POINTEUR , numérique DISPLAY, que le programmeur doit initialiser à 0 permet de compter le nombre de caractères examinés dans la zone nom-de-donnée-1.

NOM-DE-COMPTEUR, numérique DISPLAY, compte le nombre de zones réceptrices créées.

OVERFLOW, arrête le déroulement de l’instruction si le contenu du pointeur est négatif ou > à la taille de la zone nom-de-donnée-1, ou lorsque la zone nom-de-donnée-1 n’est pas entièrement examinée mais que l’instruction UNSTRING ne dispose plus de zones réceptrices i,j,…

Si un OVERFLOW est déclenché sans que l’option ne soit spécifiée, l’instruction UNSTRING est arrêtée et le programme passe à l’instruction suivante.

Les zones nom-de-donnée-i etc. sont les zones réceptrices.

DELIMITER IN spécifie la variable dans laquelle on désire transférer le délimiteur qui a été utilisé pour cet éclatement.

COUNT IN indique le nombre de caractères transférés par cet éclatement.

Exemple :
01 ZONE PIC X(12).
01 NOM PIC X(5).
01 AN PIC XXXX.
UNSTRING ZONE DELIMITED BY SPACE INTO NOM AN.
Si ZONE = "ANNEE 1999 "

alors le résultat est NOM = “ANNEE” et AN = “1999”.

UNSTRING A delimited by ‘.’ or ‘/’ ….

8.8 LES INSTRUCTIONS CONDITIONNELLES

Il existe différents types de conditions en COBOL. Une condition peut-être :
– de relation
– de classe
– de signe

Une condition de relation a la structure suivante :

IF MONTANT IS EQUAL TO 25.00 ….
IF TOTAL > MONTANT ….
IF SALAIRE-BRUT NOT < LIMITE ….

Une condition de classe a la structure suivante :

IF CODE-PROV IS NOT ALPHABETIC ….
IF MONTANT IS NUMERIC ….

Une condition de signe a la structure suivante :

L ’item doit être numérique (PIC 9)

IF TOTAL-CREDITS IS NEGATIVE ….
IF MONTANT IS POSITIVE ….
IF MONTANT-EN-CAISSE - DEBOURSES IS NOT ZERO ….

Les conditions peuvent être combinées pour former des conditions complexes avec AND et OR .

IF MOYENNE = 0 AND NBR-ETUDIANT NOT EQUAL TO ZERO ….
IF A = B OR C > D ….

La structure de sélection est traduite en COBOL par l ’énoncé IF :

IF condition
THEN Instruction impérative ….
[ELSE Instruction impérative ….]
END-IF

Exemple :

IF HRES-TRAV > 40 THEN
    COMPUTE HRES-SUPP = HRES-TRAV - 40
    COMPUTE PAYE-SUPP = HRES-SUPP * TAUX-HOR
    MOVE 40 TO HRES-REG
ELSE
    MOVE ZERO TO PAYE-SUPP
    MOVE HRES-TRAV TO HRES-REG.
    COMPUTE PAYE-REG = HRES-REG * TAUX-HOR.
    COMPUTE PAYE-TOTALE = PAYE-REG + PAYE-SUPP
END-IF.

Il est possible de donner un nom à une condition et d ’utiliser celui-ci à sa place.
Un nom de condition est défini à l ’aide du niveau 88.

88 nom-condition VALUE const-1 [{THRU} const-2 ….]

La description de niveau 88 doit suivre immédiatement celle de l ’item élémentaire auquel on fait référence. La constante doit être du même type.

05 note PIC X.
88 echec VALUE ‘E’.

Quand le nom de condition est utilisé, la valeur de l ’item et la valeur indiquée dans la description de niveau 88 sont comparées.

IF echec THEN
    PERFORM traiter-echec

ELSE PERFORM traiter-reussite
END-IF.

EVALUATE

Il est utilisé pour représenter une structure de sélection de type ‘CASE’ :

EVALUATE CHOIX
    WHEN ‘A’ PERFORM TRAITER-AJOUT
    WHEN ‘M’ PERFORM TRAITER-MODIFICATION
    WHEN ‘S’ PERFORM TRAITER-SUPPRESSION
    WHEN OTHER PERFORM TRAITER-ERREUR
END-EVALUATE.