Les chaines de caractères

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 ?! o_O

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 ! :D

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.