Bienvenue dans la formation COBOL

Apprenez les bases du COBOL et développez vos compétences en programmation legacy avec une approche moderne.

Info : Ce module vous permet d’accéder rapidement aux contenus essentiels de la formation COBOL.
Retour au plan général

Utilisation de search et search all pour rechercher dans un tableau

En cobol, rechercher dans un tableau ne se fait pas “au hasard” : il existe des instructions dédiées.  SEARCH  parcourt un tableau de façon séquentielle (comme une lecture ligne par ligne), tandis que  SEARCH  ALL  effectue une recherche binaire (beaucoup plus rapide), mais avec une condition obligatoire : le tableau doit être trié sur une clé.

Tableaux Recherche Performance

Conceptualiser

Différences clés
 SEARCH  (séquentiel)
Le tableau est parcouru dans l’ordre, élément après élément. Cela fonctionne même si le tableau n’est pas trié, mais cela peut devenir lent si la table est grande.
 SEARCH  ALL  (binaire)
Le tableau est recherché par “découpage” (recherche binaire), très rapide. Condition incontournable : le tableau doit être trié sur une clé déclarée avec  ASCENDING  KEY  (ou  DESCENDING  KEY ).
Index et sécurité
Ces instructions s’appuient sur un index associé au tableau (déclaré via  INDEXED  BY ). Une bonne pratique consiste à contrôler la saisie (numérique ou non) avant de lancer une recherche.
Point de vigilance
 SEARCH  ALL  suppose un tableau trié. Si la table n’est pas triée, le résultat peut être faux (ou “non trouvé” alors que la valeur existe).

Opérer

Exemple exécutable

Le programme suivant contient un tableau de “clients” trié par code (clé numérique). Il demande un code à l’utilisateur, puis effectue : une recherche séquentielle ( SEARCH ) et une recherche binaire ( SEARCH  ALL ). Vous pouvez ainsi comparer la logique, tout en conservant un exemple simple et fonctionnel.

Fichier : demo-search.cbl
Cobol (format libre)

 >>SOURCE FORMAT FREE
 IDENTIFICATION DIVISION.
 PROGRAM-ID. DEMO-SEARCH.

 DATA DIVISION.
 WORKING-STORAGE SECTION.

 01 WS-I            PIC 9(2) VALUE 0.
 01 WS-CHERCHE-TXT   PIC X(5) VALUE SPACES.
 01 WS-CHERCHE       PIC 9(5) VALUE 0.

 01 WS-TROUVE-SEQ    PIC X VALUE "N".
 01 WS-TROUVE-BIN    PIC X VALUE "N".

 01 WS-TABLE-CLIENTS.
    05 WS-CLIENT
        OCCURS 5 TIMES
        ASCENDING KEY IS WS-CLIENT-CODE
        INDEXED BY IX-CLIENT.
        10 WS-CLIENT-CODE PIC 9(5) VALUE 0.
        10 WS-CLIENT-NOM  PIC X(20) VALUE SPACES.

 PROCEDURE DIVISION.
    PERFORM INIT-TABLE
    PERFORM AFFICHER-TABLE

    DISPLAY "Code client a rechercher (5 chiffres) : " WITH NO ADVANCING
    ACCEPT WS-CHERCHE-TXT

    IF WS-CHERCHE-TXT IS NUMERIC
        MOVE WS-CHERCHE-TXT TO WS-CHERCHE
    ELSE
        MOVE 0 TO WS-CHERCHE
        DISPLAY "Erreur : code non numerique (" WS-CHERCHE-TXT ")"
    END-IF

    PERFORM RECHERCHE-SEQ
    PERFORM RECHERCHE-BINAIRE

    DISPLAY "--- Recapitulatif ---"
    DISPLAY "Trouve (search)     : " WS-TROUVE-SEQ
    DISPLAY "Trouve (search all) : " WS-TROUVE-BIN

    STOP RUN.

 INIT-TABLE.
    MOVE 10001 TO WS-CLIENT-CODE(1)
    MOVE "DURAND" TO WS-CLIENT-NOM(1)
    MOVE 10005 TO WS-CLIENT-CODE(2)
    MOVE "MARTIN" TO WS-CLIENT-NOM(2)
    MOVE 10010 TO WS-CLIENT-CODE(3)
    MOVE "BERNARD" TO WS-CLIENT-NOM(3)
    MOVE 10020 TO WS-CLIENT-CODE(4)
    MOVE "THOMAS" TO WS-CLIENT-NOM(4)
    MOVE 10050 TO WS-CLIENT-CODE(5)
    MOVE "PETIT" TO WS-CLIENT-NOM(5).

 AFFICHER-TABLE.
    DISPLAY "--- Table clients (triee) ---"
    PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 5
        DISPLAY "[" WS-I "] code=" WS-CLIENT-CODE(WS-I) " nom=[" WS-CLIENT-NOM(WS-I) "]"
    END-PERFORM.

 RECHERCHE-SEQ.
    MOVE "N" TO WS-TROUVE-SEQ
    SET IX-CLIENT TO 1
    SEARCH WS-CLIENT
        AT END
            DISPLAY "Search : non trouve (" WS-CHERCHE ")"
        WHEN WS-CLIENT-CODE(IX-CLIENT) = WS-CHERCHE
            MOVE "Y" TO WS-TROUVE-SEQ
            DISPLAY "Search : trouve nom=[" WS-CLIENT-NOM(IX-CLIENT) "]"
    END-SEARCH.

 RECHERCHE-BINAIRE.
    MOVE "N" TO WS-TROUVE-BIN
    SEARCH ALL WS-CLIENT
        AT END
            DISPLAY "Search all : non trouve (" WS-CHERCHE ")"
        WHEN WS-CLIENT-CODE(IX-CLIENT) = WS-CHERCHE
            MOVE "Y" TO WS-TROUVE-BIN
            DISPLAY "Search all : trouve nom=[" WS-CLIENT-NOM(IX-CLIENT) "]"
    END-SEARCH.
Ce que fait  SEARCH  ALL  dans l’exemple
  • Effectue une recherche binaire (beaucoup plus rapide sur grande table)
  • Exige une clause de clé :  ASCENDING KEY  (ou  DESCENDING KEY )
  • Exige un tableau effectivement trié selon cette clé
  • Déclenche  AT END  si non trouvé
  • Positionne l’index sur l’élément trouvé, ce qui permet de lire les champs associés

 MOVE "N" TO WS-TROUVE-BIN
 SEARCH ALL WS-CLIENT
    AT END
        DISPLAY "Search all : non trouve"
    WHEN WS-CLIENT-CODE(IX-CLIENT) = WS-CHERCHE
        MOVE "Y" TO WS-TROUVE-BIN
        DISPLAY "Search all : trouve nom=[" WS-CLIENT-NOM(IX-CLIENT) "]"
 END-SEARCH.

Table non triée avec search all
Si vous remplissez la table dans un ordre quelconque (ex. 10020 avant 10010),  SEARCH  ALL  peut échouer. Solution : garantir le tri, ou utiliser  SEARCH  séquentiel.
Index non initialisé
Pour  SEARCH , si vous ne faites pas  SET ... TO 1 , vous risquez de démarrer au mauvais endroit. Solution : initialiser l’index à une valeur cohérente avant la recherche.
Saisie invalide
Un code non numérique doit être rejeté ou transformé en valeur neutre. Solution : lire en texte, tester IS NUMERIC, puis convertir.
Explorer : exercices
1) Ajoutez une colonne “statut” (ex.  PIC X(10) ) et affichez-la quand un client est trouvé.
2) Demandez un code et, s’il est trouvé, remplacez le nom par une nouvelle valeur.
3) Augmentez le tableau (ex. 20 éléments) et ajoutez un commentaire expliquant pourquoi  SEARCH  ALL  devient intéressant sur des grandes tables.
4) Modifiez volontairement l’ordre de remplissage (désordonner la table) et observez le comportement de  SEARCH  puis de  SEARCH  ALL .

↑ Haut