Les chaines de caractères sont tellement classiques qu’on ne peut pas passer à côté, on les a déjà beaucoup utilisées mais vous ne connaissez pas encore tout ce qu’il est possible de faire !
Afin de condenser un peu les codes donnés, je ne vais pas vous redonner les plages d’affichage et de saisie à chaque fois, c’est à vous de les créer maintenant, vous devriez en être capable.
Déclaration et caractéristiques
Comme vous le savez maintenant, les chaines de caractères se déclarent de la manière suivante :
* En-tête...
WORKING-STORAGE SECTION.
77 chaine PIC x(int longueur).
Les constantes
On va parler un peu des constantes. Comme les autres langages, Cobol peut en tirer parti. Rappelons-le, le principe d’une constante est que sa valeur est constante à travers notre code.
* En-tête...
WORKING-STORAGE SECTION.
78 ma-constante VALUE 'Ma chaine de caracteres qui ne change jamais'.
Comme vous le voyez, nos constantes sont déclarées en 78, et non en 77 comme les autres variables. Ensuite comme d’habitude, le nom suivi du mot-clé VALUE
puis notre chaîne entre apostrophes (ou guillemets simples).
Je ne vous en ai pas encore parlé pour ne pas vous trop vous bourrer la tête d’un coup, mais une constante ne contient pas nécessairement une chaîne de caractères. On peut y mettre un chiffre comme ceci :
* En-tête...
WORKING-STORAGE SECTION.
78 tva VALUE 19.6.
Pour afficher la valeur d’une constante, il suffit d’utiliser DISPLAY
.
Comparaison de chaînes
J’aimerais vous dire un petit mot sur les comparaisons. Il vous arrivera peut-être de vouloir comparer des chaînes de caractères entre elles de cette manière :
IF ch1 = ch2 THEN
DISPLAY 'Chaines identiques'
ELSE
DISPLAY 'Chaines differentes'
END-IF.
C’est tout à fait possible, et cela ne dépend pas de la longueur physique que vous avez choisie lors de la déclaration de vos variables, mais bien du contenu de celles-ci.
Affectation
Nous n’en avons jamais parlé clairement, mais l’attribution d’une valeur dans une variable de type string (chaîne de caractères) se fait via le mot clé MOVE
:
MOVE 'Ma chaine' TO str.
Mais vous pouvez également copier le contenu d’une variable pour le mettre dans une autre :
MOVE str1 TO str2.
MOVE constante TO str.
Manipulations avancées
La concaténation
Comme tous les langages, il est possible de mettre des chaînes de caractères bout à bout pour former une nouvelle chaîne. Dans un premier temps, on va déclarer les variables que l’on va utiliser :
77 ch1 PIC x(20) VALUE 'J''aime'.
77 ch2 PIC x(20) VALUE 'le Cobol !'.
77 ch3 PIC x(40).
Ensuite, on va simplement les mettre les unes à côté des autres :
STRING ch1 ch2 INTO ch3.
Ce qui va vous retourner :
J'aime le Cobol !
Si vous avez pris les mêmes valeurs que moi, vous avez sûrement remarqué qu’il y a beaucoup d’espaces entre nos 2 mots. Ceci est dû à la taille que l’on a choisie lors de la déclaration de nos variables ; si vous diminuez la taille de ch1 à 10, il y aura moins d’espaces entre les mots.
Vous pouvez également restreindre vos concaténations en choisissant des caractères qui vont délimiter vos chaînes. Voyons cela avec un exemple :
STRING ch1 ch2 DELIMITED ' ' INTO ch3.
Ici j’ai choisi de délimiter les chaines par leur espace, donc dès qu’il y a un espace dans une des parties, on passe à la suivante à concaténer, le résultat sera :
J'aime le
Comme il y a un espace entre "le" et "Cobol !" alors la chaîne est coupée !
Le contenu de DELIMITED
est sensible à la casse, donc faites attention !
Il est aussi possible de connaître la longueur de la nouvelle chaîne, on va donc ajouter une nouvelle variable numérique :
77 ptr PIC 99.
*...
MOVE 1 TO ptr.
STRING ch1 ch2 DELIMITED 'C' INTO ch3 POINTER ptr.
Lors de l’affichage de ptr
le résultat obtenu est :
Nouvelle chaine : j'aime le
Valeur de ptr : 14
En réalité POINTER
ne va pas compter uniquement les caractères normaux mais aussi les espaces. Donc si on compte la longueur de ch1 plus la longueur de ch2 jusqu’au "C" inclus, le résultat est donc 14 (10 + 4).
Les structures en Cobol sont considérées comme des chaines de caractères. Cette chaine étant le résultat de la concaténation de toutes les variables de la structure.
La dé-concaténation
Comme on peut concaténer, l’idéal c’est de pouvoir faire l’inverse, et c’est ce que l’on va faire avec l’aide de UNSTRING
! La syntaxe est très proche de celle de tout à l’heure :
UNSTRING chaineComplete DELIMITED ' ' INTO chaine1 chaine2 chaineN
Vous pouvez également appliquer les mêmes opérations avec la clause POINTER
.
Test booléen
Vous pouvez également faire d’autres choses, comme les tests booléens pour tester le contenu de votre chaîne. On peut par exemple savoir si la chaîne ne contient que du numérique, de l’alphabétique en majuscule, en minuscule, etc…
IF maChaine ALPHABETIC THEN
* Si la chaine ne contient que des lettres et des espaces
END-IF.
IF maChaine NUMERIC THEN
* Si la chaine ne contient que des chiffres et un signes
END-IF.
IF maChaine ALPHABETIC-UPPER THEN
* Si la chaine ne contient que des lettres en majuscules et des espaces
END-IF.
IF maChaine ALPHABETIC-LOWER THEN
* Si la chaine ne contient que des lettres en minuscules et des espace
END-IF.
Vous pouvez également ajouter la clause NOT
juste après le nom de la variable testée, comme ceci :
IF maChaine NOT ALPHABETIC THEN
* Si la chaine ne contient pas que des lettres et des espaces
END-IF.
* ...
Quelques fonctions
REVERSE
Cette fonction permet d’inverser l’ordre des lettres dans une chaîne de caractères :
INITIALIZE ch1 ch2.
MOVE FUNCTION REVERSE (chaine1) TO chaine2.
Ici, j’ai simplement mis le contenu inversé de chaine1 dans chaine2. Mais j’aurais pu mettre le contenu de chaine1 dans chaine2 pour éviter de passer par une variable intermédiaire.
Cette fonction peut toujours vous être utile si on vous demande de regarder si un mot est un palindrome, comme kayak…
NUMVAL
NUMVAL
permet d’effectuer une sorte de cast à partir d’une chaîne de caractères vers une valeur numérique. Car comme vous pouvez vous en douter, effectuer des calculs via COMPUTE
est impossible avec une chaîne de caractères, cette fonction va le rendre possible d’une certaine manière !
MOVE 42 TO chaine.
INITIALIZE entier.
MOVE FUNCTION NUMVAL (chaine) TO entier.
Donc entier prendra bien la valeur numérique représentée dans la variable chaine.
MIN/MAX
Celle-ci permet de récupérer le minimum ou le maximum d’une chaîne. Autrement dit, vous allez passer une liste de chaînes à une des deux fonctions et elle va vous retourner le minimum ou le maximum selon l’ordre alphabétique.
77 ch1 PIC x(20) VALUE 'abc'.
77 ch2 PIC x(20) VALUE 'abcd'.
77 ch3 PIC x(20).
* ...
INITIALIZE ch3.
MOVE FUNCTION MAX (ch2 ch1) TO ch3.
Si on affiche le contenu de ch3 avec cet exemple, c’est "abcd" qui sera affiché car c’est la plus grande des deux valeurs. Si on avait utilisé MIN
, ce serait "abc" qui aurait été affiché.
LENGTH
Si vous êtes un développeur aguerri, vous devriez connaître cette fonction qui permet de récupérer la longueur d’une chaîne de caractères. Vous pourriez être tenté d’utiliser la fonction LENGTH
, ce qui est normal.
Mais il y a un piège ! Je m’explique :
IDENTIFICATION DIVISION.
PROGRAM-ID. fonction.
WORKING-STORAGE SECTION.
01 mot PIC A(30).
01 nbLettres PIC 99.
SCREEN SECTION.
01 plg-aff-titre.
02 BLANK SCREEN.
02 LINE 1 COL 10 'Fonction LENGTH.'.
01 plg-saisie.
02 LINE 5 COL 1 'Taper un mot : '.
02 PIC A(30) TO mot REQUIRED.
01 plg-res.
02 LINE 8 COL 1 'Le nombre de lettres du mot est : '.
02 PIC 99 FROM nbLettres.
PROCEDURE DIVISION.
DISPLAY plg-aff-titre plg-saisie.
ACCEPT plg-saisie.
MOVE FUNCTION LENGTH (mot) TO nbLettres.
DISPLAY plg-res.
GOBACK.
Fonction LENGTH
Taper un mot : programmation
Le nombre de lettres du mot est : 30
Quoi ?! C’est quoi ce résultat ?!
Eh bien voilà, l’utilisateur entre le mot "programmation". Le résultat est 30, alors que ce mot contient 13 lettres…
D’abord, on a déclaré une variable mot pouvant contenir jusqu’à 30 caractères. Donc, c’est comme si on avait un tableau de 30 cases contenant que des cases vides.
Ensuite, l’utilisateur a saisi un mot de 13 caractères. Voici donc ce qui se passe, le mot est stocké dans le tableau, mais toutefois, il reste des cases vides.
On a donc, le mot PROGRAMMATION contenu dans les cases de 1 à 13. Puis, des blancs de la case 14 à 30. En fait la fonction LENGTH
donne la valeur de la longueur totale de la chaîne y compris les blancs.
Alors dans ce cas, pourquoi avoir créée une telle fonction ? Je ne sais pas !
Il existe aussi l’instruction LENGTH OF
qui fait la même chose que la fonction LENGTH
.
Mais alors il est impossible de connaître la taille réelle d’une chaîne de caractères ?
Bien sûr ! Il suffit d’utiliser l’instruction INSPECT
qui permet entre autres de compter le nombre de caractères d’une chaîne.
Voici un exemple dans un programme.
IDENTIFICATION DIVISION.
PROGRAM-ID.LongMot.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 chaine PIC x(50).
01 nb PIC 99.
SCREEN SECTION.
01 plg-aff-titre.
02 BLANK SCREEN.
02 LINE 1 COL 20 'Longueur d''un mot'.
01 plg-saisie.
02 LINE 4 COL 1 'Entrez un mot : '.
02 PIC X(50) TO chaine REQUIRED.
01 plg-res.
02 LINE 6 COL 1 'La longueur du mot est: '.
02 PIC 99 FROM nb.
PROCEDURE DIVISION.
INITIALIZE nb
DISPLAY plg-aff-titre plg-saisie.
ACCEPT plg-saisie.
INSPECT chaine TALLYING nb FOR CHARACTERS BEFORE SPACE
DISPLAY plg-res
GOBACK.
END PROGRAM LongMot.
La ligne importante de ce programme est bien sûr celle-ci : INSPECT chaine TALLYING nb FOR CHARACTERS BEFORE SPACE
.
L’instruction va compter tous les caractères du mot un à un, et s’arrêter dès le premier espace qu’il aura trouvé. C’est à cela que sert la commande FOR CHARACTERS BEFORE SPACE
. La clause TALLYING
permet de placer le résultat de l’instruction dans la variable nb.
Donc pour synthétiser un peu tout ça, voici ce qu’il faut retenir :
- la fonction
LENGTH
ne permet pas de connaitre la "vraie" longueur d’une chaine, mais sa longueur physique ; - les constantes se déclarent en 78, et non en 77 ;
- il est possible de comparer des chaines dans vos conditions.