Cobol

  Accueil | Contact | Livre d'or

 

.: Rubrique 1 :.

 

Astuces XP

Programmation

 

.: Rubrique 2 :.

 

Avatar

Gif Animé

Smiley

Fond d'écran

Humour

 

.: Rubrique 3 :.

 

Freeware

En vrac

 

.: Partenaires :.

 

Liens

 

 

 

 

 

House of COBOL

Guide de l'utilisateur du
Common Business Oriented Language

 

Sommaire

Introduction

Les mots réservés

Format du fichier source

Les divisions

Les sections

Les paragraphes

Les lignes de commentaire

Le point à la fin d’une ligne

Premier exemple de programme Cobol simple

Deuxième exemple de programme Cobol

Les données

La déclaration des variables alphabétiques et alphanumériques

La déclaration des variables numériques

La déclaration des structures, des tables, et des drapeaux

Le point d’entrée d’un programme

Le point de sortie d’un programme

La saisie des données

L’affichage des données

L’instruction MOVE

Autres instructions de manipulation de données alphanumériques

Opérations arithmétiques

Formatage des données

Les comparaisons

L'instruction IF

L’instruction EVALUATE

Le déroulement d'un programme

La gestion des fichiers

La date et l'heure

Le tri  

Divers


Introduction

Le Cobol est l’un des plus vieux langages informatique. Il est apparu peu de temps après l’arrivée des premiers gros ordinateurs, c’est-à-dire vers la fin des années 50.

Le Cobol a été créé quelques années après le Fortran. Tous les deux sont des langages qui ont été qualifiés d’"universels", parce qu’ils peuvent tourner sur des machines différentes, ce qui était nouveau pour l’époque. Le Fortran est plutôt spécialisé dans le domaine du calcul, alors que le Cobol est plutôt apprécié pour la gestion des fichiers. Ces deux langages ont eu énormément de succès dans les grandes entreprises.

De nos jours, ces deux langages sont démodés. Les évolutions du Cobol, définies par un comité de standardisation international, n’ont pas été aussi rapides ni aussi radicales que les évolutions de l’informatique. Par exemple, le Cobol standard ne gère pas les bases de données, ni les interfaces graphiques.

Cependant, le Cobol continue à être utilisé dans quelques entreprises, et surtout il reste énormément de programme Cobol à maintenir.


Les mots réservés

Le langage Cobol, comme tout autre langage informatique, est basé sur l’utilisation de mots réservés. Ces mots ont une signification très précise. Ils ne peuvent pas être utilisés n’importe comment, n’importe où, et ne peuvent pas être accompagnés de n’importe quels paramètres.


Format du fichier source

Les lignes d’un programme Cobol doivent être écrites en format fixe ou en format libre.

Format fixe:

Autrefois, un fichier source Cobol se présentait sous la forme d’un paquet de cartes perforées. Sur chaque carte était dessinée une grille de 80 x 8 cases trouées ou pleines. Comme il faut huit cases par caractère, chaque carte perforée représentait donc un message de 80 caractères. De cet héritage provient la contrainte imposant qu’une ligne de code Cobol ne dépasse pas 80 caractères.

Les six premières colonnes sont réservées. A l’époque des cartes perforées ces six colonnes servaient pour contenir un numéro de référence de la carte. De nos jours, ces six colonnes sont laissées à blanc.

La septième colonne est utilisée pour certains caractères spéciaux. Par exemple: une étoile en septième colonne indique que la ligne est un commentaire; un tiret indique que la ligne continue la ligne précédente.

La huitième colonne est baptisée colonne A. Elle contient toutes les étiquettes. Une étiquette est un point de repère dans un programme. Elle indique par exemple le début d’un paragraphe.

La douzième colonne est baptisée colonne B. C’est à partir de la colonne B que doivent être écrites toutes les instructions ordinaires.

Les concepteurs du Cobol préconisent d’indenter les lignes de quatre caractères en quatre caractères (rappel: une indentation est un décalage au début des lignes qui font parties d’un même bloc, afin que ceux-ci soient bien mis en évidence; par exemple cela permet de voir d’un coup d’oeil quelles instructions seront exécutée si une condition est vraie).

Format libre:

Depuis une vingtaine d’années, les compilateurs Cobol acceptent aussi le format libre, qui permet d’écrire ce que l’on veut, à peu près où l’on le souhaite.

Beaucoup de programmeurs utilisent encore le format fixe, par habitude, et parce que cela permet de bien présenter les programmes.


Les divisions

Un programme Cobol est divisé en quatre "DIVISIONS" :

  • IDENTIFICATION DIVISION
  • ENVIRONMENT DIVISION
  • DATA DIVISION
  • PROCEDURE DIVISION

En théorie seule l’IDENTIFICATION DIVISION est obligatoire, mais dans la très grande majorité des cas, un programme Cobol a besoin des quatre divisions.

La division nommée IDENTIFICATION donne des informations sur le programme. Elle renseigne sur le nom du programme, son auteur, sa date de création, la version du compilateur à utiliser. Habituellement, le programmeur y met un pavé de lignes de commentaire expliquant ce que fait le programme.

La division nommée ENVIRONMENT donne des informations relatives à l’environnement matériel. Par exemple, c’est ici que sont décrites les principales caractéristiques des fichiers.

La division nommée DATA contient la déclaration de toutes les données utilisées par le programme.

La division nommée PROCEDURE contient les traitements.

Une division s’étend jusqu’au début d'une autre division ou jusqu’à la fin du fichier.

Les quatre divisions doivent obligatoirement apparaître dans l’ordre indiqué ci-dessus.


Les sections

Chaque division peut contenir zéro, une, ou plusieurs sections.

Chaque section commence par son nom qui doit être écrit en colonne A (c-à-d à partir du 8ème caractère), suivi du mot réservé SECTION et d’un point. Par exemple:

  • CONFIGURATION SECTION.
  • WORKING-STORAGE SECTION.
  • TRAITEMENT_PRINCIPAL SECTION.
  • CALCUL_DU_CHMILBLIK SECTION.

Les trois premières divisions (IDENTIFICATION, ENVIRONMENT, et DATA) contiennent des sections dont les noms et le contenu sont normalisées. C’est le cas, par exemple, de la CONFIGURATION SECTION dans l’ENVIRONMENT DIVISION, et de la WORKING-STORAGE SECTION dans la DATA DIVISION. Par contre les noms et le contenu des sections de la PROCEDURE DIVISION sont totalement libres.

Une section s’étend jusqu’au début d'une autre section, ou jusqu’au début d’une division, ou encore jusqu’à la fin du fichier.


Les paragraphes

Chaque section doit contenir un ou plusieurs paragraphes. Si une division ne possède pas de section, elle doit néanmoins contenir au moins un paragraphe.

Un paragraphe est un ensemble de lignes.

Chaque paragraphe commence par son nom, qui doit être écrit en colonne A, suivi par un point. Par exemple:

  • PROGRAM-ID.
  • AUTHOR.
  • SPECIAL-NAMES.
  • FILE-CONTROL.
  • LIT-FICHIER-AAA.
  • MET_A_JOUR_BBB.
  • CALCUL-ECART-DATES.

Certains paragraphes sont normalisés, c’est notamment le cas de ceux qui sont inclus dans les trois premières divisions. Dans la PROCEDURE DIVISION, les noms de paragraphes et leur contenu sont libres.

Chaque paragraphe doit contenir au moins une ligne. Il est parfois intéressant de disposer d’un paragraphe vide, par exemple dans le cas d’une instruction "PERFORM paragraphe01 THRU paragraphe99" (voir plus loin les explications sur le mot réservé PERFORM). Pour éviter de ne rien mettre dans un tel paragraphe, il faut y placer l’instruction EXIT, qui ne fait absolument rien (je profite de l’occasion pour signaler tout de suite que cette instruction EXIT constitue un piège dont presque tout programmeur a été la victime un jour, car contrairement à ce que son nom pourrait faire croire, cette instruction EXIT ne provoque pas la sortie d’une boucle, ou d’un programme, elle n’est là que pour faire du remplissage).

Un paragraphe se termine par le début d'un autre paragraphe, une nouvelle section, une nouvelle division, ou la fin du fichier.


Les lignes de commentaire

Il est possible d’insérer des lignes de commentaire n’importe où dans un programme Cobol.

Une ligne de commentaire est une ligne qui commence par une étoile placée en colonne 7.

Le langage Cobol ne donne aucun moyen pour mettre un commentaire à la fin d’une ligne (sauf si le fichier est compilé avec certains compilateurs (assez rares)).


Le point à la fin d'une ligne

Dans les trois premières divisions, il faut toujours mettre un point pour indiquer la fin d’une ligne (sauf quelques exceptions).

Dans la PROCEDURE DIVISION, avant 1974, la norme du langage Cobol exigeait que chaque instruction se terminât par un point. Cette règle comportait une exception pour les lignes de code suivant l’instruction IF, car ce point servait de délimiteur de fin au bloc d’instructions qui suit le IF. Donc, il ne fallait pas mettre de point à la fin des instructions se trouvant à l’intérieur d’un bloc sauf si cette instruction était la dernière du bloc. Lorsqu’il y avait plusieurs conditions IF imbriquées, le point final indiquait la fin de tous les IF précédents. Cela n’était pas très souple et constituait une source d’erreurs.

Depuis 1974, sont apparus les scopes terminators, c’est-à-dire les mots réservés END-IF, END-READ, END-PERFORM, etc, qui indiquent sans ambiguïté l’endroit où se termine un bloc d’instructions pour un IF, un READ, un PERFORM, etc.

La norme de 1974, adoptée par 99,9% des compilateurs actuels, reste compatible avec l’ancienne norme. Mais en plus, elle ne rend plus obligatoire les points dans la PROCEDURE DIVISION, sauf à la fin d’une étiquette, par exemple un nom de paragraphe ou de section, sauf avant une étiquette, afin que l’étiquette ne soit pas considérée comme étant l’un des paramètres de l’instruction précédente, et sauf à la fin du fichier. Personnellement, je ne mets des points qu’aux endroits obligatoires, et j’utilise les scope terminators.


Premier exemple de programme Cobol simple

Repérer les divisions, sections, et paragraphes.

Repérer les lignes de commentaires.

Observer où se trouvent les points.

Essayer de comprendre le programme.

IDENTIFICATION DIVISION.
*-----------------------
PROGRAM-ID. TEST1.

DATA DIVISION.
*-------------
WORKING-STORAGE SECTION.
77 DATA1 PIC X(6).

PROCEDURE DIVISION.
*------------------
S1 SECTION.
MY_FIRST_PARAGR.

* Initialize data
   MOVE "Hello" TO DATA1

* Process data
   PERFORM DISPLAY_DATA1

* The end
   STOP RUN
   .

DISPLAY_DATA1.

* Display "hello word."
   DISPLAY DATA1 ", world."
   .

Ce programme comporte:

  • 3 divisions : IDENTIFICATION, DATA, et PROCEDURE,
  • 2 sections : WORKING-STORAGE et S1,
  • 3 paragraphes :PROGRAM-ID, MY_FIRST_PARAGR, et DISPLAY_DATA1.
  • 9 lignes de commentaires.


Deuxième exemple de programme Cobol

IDENTIFICATION DIVISION.
*-----------------------
PROGRAM-ID. TEST1.
* This program is a simple demo program
* I won’t describe here what it does,
* I leave it up to you to guess it.

DATA DIVISION.
*-------------
WORKING-STORAGE SECTION.
77 HELLO_NAME PIC X(20) VALUE "Oliver".
77 TARTS_PER_MINUTE PIC 999V99 VALUE 7.51.
77 MINUTES_NB PIC 9(5) VALUE 4.
77 TARTS_NB PIC 9(5)V9(2).
01 DID_YOU_KNOW.
   05 TEXT_1 PIC X(33)
    VALUE "Did you notice that you received ".
   05 TARTS_NBZ PIC ZZZZ9.9(2).
   05 TEXT_2 PIC X(15)
    VALUE " tarts on your ".
   05 PART_OF_THE_BODY PIC X(20).
   05 TEXT_3 PIC X(1) VALUE "?".

*************************************
PROCEDURE DIVISION.
*------------------
MY_MAIN_SECTION SECTION.
MAIN.

* Say hello
   PERFORM HELLO_YOU

* Change the name
   MOVE "Stanley" TO HELLO_NAME

* Say hello again
   PERFORM HELLO_YOU

* Do many times
   PERFORM VARYING MINUTES_NB FROM 1 BY 2
     UNTIL MINUTES_NB > 7
     OR PART_OF_THE_BODY = "Q"

* Get data
   DISPLAY
     "Type Q to quit or enter a part of the body"
   ACCEPT PART_OF_THE_BODY

   IF PART_OF_THE_BODY NOT = "Q"

     COMPUTE TARTS_NB = TARTS_PER_MINUTE
     * MINUTES_NB + 2

* Format the number to eliminate zeroes
* on the left side
     MOVE TARTS_NB TO TARTS_NBZ

* An important message
     DISPLAY DID_YOU_KNOW

   END-IF

   END-PERFORM

* The end
   STOP RUN
   .
*************************************
* This subroutine displays a message
* IN : HELLO_NAME
* OUT: Message on the screen
*************************************
HELLO_YOU.
*---------
   DISPLAY "Hello ", HELLO_NAME
   .

Ces exemples vous montrent, entre autres choses, que le langage Cobol est très verbeux, ce qui rend les programmes facilement lisibles.

A l’origine, les programmes Cobol devaient être écrits en majuscules. Les compilateurs actuels acceptent les lettres minuscules, mais ils ne sont pas case sensitive, c’est-à-dire qu’ils ne font pas de différence entre les mots écrits en majuscules et ceux écrits en minuscules (certains compilateurs ont une option pour prendre en compte cette différence, mais je n’ai jamais vu personne l’utiliser). L’usage est resté d’écrire les programme Cobol tout en majuscules, sauf pour les commentaires et pour les chaînes littérales (les textes entre guillemets)

.


Les données

Le Cobol permet de traiter des nombres, des chaînes de caractères, des tables, des groupes de données (structures), des index de tableaux, des drapeaux, etc.

Toutes les données, à l'exception des constantes, doivent être déclarées dans la DATA DIVISION.

La déclaration d’une donnée se fait en écrivant une ligne, dans la WORKING-STORAGE SECTION de la DATA DIVISION, qui indique :

  • un niveau hiérarchique,
  • un identifiant,
  • une "picture",
  • une valeur initiale,
  • et d'autres attributs.

Le numéro d'ordre hiérarchique est :

  • un nombre compris entre 1 et 50, pour un élément d'une structure
  • 66 pour une structure renommée et réorganisé (rarement utilisé)
  • 77 pour une donnée indépendante
  • 88 pour une condition-nommée (un drapeau)

L'identifiant d'une donnée (son nom) est une chaîne de caractères d'une longueur maximale de 30 caractères. Le premier caractère doit être alphabétique; le dernier caractère doit être alphabétique ou numérique; les caractères du milieu doivent alphabétiques, numériques, ou être un tiret de soulignement, ou encore un tiret "moins" (hyphen). L'emploi du tiret "moins" peut causer des problèmes, car il risque d’être interprété comme étant l’opérateur de soustraction.

Il est interdit de choisir un mot réservé comme identifiant d’une donnée, sauf le mot FILLER, qui est utilisé quand l’identifiant n’a aucune importance (voir exemple ci-dessous).

La "picture" renseigne sur le type de donnée, sa longueur, et son format d’affichage.

La valeur initiale n’est pas obligatoire. Le compilateur l’inscrit directement dans le fichier exécutable. Personnellement, je préfère programmer l'initialisation des variables dans la PROCEDURE DIVISION.

Exemple :

01 MY_DATA.
   05 FILLER PIC XXXXXXX VALUE "My name is: ".
   05 MY_NAME PIC XXXXXXXXX VALUE "Mona Lisa".
   05 FILLER PIC XXXXX VALUE "and my age is: ".
   05 MY_AGE PIC 999 VALUE 403.
77 CURRENT_YEAR PIC 9999 VALUE 1998.


La déclaration des variables alphabétiques et alphanumériques

Une variable alphabétique est définie avec une picture comportant des caractères "A".

Une variable alphanumérique est définie avec une picture comportant des caractères "X" (dans la pratique les variables alphabétiques sont très rares, et les variable alphanumériques très fréquentes).

L'attribut JUSTIFIED RIGHT, ou en abrégé JUST, indique que les données qui seront copiées vers cette zone, devront être cadrées à droite, et non pas à gauche comme c'est le cas par défaut pour les données alphabétique ou alphanumériques.

Le programmeur Cobol dispose de "constantes figuratives" :

  • LOW-VALUE (ou LOW-VALUES) pour des zéros binaires
  • HIGH-VALUE (ou HIGH-VALUES) pour des octets ayant la valeur 255
  • SPACE (ou SPACES)
  • ZERO (ou ZEROES, ou ZEROS) pour des zéros Ascii
  • QUOTE (QUOTES) pour des apostrophes

La valeur initiale peut être spécifiée par "ALL motif", où le motif est une chaîne de caractères entre guillemets. Le motif est répété jusqu'à ce que la zone soit remplie.

Exemple :

77 DATA1 PIC XXXXX.
77 DATA2 PIC X(5) JUST.
77 DATA3 PIC X(10) VALUE "ABCDEFGHIJ".
77 DATA4 PIC X(10) VALUE SPACE.
77 DATA5 PIC X(50000) VALUE ALL "abc".

"PIC XXXXX" est équivalent à "PIC X(5)".


La déclaration des variables numériques

Une variable numérique est définie avec une "picture" qui est une combinaison des caractères "9", "S", et "V" :

  • "S" indique qu'un nombre est signé,
  • "9" représente un chiffre (0 à 9),
  • "V" marque la position d'une virgule virtuelle.

Exemple :

* NUM1 is a variable for a number between 0 and 9
77 NUM1 PIC 9.

* NUM2 and NUM3 are variables
* for numbers between 0 and 999
77 NUM2 PIC 999.
77 NUM3 PIC 9(3).

* NUM4 and NUM5 are variables
* for numbers between -9999.99 and +9999.99
77 NUM4 PIC S99999V99.
77 NUM5 PIC S9(4)V9(2).

La picture "9(3)" est équivalente à "999".

Les nombres peuvent avoir 18 chiffres au plus.

Le programmeur Cobol dispose de "constantes figuratives" :

  • ZERO (ou ZEROES, ou ZEROS),
  • LOW-VALUE (ou LOW-VALUES), la plus petite valeur possible (égale à ZERO si le nombre n'est pas signé).
  • HIGH-VALUE (ou HIGH-VALUES), la plus grande valeur possible (qui est 999... et non pas un code ASCII 255 comme pour les zones alphanumérique)

Entre les mots réservés PIC et VALUE, le mot réservé optionnel USAGE indique au compilateur quel format interne prendra une donnée :

  • "USAGE IS COMP" ou "USAGE IS BINARY", pour du binaire

par exemple, le nombre 1234 est codé sur deux octets dont les valeurs en hexadécimal sont 4 et D2,"USAGE IS COMP-3", pour du "packed BCD"

par exemple, le nombre 1234 est codé sur deux octets dont les valeurs en hexadécimal sont 12 et 34,"USAGE IS DISPLAY" pour une chaîne de caractères numériques ASCII.

par exemple, le nombre 1234 est codé sur quatre octets dont les valeurs en hexadécimal sont 31, 32, 33, et 34.

Par défaut, c’est-à-dire, si le mot réservé USAGE n’a pas été spécifié, le format est celui de USAGE IS DISPLAY. Personnellement, j’utilise le format DISPLAY pour les nombres que je dois stocker dans les fichiers et BINARY pour les autres nombres.

La taille de la mémoire réservée pour un nombre "USAGE IS BINARY" est :

  • 2 octets pour un nombre de 1 à 4 chiffres
  • 4 octets pour un nombre de 5 à 9 chiffres
  • 8 octets pour un nombre de 10 à 18 chiffres

La taille de la mémoire réservée pour un nombre "USAGE IS COMP-3" est égale au nombre des chiffres plus un si le nombre est signé, le tout divisé par deux et arrondi au chiffre supérieur. Par exemple un nombre de trois chiffres occupe deux octets, un nombre signé de dix chiffres occupe 6 octets.

La taille de la mémoire réservée pour un nombre "USAGE IS DISPLAY" est égale au nombre des chiffres plus un octet si le nombre est signé.

Dans tous les cas, la virgule décimale est virtuelle.


La déclaration des structures, des tables, et des drapeaux

Les structures sont définies grâces aux numéros d'ordre hiérarchiques.

Exemple :

01 DATE_MM_DD_YYYY.
   05 MM PIC 9(2).
   05 FILLER PIC X VALUE '/'.
   05 DD PIC 9(2).
   05 FILLER PIC X VALUE '/'.
   05 YYYY.
    10 CENTURY PIC 9(2).
    10 YY PIC 9(2).

01 DATE1_YYYYMMDD.
   23 YYYY PIC 9(4).
   23 DD PIC 9(2).
   23 MM PIC 9(2).

01 DATE2_YYYYMMDD PIC 9(8).

Il est obligatoire de commencer au niveau 1 (habituellement on écrit 01 au lieu de 1). Le niveau immédiatement inférieur peut avoir le numéro 2 ou n’importe quel autre numéro inférieur à 50. Habituellement, on choisit la séquence suivante: 01, 05, 10, 15, etc.

Cobol autorise la déclaration d’une variable de niveau 1, sans niveau inférieur, mais ce n’est pas recommandé. Dans ce cas il vaut mieux utiliser un niveau 77.

Les tables sont déclarées avec OCCURS x TIMES. Le mot réservé TIMES est facultatif.

Cobol ne permet pas la déclaration, sur une seule ligne, d’un tableau à plusieurs dimensions, mais il sait gérer les sous-tables, ce qui revient au même.

Exemple :

01 TABLES.
   02 T1 OCCURS 4 PIC X(4).

   02 T2 OCCURS 2.
    05 T2_A PIC X(4).
    05 T2_B PIC 9(2).
    05 T2_C OCCURS 3 TIMES.
    10 T2_CA PIC X(4).
    10 T2_CB OCCURS 4 PIC X(3).
    10 T2_CC PIC X(3) OCCURS 2.

Le mot réservé REDEFINES est utilisé quand le programmeur veut disposer de plusieurs noms pour désigner une zone de mémoire. Le mot réservé RENAMES est utilisé à la fois pour renommer une zone, et pour la restructurer.

Exemple :

01 NAME.
   10 FIRST-NAME PIC X(20).
   10 MIDDLE-INITIAL PIC X.
   10 LAST-NAME PIC X(20).
01 FULL-NAME REDEFINES NAME PIC X(41).
01 REDEF-NAME REDEFINES NAME.
   10 NAME-PART1 PIC X(21).
   10 NAME-PART2 PIC X(20).

01 TABLE-DAYS
   02 DAYS PIC X(21) VALUE "MonTueWenThiFriSatSun".
   02 T3 REDEFINES DAYS PIC X(3) OCCURS 7.

01 A.
   05 A1.
    10 A11 PIC X(5).
    10 A12 PIC X(5).
    10 A13 PIC X(5).
   05 A2.
    10 A21 PIC X(5).
    10 A22 PIC X(5).
   
10 A23 PIC X(5).
   66 BB RENAMES A12 THRU A22.

Le cobol gère des conditions nommées. Il s’agit de drapeaux. (voir le chapitre sur l’instruction IF pour comprendre comment s’en servir)

Exemple:

77 AGE PIC 9(3)V9.
   88 YOUNG VALUE 0 THRU 17.9.
   88 ADULT VALUE 18 THRU 59.9.
   88 OLD VALUE 60 THRU 150.
   88 MATHUSALEM VALUE 969.

77 FLAG_OK PIC X(10).
   88 OK VALUE "OK", "GOOD",
     "001" THRU "009".
   88 KO VALUE "KO", "900" THROUGH "999",
     "FAILURE", "ERROR".

77 FLAG_EOF PIC X.
   88 NOT_THE_END_OF_THE_FILE VALUE "N".
   88 EOF VALUE "E".

Les mots réservés THRU et THROUGH sont équivalents.


Le point d'entrée d'un programme

Quand un programme Cobol est lancé, c’est toujours la première ligne de code de la PROCEDURE DIVISION qui est exécuté en premier. Certains compilateurs autorisent un autre point de départ.


Le point de sortie d'un programme

Un programme Cobol se termine et rend la main au système d’exploitation lorsque l’instruction STOP RUN est rencontrée.

Un programme Cobol se termine et rend la main au programme qui l’a appelé lorsque l’instruction EXIT PROGRAM ou l’instruction GOBACK est rencontrée. EXIT PROGRAM et GOBACK sont des synonymes, ils ont exactement la même fonction. Ils ont le même effet que STOP RUN, lorsque le programme Cobol a été appelé à partir du système d’exploitation. Mais lorsque le programme Cobol a été appelé par un autre programme Cobol, la main est rendu à ce programme, et non pas directement au système d’exploitation, comme cela aurait été le cas avec STOP RUN.

L’instruction END PROGRAM est une pseudo-instruction destinée au compilateur, pour lui indiquer de ne pas compiler les lignes de code qui sont en dessous de END PROGRAM. Il est très rare d’avoir besoin de cette instruction, mais il faut la connaître pour ne pas la confondre avec EXIT PROGRAM.

En résumé, STOP RUN provoque un arrêt brutal; EXIT PROGRAM ou GOBACK provoque la sortie d’un module; et END PROGRAM est un piège pour débutant.


La saisie des données

L’instruction ACCEPT demande à l’utilisateur d’entrer une donnée sur le port d’entrée standard. Autrefois le port d’entrée standard était un lecteur de cartes perforées. Puis, ce fut un clavier. La plupart des systèmes d’exploitation permettent de redéfinir le port d’entrée standard, par exemple, afin que les données proviennent d’un fichier plutôt que du clavier. Le Cobol offre des instructions bien plus commodes pour lire les données provenant des fichiers, aussi l’instruction ACCEPT n’est utilisé dans la pratique que pour des saisies au clavier.

Derrière le mot réservé ACCEPT, il faut indiquer le nom de la variable dans laquelle sera stockée la donnée saisie par l’utilisateur. Par exemple: ACCEPT NOM1, ou ACCEPT NUMERO, ou ACCEPT OUI_OU_NON.

L’instruction ACCEPT est assez limitée. Elle n’accepte que des caractères ASCII. Par exemple, elle ne reconnaît pas la pression sur des touches spéciales telles que les flèches, la touche Echap., les touches Fxx, les touches Ctrl, Alt, etc. La saisie se termine avec le carriage return (pression sur la touche "Entrée" ou "retour"), qui n’est pas inclus dans la variable de destination. Sur un système multi-utilisateurs, l’instruction ACCEPT ne concerne que le poste à partir duquel le programme a été lancé, qui est généralement la "console système", à laquelle les utilisateurs ordinaires n’ont pas accès. Dans la pratique, du fait de ces limitations, l’instruction ACCEPT est surtout utile aux étudiants en informatique et aux programmeurs qui sont en phase de test de leur programme.

Le Cobol n’offre pas d’autre fonction de saisie de données au clavier. Pour remplacer l’instruction ACCEPT, il faut faire appel à des routines externes spécialisées, ne faisant pas partie des bibliothèques standard du Cobol. Par exemple, sur un gros systèmes IBM, on utilisera les routines de CICS; sur VAX, on se servira des routines de FMS; sur un PC sous DOS, on se servira des fonctions d’interruption du DOS; sur un PC sous Windows, on appellera les API de Windows, etc.


L'affichage des données

L’instruction DISPLAY affiche des données sur le port de sortie standard. Autrefois le port de sortie standard était une imprimante. Puis ce fut un écran. Derrière le mot réservé ACCEPT, il faut indiquer le nom de la ou des variables ou littéraux à afficher. Par exemple: DISPLAY "Je m’appelle ", MON_NOM, " et j’ai ", MON_AGE, " ans.".

Les données doivent avoir été préalablement formatées. Par exemple, on traitera les nombres afin de supprimer les zéros à gauche, d’y insérer un séparateur de décimales, de les arrondir à une précision voulue, de cadrer à droite ou à gauche les chaînes de caractères, etc.

L’instruction DISPLAY est assez limitée. L’affichage se fait sur la position courante de l’écran. Il n’y a pas d’instruction standard en Cobol pour gérer cette position courante, en dehors du rudimentaire paramètre WITH ADVANCING ou WITH NO ADVANCING. Il n’est pas possible de gérer la couleur des caractères, leur taille, leur police, etc. Sur un système multi-utilisateurs, l’instruction DISPLAY ne concerne que le poste à partir duquel le programme a été lancé, qui est généralement la "console système", à laquelle les utilisateurs ordinaires n’ont pas accès. Dans la pratique, du fait de ces limitations, l’instruction DISPLAY est surtout utile aux étudiants en informatique et aux programmeurs qui sont en phase de test de leur programme.

Le Cobol n’offre pas d’autre fonction d’affichage de données sur l’écran. Pour remplacer l’instruction DISPLAY, il faut faire appel à des routines externes spécialisées, ne faisant pas partie des bibliothèques standard du Cobol. Par exemple, sur un gros systèmes IBM, on utilisera les routines de CICS; sur VAX, on se servira des routines de FMS; sur un PC sous DOS, on se servira des fonctions d’interruption du DOS; sur un PC sous Windows, on appellera les API de Windows, etc.


L'instruction MOVE

MOVE est l’instruction la plus utilisée en Cobol. Elle copie une donnée vers une ou plusieurs variables. Sa syntaxe est: MOVE donnée_source TO zone_destination [...].

Exemple:

* Copy a number
   MOVE 20 TO CUSTOMER_AGE

* Copy a constant
   MOVE SPACES TO CUSTOMER_NAME

* Copy a string
   MOVE "DIANA" TO CUSTOMER_NAME

* Copy a bloc of data
   MOVE CUSTOMER1_DATA TO CUSTOMER2_DATA

* Copy a data to many fields
   MOVE DATA1 TO DATA3 DATA4 DATA5

Dans d’autres langages que le Cobol, le "signe égal"(=) remplace l’instruction MOVE. Mais l’instruction MOVE réalise plus qu’une simple copie de données:

  • S’il s’agit d’un mouvement d’une donnée alphanumérique vers une zone numérique, ou inversement, MOVE convertit la donnée.
  • Si la zone de destination est trop grande, des espaces ou des zéros sont rajoutés, selon la nature de la zone. La donnée est cadrée à gauche ou à droite, selon la déclaration de la zone de destination. Pour les nombres, le cadrage se fait sur la position de la virgule (quand il n’y en a pas, le cadrage est droite). Pour les chaines, le cadrage est à gauche, sauf si l’attribut JUSTIFIED RIGHT a été précisé.
  • Si la zone de destination est trop petite, la donnée est copiée mais elle est tronquée. Elle ne déborde pas sur la zone suivante, ce qui évite les ennuis que du langage C.

Quand une variable fait partie d’une structure, il est recommandé d’indiquer aussi le nom de cette structure pour améliorer la lisibilité des programmes, et pour éviter toute ambiguïté au cas où deux données auraient le même identifiant.

Exemple:

DATA DIVISION.
WORKING-STORAGE SECTION.
01 DATE_DD_MM_YYYY.
   05 DD PIC X(4) VALUE "11".
   05 FILLER PIC X VALUE "/".
   05 MM PIC X(2) VALUE "02".P>
   05 FILLER PIC X VALUE "/".
   05 YYYY PIC X(4) VALUE "1650".

01 DATE_YYYYMMDD.
   05 YYYY PIC X(4).
   05 MM PIC X(2).
   05 DD PIC X(4).

PROCEDURE DIVISION.
MAIN_PARAGRAPH.
   MOVE DD OF DATE_DD_MM_YYYY
    TO DD OF DATE_YYYYMMDD
   MOVE MM OF DATE_DD_MM_YYYY
    TO MM OF DATE_YYYYMMDD
   MOVE YYYY OF DATE_DD_MM_YYYY
    TO YYYY OF DATE_YYYYMMDD
   .

Si DATE_YYYYMMDD faisait lui même partie d’un groupe, nommé par exemple MY_DATA, alors on aurait pu écrire MOVE DD OF DATE_DD_MM_YYYY TO DD OF DATE_YYYYMMDD OF MY_DATA.

Dans le cas de l’exemple ci-dessus, les trois lignes de la PROCEDURE DIVISION peuvent être remplacées par une seule ligne en se servant d’une variante de l’instruction MOVE, comme ceci:

MOVE CORRESPONDING DATE_DD_MM_YYYY
     TO DATE_YYYYMMDD

Pour faire encore plus court, utiliser l’abréviation CORR au lieu de CORRESPONDING.

Le MOVE CORR ne marche qu’à condition que des champs aient exactement le même nom dans le bloc source et le bloc destination, et que ces champs aient le même niveau de hiérarchie.

Un élément d’une table est référencé par son nom suivi d’un indice placé entre parenthèses.

Le premier élément est l’élément 1. Il n’y a pas d’élément zéro.

Exemple

   MOVE MY_ITEM(5) TO DATA2
   MOVE MY_ITEM(NUM) TO DATA2
   MOVE MY_SQUARE(I) OF MY_LINE(J) TO DATA2
   MOVE MY_SQUARE(I, J) TO DATA2

Pour ne manipuler qu'une sous-chaîne, il faut utiliser la syntaxe suivante : variable(position:longueur).

La position 1 correspond au premier caractère. Il n’y a pas de position 0.

Exemple :

   MOVE DATA1(2:3) TO DATA2
   MOVE DATA1 OF GROUP1(2:3) TO DATA2
   MOVE DATA1 TO DATA2(POS:LG)

La deuxième ligne de l’exemple copie les trois caractères à partir du deuxième caractère du champ DATA1 vers DATA2. Notez que OF GROUP1 doit être placé avant la parenthèse.

Pour initialiser un drapeau, il existe deux possibilités, soit l’instruction MOVE, soit l’instruction SET.

Exemple:

DATA DIVISION.
WORKING-STORAGE SECTION.
77 FLAG_EOF PIC X.
   88 NOT_THE_END_OF_THE_FILE VALUE "N".
   88 EOF VALUE "E".
PROCEDURE DIVISION.
MAIN_PARAGRAPH.
   MOVE "E" TO FLAG_EOF
   SET EOF TO TRUE
   .


Autres instructions de manipulation de données alphanumériques

L’instruction INITIALIZE remplit une variable avec des espaces ou avec des zéros selon que la zone est de type alphanumérique ou numérique. Pour une zone simple, INITIALIZE est équivalent à MOVE SPACES ou à MOVE ZEROES. Pour un bloc de données (structure), INITIALIZE met des espaces ou des zéros en fonction du type de chaque zone du bloc.

Exemple :

   INITIALIZE MY_NAME
   INITIALIZE MY_AGE
   INITIALIZE MY_DATA

L’instruction STRING met bout à bout plusieurs chaînes de caractères.

L’instruction UNSTRING tronçonne une chaîne de caractères en plusieurs morceaux.

L’instruction INSPECT compte et/ou remplace des caractères.


Opérations arithmétiques

L’instruction COMPUTE sert pour faire toutes sortes de calculs

Sa syntaxe est: COMPUTE data1 = expression arithmétique.

Exemple :

COMPUTE NUM1 = NUM2 + NUM3 * NUM4
     / (NUM5 + NUM6)
     - 23.4 + 6
COMPUTE BIG_NUMBER = (2 ** POWER) - 1

L'ordre de priorité des opérateurs est classique. En premier, sont traitées les sous-expressions arithmétiques entre parenthèses, puis les multiplications et les divisions, et enfin les additions et les soustractions.

Il reste quatre autres instructionsarithmétiques : ADD, SUBTRACT, DIVIDE, et MULTIPLY, dont les syntaxes sont:

ADD data1 TO data2.

(Equivalent à COMPUTE data2 = data1 + data2)

ou ADD data1 TO data2 GIVING DATA3.

ou ADD CORRESPONDING struct1 TO struct2.

SUBTRACT data1 FROM data2.

(Equivalent à COMPUTE data2 = data2 - data1)

ou SUBTRACT data1 FROM data2 GIVING DATA3.

ou SUBTRACT CORRESPONDING struct1 FROM struct2.

MULTIPLY data1 BY data2.

(Equivalent à COMPUTE data2 = data1 * data2)

ou MULTIPLY data1 BY data2 GIVING DATA3.

DIVIDE data1 BY data2 GIVING data3.

(Equivalent à COMPUTE data3 = data1 / data2)

DIVIDE data1 BY data2 GIVING data3 REMAINDER data4.

DIVIDE data1 INTO data2.

(Equivalent à COMPUTE data2 = data2 / data1)

DIVIDE data1 INTO data2 GIVING data3.

DIVIDE data1 INTO data2 GIVING data3

REMAINDER data4.

Personnellement je ne me sers que de COMPUTE, sauf pour incrémenter un compteur, auquel cas, je me sers de ADD.

Le Cobol standard ne dispose pas d’autre fonction arithmétique. Par exemple, il n’y a pas de fonction trigonométrique, ni de fonction retournant un nombre aléatoire, mais de nombreux compilateurs les proposent.


Formatage des données

Pour formater un nombre avant de l'afficher ou de l'imprimer, il faut utiliser une instruction MOVE vers un "masque d'édition", comportant :

  • 9 pour un chiffre
  • Z pour un espace à la place d'un zéro à gauche du nombre
  • - pour un signe moins à gauche du nombre, si le nombre est négatif
  • + pour un signe plus ou moins à gauche du nombre
  • $ pour un signe monétaire à gauche du nombre
  • * pour une étoile à la place d'un zéro à gauche du nombre
  • B pour l'insertion d'un espace
  • 0 pour l'insertion d'un zéro
  • / pour l'insertion d'une barre oblique
  • , pour l'insertion d'une virgule
  • . pour l'insertion d'un point (ou d'une virgule, voir plus loin) séparant les décimales
  • CR pour l'addition de CR après un nombre négatif
  • DB pour l'addition de DB après un nombre négatif

Exemple :

IDENTIFICATION DIVISION.
PROGRAM-ID. TEST1.

DATA DIVISION.
WORKING-STORAGE SECTION.
77 NUM1 PIC S9999V99 COMP VALUE -1234.89.
77 EDI1 PIC ZZ,ZZ9.99.
77 EDI2 PIC -- --9.99.

PROCEDURE DIVISION.
MAIN.

* Display -123489
   DISPLAY NUM1

* Display 1,234.89
   MOVE NUM1 TO EDI1
   DISPLAY EDI1

* Display -1 234.89
   MOVE NUM1 TO EDI2
   DISPLAY EDI2

* The end
   STOP RUN
   .

Les français ont l’habitude de mettre une virgule au lieu d'un point pour séparer la partie décimale de la partie entière d'un nombre. Les concepteurs du Cobol y ont penser. Pour changer de convention, il suffit d’écrire "DECIMAL-POINT IS COMA." dans le paragraphe SPECIAL-NAMES de la CONFIGURATION SECTION de l’ENVIRONMENT DIVISION.


Les comparaisons

Les instructions IF, EVALUATE et PERFORM font des comparaisons (surtout IF et EVALUATE).


L'instruction IF

Les deux formes de l'instruction IF sont :

  • IF condition THEN instructions END-IF
  • IF condition THEN instructions ELSE instructions END-IF

Le mot réservé THEN est facultatif.

L'ancienne syntaxe (qui est toujours en usage et comprise par les compilateurs modernes) exige un point au lieu d'un ou de plusieurs END-IF consécutifs. Personnellement, je n’utilise jamais l’ancienne syntaxe. Il faut la connaître, parce que la loi de la tartine beurrée veut que l’on vous donne souvent à maintenir un programme écrit avec la vieille syntaxe.

Les comparaisons en Cobol sont très puissantes.

Tout d'abord, voici quelques exemples de comparaisons semblables à celles d'autres langages (Basic, C, Pascal, etc).

* comparaison of simple strings
   IF STRING1 = STRING2
    DISPLAY "yes"
   END-IF

* comparaison of simple numbers
   IF NUM1 = NUM2
    DISPLAY "yes"
   END-IF
   IF NUM1 > NUM2
    DISPLAY "yes"
   END-IF
   IF NUM1 < NUM2
    DISPLAY "yes"
   END-IF
   IF NUM1 <= NUM2
    DISPLAY "yes"
   END-IF
   IF NUM1 >= NUM2
    DISPLAY "yes"
   END-IF

* comparaison of arithmetic expressions
   IF NUM1 + NUM2 - NUM3 * NUM4 / NUM5 = NUM9
    DISPLAY "yes"
   END-IF

* composed conditions using boolean operators
   IF STRING1 = STRING2 AND STRING3 = STRING4
    DISPLAY "yes"
   END-IF
   IF STRING1 = STRING2 OR NUM1 + NUM2 < NUM3
    DISPLAY "yes"
   END-IF

Maintenant, voici des exemples de conditions propres au Cobol.

* class condition
   IF STRING1 IS NUMERIC
    DISPLAY "yes"
   END-IF
   IF STRING1 IS ALPHABETIC
    DISPLAY "yes"
   END-IF
   IF STRING1 IS ALPHABETIC-LOWER
    DISPLAY "yes"
   END-IF
   IF STRING1 IS ALPHABETIC-UPPER
    DISPLAY "yes"
   END-IF

* sign condition
   IF NUM1 IS POSITIVE
    DISPLAY "yes"
   END-IF
   IF NUM1 IS NEGATIVE
    DISPLAY "yes"
   END-IF
   IF NUM1 IS ZERO
    DISPLAY "yes"
   END-IF

* condition-name
   IF FLAG_SET_TO_YES
    DISPLAY "yes"
   END-IF
   IF END_OF_FILE1
    DISPLAY "yes"
   END-IF
   IF EUROPEAN_COUNTRY
    DISPLAY "yes"
   END-IF

* abbreviated conditions
* if NUM1 is between NUM2 and NUM3
   IF NUM1 > NUM2 AND < NUM3
    DISPLAY "yes"
   END-IF

* if NUM1 is greater than NUM2,
* or NUM1 is greater than NUM3
   IF NUM1 > NUM2 OR NUM3
    DISPLAY "yes"
   END-IF

* It is not necessary to repeat
* the first member of the comparaison
   IF SALAIRE+REVENU*COEFFICIENT
    - ABBATEMENT * TAUX + ETC
    > NUM2 AND NUM3
    DISPLAY "yes"
   END-IF

Ne sont-elles pas belles ces conditions abrégées?


L'instruction EVALUATE

L’instruction EVALUATE s'utilise à la place de plusieurs IF.

EVALUATE est une instruction très puissante (plus que le "switch" du C), comme le montrent les exemples suivants:

* evaluate a data
   EVALUATE STRING1
   WHEN "foo"
     DISPLAY "STRING1=foo"
   WHEN "bar"
     DISPLAY "STRING1=bar"
   END-EVALUATE

* evaluate an expression
   EVALUATE TRUE
   WHEN STRING1 = "foo"
     DISPLAY "STRING1=foo"
   WHEN NUM1 > NUM2
     DISPLAY "NUM1 > NUM2"
   END-EVALUATE

* compare an expresion with another expression
   EVALUATE NUM1 + 10
   WHEN NUM2
     DISPLAY "NUM2=NUM1+10"
   WHEN NUM3
     DISPLAY "NUM3=NUM1+10"
   WHEN OTHER
     DISPLAY "other"
   END-EVALUATE

* evaluate many things at once
   EVALUATE NUM1 NUM2
   WHEN 12 25
     DISPLAY "NUM1=12 and NUM2=25"
   WHEN ANY 26.06
     DISPLAY "NUM1 not=12 and NUM2=26.06"
   WHEN OTHER
     DISPLAY "other"
   END-EVALUATE


Le déroulement d'un programme

Six instructions modifient le déroulement séquentiel d'un programme :

STOP RUN, GO TO, PERFORM, CALL, EXIT PROGRAM, et GOBACK.

GO TO force le programme à sauter au paragraphe dont le nom est passé en paramètre du GO TO.

Exemple :

GO TO PARAG_2

Il est toujours possible d’éviter d’écrire un GO TO. Personnellement, je n’ai jamais écrit un seul GO TO de ma vie (sauf pour cette exemple, et quand j’étais très très jeune). Seules les mauvais programmeurs utilisent les GO TO.

L’instruction PERFORM appelle un "module interne", c’est-à-dire localisé dans le fichier source en cours. Un "module interne" peut être :

  • un paragraphe
  • plusieurs paragraphes contigus
  • une section
  • un bloc de lignes de code commençant après PERFORM et s'étendant jusqu'à END-PERFORM. Dans ce cas, il s’agit d’un "in-line perform".

Exemple :

IDENTIFICATION DIVISION.
PROGRAM-ID. TEST_PERFORM.

PROCEDURE DIVISION.
S1 SECTION.
MAIN.
   PERFORM SUBROUTINE1
   PERFORM SUBROUTINE1 THRU SUBROUTINE2
   PERFORM S2
   PERFORM
    DISPLAY "in-line perform"
   END-PERFORM
   STOP RUN
   .
SUBROUTINE1.
   DISPLAY "subroutine 1"
   .
SUBROUTINE2.
   DISPLAY "subroutine 2"
   .
S2 SECTION.
S2PARAG1.
   DISPLAY "section S2"
   .

PERFORM peut appeler un module plusieurs fois. Exemple :

PERFORM SUBROUTINE1 10 TIMES
PERFORM SUBROUTINE1 NUM1 TIMES

L'appel du module peut dépendre d'une condition.

Exemple :

PERFORM SUBROUTINE1 WITH TEST BEFORE
     UNTIL I > 10
PERFORM SUBROUTINE1 UNTIL I > 10
PERFORM SUBROUTINE1 WITH TEST AFTER
     UNTIL END_OF_FILE1

L'option par défaut est "WITH TEST BEFORE".

Une variable peut être initialisée avant le premier appel, et être incrémentée à chaque fois que le module est appelé.

Exemple :

PERFORM SUBROUTINE1 VARYING I FROM 1 BY 1

Voici un exemple plus complexe :

PERFORM SUBROUTINE1 THRU SUBROUTINE2
     VARYING I FROM NUM1 BY NUM2
     UNTIL TOTO >= TITI OR END-OF-FILE
      OR ERROR-FLAG = "E"

L’instruction CALL appelle un "module externe", c’est-à-dire, un module qui n'est pas localisé dans le fichier source actuel. Un "module externe" peut être :

  • un programme écrit en Cobol,
  • une routine écrite dans un autre langage, qui respecte quelques obligations (cela dépend du compilateur Cobol, de l'éditeur de liens et du système d'exploitation).

Les paramètres, s'il y en a, sont passés après le mot réservé USING.

Exemple :

CALL "PROCESS1"
CALL "CLIENTS" USING NAME,
     ADDRESS1, ADDRESS2, TEL

Le nom du module doit être indiqué entre guillemets dans le programme. Il n'est pas possible de mettre le nom du module dans une variable.

Le module appelé redonne la main au module appelant grâce à l'instruction EXIT PROGRAM, ou son synonyme GOBACK.

Dans le module appelé, les paramètres doivent être énumérés sur la ligne commençant par PROCEDURE DIVISION. Ils doivent aussi être redéclarés dans la LINKAGE SECTION de la DATA DIVISION.

Exemple :

IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN.
DATA DIVISION.
WORKING-STORAGE SECTION.
77 ITEM PIC X(20) VALUE "BOOKS".
77 TOTAL_QUANTITY PIC 9(5) VALUE 36.
PROCEDURE DIVISION.
MAIN.
   DISPLAY "Before, there are: " TOTAL_QUANTITY
     " " ITEM
   CALL "ADDSTOCK" USING ITEM TOTAL_QUANTITY
   DISPLAY "After, there are: " TOTAL_QUANTITY
     " " ITEM
   STOP RUN
   .

 

IDENTIFICATION DIVISION.
PROGRAM-ID. ADDSTOCK.
DATA DIVISION.
WORKING-STORAGE SECTION.
77 QUANTITY PIC 9(5) VALUE 7.
LINKAGE SECTION.
77 ITEM_A PIC X(20).
77 GLOBAL_QUANTITY PIC 9(5).
PROCEDURE DIVISION USING ITEM_A GLOBAL_QUANTITY.
MAIN2.
   DISPLAY "Now, I add " QUANTITY " " ITEM
   ADD QUANTITY TO GLOBAL_QUANTITY
   EXIT PROGRAM
   .

Les compilateurs les plus récents autorisent la présence de plusieurs modules dans le même fichier source (les deux modules de l’exemple pourraient être l’un derrière l’autre dans le même fichier). Mais traditionnellement, ces deux modules doivent se trouver dans deux fichiers sources différents, et être compilés indépendamment l’un de l’autre.

Il est très important de s'assurer que la liste des paramètres derrière l'instruction CALL, soit identique à la liste des paramètres derrière PROCEDURE DIVISION. Les noms des variables peuvent être différents dans les deux programmes. Si le nombre de paramètre est différent, si le type ou la taille des paramètres est différent, le compilateur ne le détectera pas. L’éditeur de liens devraient théoriquement le détecter, mais 99% ne le détecte pas. Un mauvais passage de paramètres provoquera des phénomènes étranges, lors de l'éxécution du programme.


La gestion des fichiers

Cobol, dans sa version de base, permet de gérer des fichiers simples et des fichiers indexés. Les enregistrements peuvent être lus de deux façons : séquentiellement, ou directement par une clé.

Pour gérer un fichier, le programmeur doit :

  • "selectionner" le fichier dans le paragraphe FILE-CONTROL de l'INPUT-OUTPUT SECTION de l'ENVIRONMENT DIVISION,
  • déclarer le(s) enregistrement(s) dans la FILE SECTION de la DATA DIVISION,
  • déclarer éventuellement, un "file status", et/ou une clé dans la WORKING-STORAGE SECTION de la DATA DIVISION,
  • traiter le fichier dans la PROCEDURE DIVISION.

Dans le paragraphe FILE-CONTROL de l'INPUT-OUTPUT SECTION de l'ENVIRONMENT DIVISION, les caractéristiques globales du fichier sont décrites par l'instruction SELECT :

  • Le nom interne au programme Cobol du fichier.
  • Le nom externe du fichier avec le chemin complet (le disque et les répertoires).
  • Le mot réservé‚ FILE-ID peut remplacer le nom d'un fichier entre guillemets. Dans ce cas, FILE-ID, dans la FILE SECTION de la DATA DIVISION, est associé à une variable qui contiendra le nom du fichier.
  • Le type d'organisation : SEQUENTIAL, RELATIVE, ou INDEXED. Le mode d'organisation par défaut est SEQUENTIAL.
  • Le mode d'accès : SEQUENTIAL, RANDOM, ou DYNAMIC.
  • La clé, uniquement si l'organisation n'est pas séquentielle.
  • Eventuellement, un "file status", qui est une zone de deux octets qui sera mis à jour par les routines internes de gestion des fichiers pour indiquer une fin de fichier, un succès, ou un échec.
  • Exemple :

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
   SELECT SEQUENTIAL_FILE1 ASSIGN TO "FILE1.TXT".
   SELECT SEQUENTIAL_FILE2 ASSIGN TO "FILE2.TXT"
     FILE STATUS IS SEQUENTIAL_FS.
   SELECT SEQUENTIAL_FILE3 ASSIGN TO FILE-ID.
   SELECT RELATIVE_FILE ASSIGN TO "FILE3.TXT"
     ORGANIZATION IS RELATIVE
     ACCESS MODE IS RANDOM
     RELATIVE KEY IS RELATIVE_FILE_KEY
     FILE STATUS IS RELATIVE_FS.
   SELECT INDEXED_FILE ASSIGN TO "FILE4.TXT"
     ORGANIZATION IS INDEXED
     ACCESS MODE IS DYNAMIC
     RECORD KEY IS INDEXED_FILE_KEY
     FILE STATUS IS INDEXED_FS.

La FILE SECTION de la DATA DIVISION contient des informations sur la structure des enregistrements.

Exemple :

DATA DIVISION.
FILE SECTION.
FD SEQUENTIAL_FILE1
   DATA RECORD IS SEQUENTIAL_FILE_RECORD.
01 SEQUENTIAL_FILE1_RECORD.
   05 ITEM PIC X(50).
   05 QUANTITY PIC 9(5).

FD SEQUENTIAL_FILE2
   DATA RECORD IS SEQUENTIAL_FILE2_RECORD1
     SEQUENTIAL_FILE2_RECORD2.
01 SEQUENTIAL_FILE2_RECORD1.
   05 ITEM PIC X(50).
   05 QUANTITY PIC 9(5).
01 SEQUENTIAL_FILE2_RECORD2 PIC X(55).

FD SEQUENTIAL_FILE3
   VALUE OF FILE-ID IS FILE3_NAME
   DATA RECORD IS SEQUENTIAL_FILE_RECORD.

FD RELATIVE_FILE
   DATA RECORD IS RELATIVE_FILE_RECORD.
01 RELATIVE_FILE_RECORD PIC X(55).

FD INDEXED_FILE
   DATA RECORD IS INDEXED_FILE_RECORD.
01 INDEXED_FILE_RECORD.
   05 INDEXED_FILE_KEY PIC 9(5).
   05 ITEM PIC X(50).
   05 QUANTITY PIC 9(5).

WORKING-STORAGE SECTION pour les fichiers

Dans la WORKING-STORAGE SECTION de la DATA DIVISION, sont déclarés le "file status" avec une "PIC 99", et la clé d'un fichier relatif, qui est définie avec une picture numérique quelconque.

Exemple :

DATA DIVISION.
WORKING-STORAGE SECTION.
77 SEQUANTIAL_FS PIC 99.
77 RELATIVE_FILE_KEY PIC 9(3).

Avant de traiter des enregistrements, il faut ouvrir le fichier par l'instruction OPEN.

Il y a quatre modes d'ouverture différents :

  • INPUT = ouverture en lecture uniquement.
  • OUTPUT = ouverture en création. Si un fichier ayant le même nom existe déjà, il sera écrasé‚ par le nouveau.
  • I-O = ouverture d'un fichier existant déjà, pour des mises à jour.
  • EXTEND = ouverture pour des écritures en fin de fichier.

Exemple :

OPEN INPUT FILE1
OPEN OUTPUT FILE1, FILE2

L’instruction CLOSE ferme un fichier

Quand à la fin d'un programme, le contrôle est redonné au système d’exploitation, tous les fichiers sont automatiquement fermés. Cependant, il est conseillé de fermer un fichier, dés que son traitement est terminé, parce que le système d’exploitation limite le nombre de fichier ouverts simultanément, et surtout parce que la fermeture écrit sur le disque toutes les données qui pourraient éventuellement se trouver encore dans des zones tampon (un ordre WRITE n'écrit pas toujours physiquement un enregistrement sur le disque; l’enregistrement est parfois envoyé vers une zone tampon, qui ne sera transférée sur le disque qu’à la fermeture du fichier).

Exemple :

CLOSE FILE1
CLOSE FILE1, FILE2

Les enregistrements sont lus de manière directe par l'instruction READ, quand ACCESS MODE IS RANDOM, ou ACCESS MODE IS DYNAMIC. Avant la lecture, il faut évidemment, renseigner la clé.

Si l'organisation est relative, la clé correspond au numéro de l'enregistrement.

Si l'organisation est indexée, la clé doit être la zone numérique ou alphanumérique, qui a été définie lors de la première création du fichier.

Exemple :

IDENTIFICATION DIVISION.
PROGRAM-ID. TEST_READ_RELATIVE.

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
   SELECT RELATIVE_FILE ASSIGN TO "FILE3.TXT"
     ORGANIZATION IS RELATIVE
     ACCESS MODE IS RANDOM
     RELATIVE KEY IS RELATIVE_FILE_KEY
     FILE STATUS IS RELATIVE_FS.

   SELECT INDEXED_FILE ASSIGN TO "FILE4.TXT"
     ORGANIZATION IS INDEXED
     ACCESS MODE IS DYNAMIC
     RECORD KEY IS ITEM
     FILE STATUS IS INDEXED_FS.

DATA DIVISION.
FILE SECTION.
FD RELATIVE_FILE
   DATA RECORD IS RELATIVE_FILE_RECORD.
01 RELATIVE_FILE_RECORD PIC X(55).

FD INDEXED_FILE
   DATA RECORD IS INDEXED_FILE_RECORD.
01 INDEXED_FILE_RECORD.
   05 ITEM PIC X(50).
   05 QUANTITY PIC 9(5).

WORKING-STORAGE SECTION.
77 RELATIVE_FILE_KEY PIC 9(3).
77 RELATIVE_FILE_FS PIC 99.
01 RELATIVE_FILE_BUFFER.
   05 NAME PIC X(50).
   05 TEL PIC 9(10).
77 INDEXED_FILE_FS PIC 99.

PROCEDURE DIVISION.
MAIN.

   OPEN INPUT RELATIVE_FILE INDEXED_FILE

   MOVE 3 TO RELATIVE_FILE_KEY
   READ RELATIVE_FILE INTO RELATIVE_FILE_BUFFER
   IF RELATIVE_FILE_FS = 0
   DISPLAY "<" NAME ">"
   END-IF

   MOVE "CD-ROM" TO ITEM
   READ INDEXED_FILE
   IF INDEXED_FILE_FS = 0
   DISPLAY "<" INDEXED_FILE_RECORD ">"
   END-IF

   CLOSE INPUT RELATIVE_FILE INDEXED_FILE

   STOP RUN
   .

Les enregistrements peuvent être lus séquentiellement par READ NEXT, ou simplement par READ, quand il n'y a pas de risque de confusion avec une lecture en accès direct, c'est-à-dire lorsque ORGANIZATION IS SEQUENTIAL et ACCESS MODE IS SEQUENTIAL.

Exemple :

IDENTIFICATION DIVISION.
PROGRAM-ID. TEST_READ_SEQUENTIAL.

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
   SELECT FILE1 ASSIGN TO "FILE1.TXT"
     FILE STATUS IS FILE1_FS.

DATA DIVISION.
FILE SECTION.
FD FILE1
   DATA RECORD IS FILE1_RECORD.

01 FILE1_RECORD1.
   05 ITEM PIC X(50).
   05 QUANTITY PIC 9(5).

WORKING-STORAGE SECTION.
77 FILE1_FS PIC 99.
77 FLAG_EOF PIC X.
   88 KEEP_ON_READING VALUE "K".
   88 STOP_READING VALUE "S".

PROCEDURE DIVISION.
MAIN.

   OPEN INPUT FILE1
   SET KEEP_ON_READING TO TRUE

   PERFORM WITH TEST AFTER UNTIL STOP_READING
    READ FILE1 NEXT
    IF FILE1_FS = 0
     DISPLAY "<" FILE1_RECORD ">"
    ELSE
     SET STOP_READING TO TRUE
    END-IF
   END-PERFORM

   CLOSE FILE1

   STOP RUN
   .

Avant une lecture séquentielle, l'instruction START positionne un pointeur virtuel sur le fichier.

Exemple :

START FILE1 KEY = KEY1
START FILE1 KEY > KEY1
START FILE1 KEY >= KEY1

Il n'est pas possible de commencer avec une clé immédiatement inférieure à une valeur donnée.

WRITE écrit un enregistrement à la fin d'un fichier quand ACCESS MODE IS SEQUENTIAL, ou bien WRITE écrit un enregistrement dont la clé n’est égale à aucune de celles des enregistrements déjà présents. Exemple :

WRITE FILE1_RECORD
WRITE FILE2_RECORD FROM BUFFER

REWRITE met à jour un enregistrement. REWRITE ne peut pas être utilisé si ACCESS MODE IS SEQUENTIAL.

Exemple :

REWRITE FILE1_RECORD
REWRITE FILE2_RECORD FROM BUFFER

DELETE écrit des espaces dans un fichier simple, ou supprime un enregistrement dans un fichier indexé.

Exemple : DELETE FILE1 RECORD

Les DECLARATIVES sont des SECTIONs, qui seront appelées lorsque certains événements se produisent, comme par exemple des erreurs survenants lors d’un accès à un fichier.

Les DECLARATIVES doivent être écrites au début de la PROCEDURE DIVISION.

Avec les DECLARATIVES, le programmeur n'a pas besoin de tester le "file status" après chaque entrée/sortie sur un fichier. Personnellement, je préfère me passer des DECLARATIVES et tester le "file status", car je souhaite savoir précisément à quel endroit de mon programme est survenue une erreur, et avoir la possibilité de la traiter différemment selon cet endroit.

Exemple :

PROCEDURE DIVISION.
DECLARATIVES.
PROBLEM-WITH-FILE-1 SECTION. USE AFTER ERROR PROCEDURE ON INPUT.
   DISPLAY "Error on input " REL_FILE_FS ". "

PROBLEM-WITH-FILE-2 SECTION. USE AFTER ERROR PROCEDURE ON OUTPUT.
   DISPLAY "Error on output " REL_FILE_FS ". "

PROBLEM-WITH-FILE-3 SECTION. USE AFTER ERROR PROCEDURE ON REL_FILE.
   DISPLAY "Error on REL_FILE " REL_FILE_FS ".
"
END DECLARATIVES.


La date et l'heure

Il faut utiliser une variante de l'instruction ACCEPT pour récupérer la date et l'heure de l'ordinateur.

Exemple :

IDENTIFICATION DIVISION.
PROGRAM-ID. TEST_accept.

DATA DIVISION.
WORKING-STORAGE SECTION.
77 DATE_YYMMDD PIC 9(6).
77 DAY_YYQQQ PIC 9(5).
77 DOW PIC 9(1).

01 TIME_0.
   05 HH PIC 9(2).
   05 MM PIC 9(2).
   05 SS PIC 9(2).
   05 HU PIC 9(2).

PROCEDURE DIVISION.
MAIN.

   ACCEPT TIME_0 FROM TIME
   ACCEPT DATE_YYMMDD FROM DATE
   ACCEPT DAY_YYQQQ FROM DAY
   ACCEPT DOW FROM DAY-OF-WEEK
   STOP RUN
   .


Le tri

Cobol comporte des routines pour trier les données. Elles sont conçues principalement pour trier des enregistrements de fichiers. Le programmeur doit donner le nom des fichiers en entrée et en sortie, le nom d'une ou plusieurs clés, et le nom d'un fichier temporaire dont aura besoin SORT pour son traitement.

Exemple :

SORT TMPFILE
    ON ASCENDING KEY
     NAME OF FILE_BEFORE_SORT_RECORD
     FIRST_NAME OF FILE_BEFORE_SORT_RECORD
    USING FILE_BEFORE_SORT
    GIVING FILE_AFTER_SORT

Le fichier temporaire doit être déclaré dans l'ENVIRONMENT DIVISON et dans la DATA DIVISION. Exemple :

ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
   SELECT TMPFILE ASSIGN TO "SORTFILE".
DATA DIVISION.
FILE SECTION.
SD TMPFILE
   DATA RECORD IS TMPILE_REC.

01 TMPFILE_REC.
   05 NB PIC 9(3).
   05 NAME PIC X(20).
   05 FIRST_NAME PIC X(30).
   
05 YEAR PIC 9(4).
   05 DURATION PIC 9(2).

Dans la DATA DIVISION, SD remplace FD.

SORT peut aussi trier d'autres types de données. Alors, le programmeur doit indiquer le nom d'une section, à laquelle SORT fera appel pour alimenter le fichier temporaire, et le nom d'une autre section à laquelle SORT fera appel pour rendre les données triées, une par une.

Exemple :

SORT TMPFILE
    ON ASCENDING KEY
     NAME OF FILE_BEFORE_SORT_RECORD
     FIRST_NAME OF FILE_BEFORE_SORT_RECORD
    INPUT PROCEDURE IS FEED_SORT
    OUTPUT PROCEDURE IS EXTRACT_SORT

Dans la SECTION déclarée comme étant l'INPUT PROCEDURE, les données sont transférées à la routine de tri par l’instruction RELEASE. Sa syntaxe est quasiment la même que celle de WRITE.

Exemple :

RELEASE TMPFILE_REC FROM BUFFER

Dans la SECTION déclarée comme étant l'OUTPUT PROCEDURE, les données triées sont retirées du fichier temporaire, l'une après l'autre, par l’instruction RETURN, dont la syntaxe est quasiment la même que celle de READ.

Exemple :

RETURN TMPFILE INTO BUFFER
     AT END
     SET SORTFILE_EOF TO TRUE
END-RETURN

Il est aussi possible de mélanger plusieurs types de tri.

Exemple :

SORT TMPFILE
    ON ASCENDING KEY
     NAME OF FILE_BEFORE_SORT_RECORD
     FIRST_NAME OF FILE_BEFORE_SORT_RECORD
    USING FILE_BEFORE_SORT
    OUTPUT PROCEDURE IS EXTRACT_SORT

SORT TMPFILE
    ON ASCENDING KEY
     NAME OF FILE_BEFORE_SORT_RECORD
     FIRST_NAME OF FILE_BEFORE_SORT_RECORD
    INPUT PROCEDURE IS FEED_SORT
    GIVING FILE_AFTER_SORT


Divers

Le langage Cobol possède d'autres instructions.

SEARCH sert à rechercher un élément dans une table. Je ne me suis jamais servi de cette instruction parce que je pense qu'écrire une petite boucle est une chose plus facile à faire que de retenir la syntaxe et le fonctionnement de SEARCH. Si j'ai besoin d'une recherche très rapide, je crée une table hachée, et celle-ci ne peut être gérée par SEARCH.

Le Report Writer est un ensemble de fonctions apparues dans les spécifications ANSI 1974 du Cobol. Le Report Writer est sensé faciliter la programmation des éditions. J’estime qu’environ 10 pour cent des programmes d’édition font appel aux fonctions du Report Writer. Personnellement, je trouve que le "Report Writer" n'est pas pratique. Je ne l'aime pas, parce qu’il est complexe, et parce qu'il est souvent impossible de faire de la programmation modulaire structurée en l'utilisant. Cela dit, la plupart des autres outils de génération d’état ont les mêmes défauts.

 

 

 

 

 

© Copyright Alakazam 2004.