House of
COBOL
Guide de l'utilisateur du
Common Business Oriented Language
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
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.

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.

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.

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.

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.

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.

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)).

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.

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.

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)
.
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. |

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)".

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.

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.

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.

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.

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’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.

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
. |

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.

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.

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 instructions IF, EVALUATE et PERFORM font des comparaisons (surtout IF et
EVALUATE).

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 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 |

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 :
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.

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. |

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 . |

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 |

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.

|