La FILE SECTION contient une description de fichier ainsi qu’une ou plusieurs descriptions d’enregistrement pour chaque fichier utilisé par le programme.
DECLARATION DU FICHIER
FD file-name BLOCK CONTAINS XXX RECORDS RECORD CONTAINS NNN CHARACTERS LABEL RECORD IS {STANDARD} {OMITTED } VALUE OF { FILE-ID } IS id-name DATA { RECORD IS } {record-name} … { RECORDS ARE }
Le nom est celui que l’on trouve dans SELECT XXX indique le nombre d’enregistrements contenu dans un bloc NNN donne la longueur en octet d’un enregistrement LABEL indique s’il s’agit d’enregistrements sur imprimante (omitted) ou autre VALUE permet de donner le nom du fichier sur disque DATA RECORD est utilisé pour indiquer le nom de l’enregistrement qui décrira le niveau 01, comme il peut y avoir des enregistrements de modèles différents on peut les renseigner ici.
Description de l’enregistrement
Cette partie donne : – le type et la longueur des champs qui le composent – l’ordre de ces champs
Dans la description de l’enregistrement : –les données sont définies de façon hiérarchique (par niveau). –Le nom de l’enregistrement porte le numéro 01 –les numéros 02 à 49 peuvent être utilisés pour identifier les items dans l’enregistrement. –Les items qui composent un item de groupe doivent porter un numéro plus grand que ce dernier. –Tous les items de même niveau doivent porter le même numéro.
Le format général d’une description de zone de données est : – 01 débute dans la marge A, – les autres numéros dans la marge B.
Cette section (WORKING-STORAGE SECTION) décrit les variables de travail. Les variables COBOL peuvent être classées en 2 catégories : les données élémentaires et les groupes de données.
Les variables élémentaires
Niveau nom-de-donnée [PICTURE] description Usage [VALUE IS littéral] [PIC ]
Niveau : les données élémentaires isolées ont soit le niveau 77 soit 01 (marge A), en soi il n’y a aucune différence, seulement les 77 doivent être déclarées en tête de la WSS. Il n’y a pas de 77 en File Section.
Nom de la donnée : c’est le nom par lequel le programmeur pourra référencer la variable. Ils doivent être différents des mots réservés et univoques.
PICTURE
identifie le type de donnée indique la dimension (grandeur) de l’item le type peut être alphanumérique (X), numérique (9), alphabétique (A), numérique édité (9,Z,+, -, …)
Pour éviter les répétitions, on peut utiliser la forme suivante 05 PRENOM PIC X(10). 15 SALAIRE PIC 9(7).
La clause PICTURE : – est présente pour les éléments SIMPLES seulement. – peut débuter n’importe où dans la marge B. – la chaîne de caractère décrivant l’item doit être précédée d’au moins un espace. – Il ne doit pas y avoir d’espace dans la chaîne de caractères.
Les items numériques (PICTURE 9) sont les seuls qui peuvent être utilisés pour les opérations arithmétiques. Lorsqu’une valeur décimale est lue dans un fichier d’entrée, le point décimal n’apparaît pas mais sa présence est implicite.
Ex. 12500 représente 125.00 Ceci est indiqué en plaçant le symbole V à l’endroit où doit être le point: 05 MONTANT PIC 999V99
USAGE
identifie le type de représentation interne qui est utilisé pour enregistrer l’information. Les principaux types sont :
DISPLAY BINARY PACKED-DECIMAL
VALUE
Il est possible d’initialiser la donnée, le littéral est une valeur constante. Cette initialisation ne se fait qu’une fois lors du lancement du programme. Cette valeur doit être conforme à la descriptions qui a été faite.
Si Value est omis, la valeur initiale est INDETERMINEE.
77 TAUX PIC 99 VALUE 0. 01 CAPITAL PIC 999999 VALUE ZERO. 01 REPONSE PIC XXX VALUE 'NON'.
Dans le cas des PIC X ou A attention à la longueur, la chaîne est toujours mise entre ” ” , le mot ALL peut être utilisé et dans ce cas il y aura n occurrence du caractère dans la chaîne.
77 CHAINE PIC XXXXXXXX VALUE ALL 'N'. sans ALL un seul N suivi de blancs serait placé dans chaine.
Ne peut contenir que des chaînes de caractères issues des lettres “A” à “Z” ou “a” à “z” et le caractère blanc. Un caractère occupe 1 octet en mémoire.
X pour Alphanumérique
Une chaîne de ce type peut contenir n’importe quel caractère. Un caractère occupe 1 octet en mémoire.
Dans les 2 cas : – si le texte du value est < à la taille du Pic un complément à blanc est effectué. – si le texte du value est > à la taille du Pic une erreur sera donnée à la compilation – si All est utilisé le caractère sera transféré dans toutes les positions de la variable – si Space est utilisé toute la donnée sera mise à blanc – les données sont cadrées à gauche
9 pour Numérique
DISPLAY BINARY PACKED-DECIMAL
Les données numériques sont représentées par les symboles 9 S et V et selon l’usage utilisé elles seront DISPLAY BINARY ou PACKED-DECIMAL. Les données sont cadrées à droite sur la virgulle virtuelle. Si la virgule n’est pas présente elles est supposée être à l’extrême droite. Lors d’un MOVE la donnée sera tronquée à gauche si la zone réceptrice est plus petite que la zone émettrice. Le transfert de 1000 dans une PIC 999 donne comme résultat 000. Si la réceptrice est plus grande la donnée est complétée par des zéros à gauche.
La donnée aura :
Autant de chiffres que la description contiendra de 9. Un signe suivant la présence ou non du S en début de la description. Un point décimal à l’emplacement défini par V.
En mode DISPLAY
La donnée occupera autant d’octects qu’il y a de 9 et avec un maximum de 18. Le signe est superposé au dernier chiffre, dans les 4 bits de gauche de l’octet le plus à droite. Le point décimal V est implicite et n’occupe aucune place en mémoire.
En mode BINARY
Le signe se trouve dans le bit de gauche. Comme les variables sont binaires elles sont normalisées à 2, 4, 8 octets.
Pour Pic 9 à Pic 9999 on réserve en mémoire 2 octets : PIC 9999 BINARY Pour Pic 9(5) à Pic 9(9) on réserve en mémoire 4 octets Pour Pic 9(10) à Pic 9(18) on réserve en mémoire 8 octets
En mode PACKED-DECIMAL
Ce mode caractérise les numériques en décimal condensé avec 2 chiffres par octet. Le signe se trouve dans les 4 bits de droite de l’octet le plus à droite. Ce mode est particulièrement adapté à l’écriture sur les supports externes. La longueur en octet est calculée de la manière suivante : (nombre de 9) / 2 + 1
Soit VARA PIC 9(7) PACKED-DECIMAL => 7/2 + 1 = 4 octets
Lorsque l’information est entreposée sur un support magnétique les caractères d’édition ne sont pas inclus. Certaines fonctions d’édition doivent donc être accomplies quand ces données sont imprimées. Ceci est accompli en utilisant des caractères d’édition dans la PICTURE des items qui doivent être imprimés.
Les fonctions d’édition les plus courantes sont :
Suppression des zéros non-significatifs
Impression du point décimal
Impression des virgules
Impression du signe de dollar
Impression d’astérisques en guise de protection
Impression d’un signe (+ ou -)
Le symbole Z est utilisé pour supprimer l’impression des zéros non-significatifs. Ce symbole peut apparaître plus d’une fois dans un PICTURE. Le Z a le même effet que le 9, sauf qu’une valeur de 0 qui n’est pas significative est remplacée par un espace.
Pour créer un PICTURE qui contient un symbole flottant, on remplace chaque Z par le symbole qui doit précéder le nombre ( ceux-ci peuvent être * + – Z)
Il est à noter que le premier + – ne prend pas la place d’un caractère numérique. Donc il faut compter une position de plus afin de garder l’intégrité de la donnée. Pour éviter qu’un signe soit imprimé sans chiffre, la clause BLANK WHEN ZERO est utilisée.
La clause BLANK WHEN ZERO est utilisée avec les items numériques. Si la valeur de l’item est nulle, l’item ne contient que des espaces. La clause REDEFINES permet de définir des structures de données différentes pour une même zone de mémoire. La clause JUSTIFIED est utilisée pour modifier la justification (cadrage) des items alphanumériques ou alphabétiques. La clause SIGN, utilisée pour les items numériques de types DISPLAY contenant un PICTURE S, indique le mode de représentation du signe. La clause OCCURS sert à définir un tableau.
Le mot réservé FILLER est utilisé :
Pour indiquer la présence dans un fichier d’entrée d’un ou plusieurs champs auxquels on ne fera pas référence.
Le mot FILLER peut apparaître plus d’une fois dans un programme.
Pour les travaux de gestion, il est nécessaire d’attribuer un nom collectif à tout ensemble de données puis des noms collectifs à des sous-ensembles,…. En COBOL nous disposons de 2 sortes d’ensembles de données, les structures et les tables.
Une structure est un système hiérarchique de noms qui renvoie à une zone de mémoire centrale regroupant un ensemble de données.
Au premier niveau 01, se trouve le nom de la structure principale qui désigne l’ensemble des éléments de données mémorisées dans la totalité de la zone attribuée à cette structure. Ce nom ne pourra plus être utilisé pour définir une variable simple ou une autre structure ou un quelconque autre nom dans ce programme.
Au niveau 02, il est attribué de nouveaux noms à certaines portions de la zone. Ce processus se poursuit jusqu’à ce qu’au dernier niveau un seul nom désigne un seul et même élément de données appelé élément simple.
Un élément collectif de structure est appelé un groupe et est toujours de type alphanumérique.
Remarque :
Toute ligne de description d’un niveau se termine par un point, un niveau par ligne.
Le niveau 01 doit être en marge A.
Les niveau suivant de 02 à 49 sont écrits à partir de la marge B, avec indentation.
Les éléments simples sont les seuls à disposer d’une PICTURE, le mode DISPLAY étant l’option par défaut.
Si pour certaines raisons, le programme dispose de zones décrites dans une ou plusieurs structures et qui ne doivent pas être utilisées, nous pouvons utiliser l’option FILLER.
Une table est un groupe de données composé d’éléments simples ayant tous des attributs identiques. Les tables sont utilisées pour mettre en mémoire un certain nombre d’informations dans le but de pouvoir les retrouver plus facilement. Par exemple : trouver le prix de vente d’un article connaissant son code, trouver le nom d’un employé en fonction de son matricule. La taille d’un tableau n’est pas illimitée, les contraintes viennent du type d’ordinateur utilisé sur PC OCCURS 1300 et il faut encore tenir compte des longueurs des variables utilisées. (PRUDENCE). La recherche d’un élément en table se fait en affectant un numéro d’ordre à chaque élément de la table. Ce numéro d’ordre est appelé INDICE.
Exemple :
01 TABLE. 02 QUANTITE OCCURS 5 PIC 999
Ce qui représente une table à 1 dimension de 5 éléments de 3 caractères numériques.
Quantité 1
Quantité 2
Quantité 3
Quantité 4
Quantité 5
La quantité 4 de la table sera désignée par l’expression QUANTITE(4), et si nous désirons ajouter un nombre QACHAT à la quantité 2, nous devons écrire : ADD QACHAT TO QUANTITE (2).
L’indice peut être utilisé sous forme d’un nombre ou d’une variable.
Sous forme de nombre : on écrit QUANTITE (3) pour atteindre à chaque fois l’élément 3.
Sous forme de variable : on lira par exemple l’indice N qui peut avoir les valeurs 1 à 5 puis la quantité est atteinte en écrivant QUANTITE (N).
Comme toute variable, l’indice doit être déclaré en DATA-DIVISION. Il peut être tout simplement une zone de fichier entrée qui sert occasionnellement d’indice.
Remarque : la parenthèse gauche doit toujours être précédée par un espace à gauche, mais pas la parenthèse droite.
4.7.3 Tables à plusieurs indices
Cobol autorise des tables à 3 indices. Dans l’exemple suivant, on recherche les points d’un examen de math en deuxième année d’un étudiant d’info.
L’ensemble des points par étudiant se retrouve dans TABLE-ETUDIANT, il s’agit d’une suite continue de caractères numériques. Il n’autorise pas l’usage d’un indice.
LANNEE, spécifie si les points recherchés sont ceux d’un étudiant de première, seconde ou troisième année. L’utilisation de LANNEE (2) nous donne une longue série de chiffres qui correspond à 55 x 15 càd les 15 résultats des 55 étudiants de seconde. Cette zone autorise l’usage d’un indice et d’un seul.
CODE-ETUDIANT, donne pour un étudiant d’une année l’ensemble des points obtenus pour cette année la. L’utilisation de CODE-ETUDIANT (2, 17) nous donne une série de 15 chiffres de 2 caractères, cette série représente pour l’étudiant n° 17 de seconde année l’ensemble des points obtenus. Cette zone autorise l’usage de 2 indices et de toujours 2 indices.
LABRANCHE, donne pour un étudiant d’une année les points obtenus dans une branche. L’utilisation de LABRANCHE (2, 17, 4) nous donne les points de la quatrième matière de l’étudiant n° 17 de 2ème année , il s’agit d’un nombre de 2 positions en PIC 99. Cette zone autorise l’usage de 3 indices et de toujours 3 indices.
Les points du premier examen du deuxième étudiant de troisième année s’écrira : LABRANCHE (3, 2, 1)
Pour déplacer l’ensemble des points de l’étudiant 5 de première année on écrira : CODE-ETUDIANT (1, 5)
Pour déplacer l’ensemble des points des étudiants de première année on écrira : LANNEE (1)
4.7.4 La clause OCCURS
OCCURS n TIMES, spécifie qu’un groupe ou un élément se reproduit n fois. Dans notre exemple nous avions considéré 3 années de 55 étudiants ayant au maximum 15 banches. Cette clause ne peut pas s’écrire à un niveau 1. Pour définir une table à plusieurs niveaux, chaque OCCURS doit être de niveau inférieur sans quoi on obtient plusieurs tables à 1 niveau. Le mot TIMES est facultatif.
Une clause VALUE spécifiée pour un OCCURS initialise chaque position à cette valeur.
Pour initialiser une table à des valeurs différentes on doit utiliser la clause REDEFINES sous la forme suivante :
01 ENSEMBLE. 02 FILLER PIC X(9) VALUE "JANVIER". 02 FILLER PIC X(9) VALUE "FEVRIER". 02 FILLER PIC X(9) VALUE "MARS". 02 FILLER PIC X(9) VALUE "AVRIL". 02 FILLER PIC X(9) VALUE "MAI". 02 FILLER PIC X(9) VALUE "JUIN". 02 FILLER PIC X(9) VALUE "JUILLET". 02 FILLER PIC X(9) VALUE "AOUT". 02 FILLER PIC X(9) VALUE "SEPTEMBRE". 02 FILLER PIC X(9) VALUE "OCTOBRE". 02 FILLER PIC X(9) VALUE "NOVEMBRE". 02 FILLER PIC X(9) VALUE "DECEMBRE".
01 TABLE-MOIS REDEFINES ENSEMBLE. 02 MOIS OCCURS 12 PIC X(9).
L’utilisation des tables est inchangée, mais l’accès mémoire est plus rapide, certaines instructions de recherche peuvent être utilisées ce qui facilite la programmation. Dans ce cas les indices utilisés sont des données spéciales appelées INDEX (représentation de l’indexation). Ceux-ci doivent être définis par la clause INDEXED BY des clauses OCCURS.
Description d’une table :
01 TABLE. 02 INFO OCCURS 10 INDEXED BY J PIC X(33).
Utilisation :
MOVE "Ceci est un test " TO INFO (J). MOVE "Ceci est un test " TO INFO (J + 3).
Remarque :
Les INDEX ne peuvent être modifiés ou initialisés que par PERFORM ou par l’instruction SET. L’index qui définit un OCCURS doit toujours être utilisé avec le nom de son OCCURS dans notre cas J et INFO. Une opération + ou – dans la parenthèse peut être réalisée, ce qui donne une indexation relative. L’entier utilisé doit être > 0 et non signé, le signe doit être précédé et suivi d’un blanc. On ne peut pas mélanger les INDICES et les INDEX.
Exemple :
01 TABLE. 02 PCODE OCCURS 3 TIMES INDEXED BY PAR. 03 ACODE OCCURS 3 TIMES INDEXED BY AGE. 04 MF OCCURS 2 TIMES INDEXED BY F PIC 9999 USAGE DISPLAY.
La table est de dimension (3, 3, 2) et référencée par MF (PAR, AGE + 2, F – 1)
La clause OCCURS dans le cas des INDEX
Format 1 :
| ASCENDING | OCCURS n TIMES | |KEY is nom-de-donnée-a, … | DESCENDING | INDEXED BY nom-index.
Format 2 :
OCCURS n TO m TIMES [DEPENDING ON nom-de-donnée1] | ASCENDING |KEY is nom-de-donnée2, nom-de-donnée3,… | DESCENDING | INDEXED BY nom-index.
La clause ASCENDING ou DESCENDING spécifie l’argument de classement de la table de manière à préparer les recherches futures par l’instruction SEARCH.
01 TABLE. 02 ELEMENT OCCURS 100 ASCENDING KEY COD. 04 COD PIC XX. 04 VALEUR PIC S9999 BINARY
Ce qui signifie que le programmeur rangera les différentes informations de la table dans l’ordre croissant du COD. Il peut y avoir un maximum de 12 arguments de classement. Il est bien entendu que la valeur du classement ne peut dépendre que d’une variable incluse au tableau.
Exemples
Mise à zéro d’une table à 2 dimensions.
Soit une table de 30 lignes et 30 colonnes. Chaque élément est numérique entier de 4 de long en display. On demande d’initialiser le tableau à 1.
WORKING-STORAGE SECTION. 01 TABLE. 02 LIGNES OCCURS 30. 05 COLON OCCURS 30. 10 ELEMENT PIC 9999. 01 I PIC 99 VALUE 0. 01 J PIC 99 VALUE 0.
PROCEDURE DIVISION. DEB. PERFORM VARYING I FROM 1 BY 1 UNTIL I > 30 AFTER J FROM 1 BY 1 UNTIL J > 30 MOVE 1 TO ELEMENT (I, J) END-PERFORM.
Soit une table de 30 lignes et 30 colonnes. Chaque élément du tableau est formé d’une zone numérique entière de 4 de long en display et d’une zone alphanumérique de 20 caractères. On demande d’initialiser les numériques à 5 et les alphanumériques à blancs.
WORKING-STORAGE SECTION. 01 TABLE. 02 LIGNES OCCURS 30. 05 COLON OCCURS 30. 10 ELEMENT PIC 9999. 10 CARACTER PIC X(20). 01 I PIC 99 VALUE 0. 01 J PIC 99 VALUE 0.
PROCEDURE DIVISION. DEB. PERFORM VARYING I FROM 1 BY 1 UNTIL I > 30 AFTER J FROM 1 BY 1 UNTIL J > 30 MOVE SPACE TO CARACTER(I, J) MOVE 5 TO ELEMENT (I, J) END-PERFORM.
Soit le vecteur
01 VECT. 03 A PIC XXX OCCURS 4. 03 B PIC XXX OCCURS 4.
Et le vecteur
01 VECT2. 03 A OCCURS 4. 05 B OCCURS 4 PIC XXX.
Le premier vecteur représente 2 petits tableaux séparés à 1 dimension de 4 éléments chacun. Le second correspond à 1 tableau à 2 dimensions de 4 lignes de 4 colonnes chacune.
Instruction MERGE dans un programme COBOL. Nous avons vu dans d’autres articles comment faire un MERGE dans un JCL. Dans cet article, nous verrons comment faire cela dans un programme cobol. Utilité? Ça dépend. La vérité est qu’étant capable de faire cela par JCL, je ne vois aucune raison de le faire dans un programme. Mais qui sait! Certains lecteurs pourront peut-être nous donner une idée de son utilisation pratique.
MERGE:
L’instruction MERGE en cobol sert à joindre deux fichiers en tenant compte de la clé par laquelle ils sont triés. C’est-à-dire que nous ne pouvons pas MERGE des fichiers désordonnés. Ce qu’il fera, c’est “mettre” les clés correspondantes ensemble dans le fichier de sortie.
Pour l’exemple, nous utiliserons : – 2 fichiers d’entrée avec les données à joindre. – 1 fichier temporaire où se produira la MERGE.
Les données des fichiers d’entrée pour notre exemple seront :
Fichier 1
Fichier 2
A B C
B C E
IDENTIFICATION DIVISION.
PROGRAM-ID.PRGMERGE.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
* Définition des fichiers
SELECT TABLE-MERGE ASSIGN TO DISK 'SORTWORK'.
SELECT TABLE-FICHIER1 ASSIGN TO FICHIER1.
SELECT TABLE-FICHIER2 ASSIGN TO FICHIER2.
DATA DIVISION.
FILE SECTION.
* Fichiers physiques
FD TABLE-FICHIER1
DATA RECORD IS FICHIER1.
01 FICHIER1.
05 FILLER PIC X(001).
FD TABLE-FICHIER2
DATA RECORD IS FICHIER2.
01 FICHIER2.
05 FILLER PIC X(001).
* Fichier temporaire
SD TABLE-MERGE
DATA RECORD IS ELEMENTO-MERGE.
01 ELEMENT-MERGE.
05 MERGE-CLE1 PIC X(001).
WORKING-STORAGE SECTION.
* Variable où nous enregistrerons le résultat de MERGE
01 VARIABLES.
05 WA-REGISTRE.
10 WA-AUX-CLE1 PIC X(001).
* Switch pour la boucle
01 SWITCH.
05 SW-FIN-TABLE-MERGE PIC X(001).
88 SI-FIN-TABLE-MERGE VALUE 'O'.
88 NO-FIN-TABLE-MERGE VALUE 'N'.
* Enregistrement de données après MERGE
01 WR-ELEMENT-MERGE.
05 WR-MERGE-CLE1 PIC X(001).
PROCEDURE DIVISION.
PERFORM 1000-INIT
PERFORM 2000-PROCESS
PERFORM 9000-FINAL
.
1000-INIT.
INITIALIZE VARIABLES
.
2000-PROCESS.
* Instruction MERGE
* Nous joignons FICHIER1 et FICHIER2 dans TABLE-MERGE par clé
* MERGE-CLE1
MERGE TABLE-MERGE ASCENDING KEY MERGE-CLE1
USING FICHIER1 FICHIER2
OUTPUT PROCEDURE 2100-PROCESS-SORTIE
* Dans OUTPUT PROCED nous utiliserons les informations déjà recueillies
IF SORT-RETURN NOT = ZEROS
DISPLAY 'ERREUR DANS LE MERGE:' SORT-RETURN
END-IF
.
2100-PROCESS-SORTIE.
* On passe du fichier temporaire au registre de sortie avec
* l'instruction RETURN
* On affiche les informations d'une variable définie dans
* le programme
SET NO-FIN-TABLE-MERGE TO TRUE
PERFORM UNTIL SI-FIN-TABLE-UNION
RETURN TABLE-MERGE INTO WR-ELEMENT-MERGE
AT END
SET SI-FIN-TABLE-MERGE TO TRUE
NOT AT END
MOVE WR-MERGE-CLE1 TO WA-AUX-CLE1
DISPLAY 'REGISTRE-> ' WA-REGISTRE
END-RETURN
END-PERFORM
.
9000-FINAL.
STOP RUN
.
RESULTAT :
REGISTRE-> A
B
B
C
C
E
Remarque : même si vous ne voyez aucun paragraphe “ouvrir le fichier”, “lire le fichier”, etc., cela ne signifie pas que nous avons perdu le FOCUS, c’est juste que ce n’est pas nécessaire !