[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [volume] [parte]


Capitolo 574.   Tabelle

Il linguaggio COBOL offre la gestione di array attraverso la definizione di variabili multiple, all'interno di variabili strutturate (record); tuttavia, la denominazione usata nel COBOL per queste rappresentazioni dei dati è di tabella.

level-number  data-name-1

              [omissis]

                         /                                                           \
                         |               integer-2 TIMES                             |
                 OCCURS  <                                                           >
                 ¯¯¯¯¯¯  |  integer-1 TO integer-2 TIMES [DEPENDING ON data-name-3]  |
                         \            ¯¯                  ¯¯¯¯¯¯¯¯¯                  /
                                                                                      
                         .--  /              \                          --.           
                         |    |  ASCENDING   |                            |           
                         |    <  ¯¯¯¯¯¯¯¯¯   >  KEY IS  {data-name-4}...  |...        
                         |    |  DESCENDING  |                            |           
                         `--  \  ¯¯¯¯¯¯¯¯¯¯  /                          --'           
                                                                                      
                         [ INDEXED BY  {index-name-1}... ]                            
                           ¯¯¯¯¯¯¯                                                    
              [omissis] .

574.1   Dichiarazione di una tabella

Si dichiara che un campo è composto da più elementi dello stesso tipo aggiungendo in coda l'opzione OCCURS n TIMES. Lo schema sintattico completo dell'opzione è il seguente:

        /                                                           \
        |               integer-2 TIMES                             |
OCCURS  <                                                           >
¯¯¯¯¯¯  |  integer-1 TO integer-2 TIMES [DEPENDING ON data-name-3]  |
        \            ¯¯                  ¯¯¯¯¯¯¯¯¯                  /
                                                                     
        .--  /              \                          --.           
        |    |  ASCENDING   |                            |           
        |    <  ¯¯¯¯¯¯¯¯¯   >  KEY IS  {data-name-4}...  |...        
        |    |  DESCENDING  |                            |           
        `--  \  ¯¯¯¯¯¯¯¯¯¯  /                          --'           
                                                                     
        [ INDEXED BY  {index-name-1}... ]                            
          ¯¯¯¯¯¯¯

Le tabelle più semplici sono quelle che hanno un numero fisso di elementi. Si osservi l'esempio seguente:

000000 01  A.
000000     02  B        PIC 9999.
000000     02  C                        OCCURS 10 TIMES.
000000         03  D    PIC X(10).
000000         03  E    PIC 99          OCCURS  7 TIMES.
000000     02  F        PIC X(10).

Nell'esempio viene dichiarata una variabile strutturata denominata A, che si articola nelle variabili B, C e F. La variabile C è ripetuta per 10 volte e si articola ogni volta nella variabile D e nella variabile E. La variabile E si ripete per sette volte.

La variabile E è una tabella a due dimensioni, perché è inclusa nelle ripetizioni della variabile C, mentre la variabile C è una tabella a una sola dimensione.

È evidente che per fare riferimento ai valori contenuti nelle tabelle sia necessario utilizzare un indice.

L'opzione OCCURS si può utilizzare per tutte le variabili dichiarate con un numero di livello da 02 a 49. In pratica vengono esclusi i livelli 01 (record), 66 (usato per il raggruppamento delle variabili), 77 (usato esclusivamente per le variabili scalari) e 88 (nomi di condizione).

Lo standard del 1974 del linguaggio COBOL pone come limite un massimo di tre dimensioni per le tabelle.

574.2   Riferimento al contenuto di una tabella

Per fare riferimento a un elemento di una tabella, nelle istruzioni della divisione PROCEDURE DIVISION si usa una forma descritta dallo schema sintattico seguente:

data-name (subscript-1 [subscript-2 [subscript-3...]])

In pratica, si scrive il nome della variabile ripetuta, seguita dall'indice o dagli indici tra parentesi tonde. Il primo indice riguarda la prima dimensione, intesa come quella più esterna; l'ultimo riguarda l'annidamento più interno.

L'indice è un numero intero positivo che va da uno fino al massimo della dimensione che lo riguarda. Seguendo l'esempio apparso nella sezione precedente, E (1 7) rappresenta la settima occorrenza della variabile E nell'ambito della prima della variabile C. Pertanto, il nome da usare per indicare l'elemento è quello della variabile più interna che si vuole individuare, mentre gli indici partono dalla posizione più esterna.

Si noti che è convenzione comune inserire delle virgole per separare gli indici, anche se si tratta di una forma di rappresentazione facoltativa.

Viene mostrato un altro esempio di tabella a tre dimensioni:

000000 01  ENCICLOPEDIA.
000000     05  VOLUME                   OCCURS 10 TIMES.
000000         10  TITOLO-VOLUME            PIC X(30).
000000         10  PARTE                OCCURS 20 TIMES.
000000             15  TITOLO-PARTE         PIC X(30).
000000             15  CAPITOLO         OCCURS 30 TIMES.
000000                 20  TITOLO-CAPITOLO  PIC (30).
000000                 20  TESTO            PIC (200).

Si tratta di una variabile strutturata che serve a contenere delle informazioni su un'enciclopedia. L'elemento VOLUME (5) contiene le informazioni su tutto il volume quinto; l'elemento TITOLO-VOLUME (5) contiene il titolo del volume quinto; l'elemento TITOLO-PARTE (5, 3) contiene il titolo della terza parte del volume quinto; l'elemento TESTO (5, 3, 25) contiene il testo del venticinquesimo capitolo contenuto nella terza parte del quinto volume. Naturalmente, in questo esempio si intende che la numerazione delle parti ricominci da uno all'inizio di ogni volume; così si intende che all'inizio di ogni parte la numerazione dei capitoli riprenda da uno.

574.3   Indice

L'indice di una tabella può essere indicato attraverso una costante numerica, una variabile numerica a cui sia stato attribuito preventivamente un valore appropriato o attraverso un'espressione elementare che risulta in un numero intero appropriato.

Quando si usa una variabile per la gestione di un indice, è possibile ed è consigliabile che il tipo numerico di tale variabile sia INDEX. In pratica, nella sezione WORKING-STORAGE SECTION un indice potrebbe essere dichiarato come nell'esempio seguente, dove se ne vedono due, il primo, denominato INDICE, è dichiarato come variabile scalare di livello 77, il secondo, denominato INDICE-C, è sempre costituito da una variabile scalare, che però fa parte di una variabile strutturata:

000000 77  INDICE           USAGE IS INDEX.
000000
000000 01  A.
000000     02  B            PIC X(30).
000000     02  INDICE-C     USAGE IS INDEX.

Si può osservare che questo tipo di variabile numerica non prevede la definizione della sua dimensione che è stabilita invece dal compilatore, in base alle caratteristiche dell'elaboratore e del sistema operativo.

In alternativa, l'indice può essere dichiarato contestualmente alla dichiarazione della variabile ricorrente; in tal caso, il compilatore può aggiungere dei controlli tali da impedire che si possa assegnare alla variabile un valore al di fuori dell'ambito della dimensione della tabella:

000000 01  ENCICLOPEDIA.
000000     05  VOLUME                   OCCURS 10 TIMES
000000                                  INDEX IS IND-VOLUME.
000000         10  TITOLO-VOLUME            PIC X(30).
000000         10  PARTE                OCCURS 20 TIMES
000000                                  INDEX IS IND-PARTE.
000000             15  TITOLO-PARTE         PIC X(30).
000000             15  CAPITOLO         OCCURS 30 TIMES
000000                                  INDEX IS IND-CAPITOLO.
000000                 20  TITOLO-CAPITOLO  PIC (30).
000000                 20  TESTO            PIC (200).

Qui viene ripreso e modificato un esempio già apparso in una sezione precedente. La differenza consiste nell'assegnare l'indice a ogni variabile ricorrente. Pertanto si hanno gli indici: IND-VOLUME, IND-PARTE e IND-CAPITOLO.

Come accennato, si può fare riferimento a un elemento di una tabella indicando un indice costituito da un'espressione matematica elementare. Si parla in questo caso di indici relativi, perché si possono sommare o sottrarre dei valori a partire da una posizione di partenza. Per esempio, supponendo che la variabile I contenga il numero 15, l'elemento indicato come ELE (I - 4) corrisponderebbe alla notazione ELE (11); nello stesso modo, l'elemento indicato come ELE (I + 4) corrisponderebbe alla notazione ELE (19).

574.4   Tabelle di dimensione variabile

Teoricamente, è possibile dichiarare l'occorrenza di una variabile per una quantità variabile di elementi; si usa in tal caso la forma OCCURS m TO n TIMES. A seconda del compilatore, può essere obbligatorio, o facoltativo, specificare il nome di una variabile che controlla dinamicamente la quantità massima di elementi:

OCCURS  integer-1 TO integer-2 TIMES [DEPENDING ON data-name-3]
¯¯¯¯¯¯            ¯¯                  ¯¯¯¯¯¯¯¯¯

Viene mostrato l'esempio di un programma completo, che serve ad accumulare in una tabella alcuni dati personali. Sono previsti un massimo di 60 elementi e la quantità effettiva di elementi è controllata dalla variabile UTENTI-MAX:

000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID.   ELM1150.
000300 AUTHOR.       DANIELE GIACOMINI.
000400 DATE-WRITTEN. 2005-02-24.
000500*
000600 ENVIRONMENT DIVISION.
000700*
000800 DATA DIVISION.
000900*
001000 WORKING-STORAGE SECTION.
001100 01  RECORD-UTENTI.
001200     02  UTENTE           OCCURS 1 TO 60 TIMES
001300                          DEPENDING ON UTENTI-MAX
001400                          INDEXED BY IND-UTENTE.
001500         03  COGNOME      PIC X(30).
001600         03  NOME         PIC X(30).
001700         03  NOTA         PIC X(200).
001800 77  UTENTI-MAX           USAGE IS INDEX.
001900 77  EOJ                  PIC 9   VALUE ZERO.
002000 77  RISPOSTA             PIC XX.
002100*
002200 PROCEDURE DIVISION.
002300*------------------------- LIVELLO 0 -----------------------------
002400 MAIN.
002500     PERFORM INSERIMENTO-DATI
002600             VARYING IND-UTENTE FROM 1 BY 1
002700             UNTIL EOJ = 1.
002800     PERFORM SCANSIONE
002900             VARYING IND-UTENTE FROM 1 BY 1
003000             UNTIL IND-UTENTE > UTENTI-MAX.
003100*
003200     STOP RUN.
003300*------------------------- LIVELLO 1 -----------------------------
003400 INSERIMENTO-DATI.
003500     MOVE IND-UTENTE TO UTENTI-MAX.
003600     DISPLAY "INSERISCI IL COGNOME: ".
003700     ACCEPT COGNOME (IND-UTENTE).
003800     DISPLAY "INSERISCI IL NOME: ".
003900     ACCEPT NOME (IND-UTENTE).
004000     DISPLAY "INSERISCI UNA NOTA DESCRITTIVA: ".
004100     ACCEPT NOTA (IND-UTENTE).
004200*
004300     IF IND-UTENTE >= 60
004400       THEN
004500           MOVE 1 TO EOJ;
004600       ELSE
004700           DISPLAY "VUOI CONTINUARE? SI O NO",
004800           ACCEPT RISPOSTA;
004900           IF RISPOSTA = "SI"
005000             THEN
005100                 DISPLAY "OTTIMO!";
005200             ELSE
005300                 MOVE 1 TO EOJ.
005400*-----------------------------------------------------------------
005500 SCANSIONE.
005600     DISPLAY COGNOME (IND-UTENTE), " ",
005700             NOME (IND-UTENTE), " ",
005800             NOTA (IND-UTENTE).
005900*

574.5   Tabelle ordinate

Se si devono utilizzare i dati in una tabella per eseguire una ricerca al suo interno (utilizzando l'istruzione SEARCH nella divisione PROCEDURE DIVISION), se si può essere certi che le informazioni contenute siano ordinate secondo una certa chiave, lo si può specificare nella dichiarazione:

        /                                                           \
        |               integer-2 TIMES                             |
OCCURS  <                                                           >
¯¯¯¯¯¯  |  integer-1 TO integer-2 TIMES [DEPENDING ON data-name-3]  |
        \            ¯¯                  ¯¯¯¯¯¯¯¯¯                  /

        .--  /              \                          --.
        |    |  ASCENDING   |                            |
        |    <  ¯¯¯¯¯¯¯¯¯   >  KEY IS  {data-name-4}...  |...
        |    |  DESCENDING  |                            |
        `--  \  ¯¯¯¯¯¯¯¯¯¯  /                          --'

        [ INDEXED BY  {index-name-1}... ]
          ¯¯¯¯¯¯¯

La metavariabile data-name-4 dello schema sintattico rappresenta una variabile contenuta nell'elemento ricorrente; attraverso la parola chiave ASCENDING si intende dichiarare che la tabella è ordinata, lessicograficamente, in modo ascendente, secondo il contenuto di quella variabile, se invece si usa la parola chiave DESCENDING, si intende un ordinamento decrescente.

È possibile specificare più chiavi di ordinamento successive, nel caso si vogliano abbinare chiavi secondarie di ordinamento.

Sia chiaro che la tabella deve già risultare ordinata secondo le chiavi specificate, altrimenti le istruzioni SEARCH della divisione PROCEDURE DIVISION danno risultati errati o falliscono semplicemente. Naturalmente, all'interno del programma è possibile prevedere un procedimento di riordino, da eseguire prima di utilizzare delle istruzioni SEARCH.

L'esempio seguente mostra l'indicazione della chiave di ordinamento, costituita precisamente dalla variabile COGNOME, che deve risultare ascendente in fase di ricerca:

001000 WORKING-STORAGE SECTION.
001100 01  RECORD-UTENTI.
001200     02  UTENTE           OCCURS 1 TO 60 TIMES
001300                          DEPENDING ON UTENTI-MAX
001350                          ASCENDING KEY IS COGNOME
001400                          INDEXED BY IND-UTENTE.
001500         03  COGNOME      PIC X(30).
001600         03  NOME         PIC X(30).
001700         03  NOTA         PIC X(200).
001800 77  UTENTI-MAX           USAGE IS INDEX.

574.6   Scansione delle tabelle

Il linguaggio COBOL prevede un'istruzione apposita per facilitare la scansione delle tabelle. Si tratta di SEARCH, che ha due modalità di funzionamento, a seconda che si voglia eseguire una ricerca sequenziale o una ricerca binaria. Naturalmente, la ricerca sequenziale si presta alla scansione di una tabella i cui dati non sono ordinati, mentre nel secondo caso devono esserlo.

Viene mostrato l'esempio di un programma completo che inizia con l'inserimento di dati all'interno di una tabella, quindi esegue una ricerca sequenziale al suo interno:

000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID.   TEST-SEARCH.
000300 AUTHOR.       DANIELE GIACOMINI.
000400 INSTALLATION. NANOLINUX IV,
000500               OPENCOBOL 0.31,
000600 DATE-WRITTEN. 2005-03-12.
000700*
000800 ENVIRONMENT DIVISION.
000900*
001000 DATA DIVISION.
001100*
001200 WORKING-STORAGE SECTION.
001300 01  RECORD-UTENTI.
001400     02  UTENTE           OCCURS 60 TIMES
001500                          INDEXED BY IND-UTENTE.
001600         03  COGNOME      PIC X(30).
001700         03  NOME         PIC X(30).
001800         03  NOTA         PIC X(200).
001900 77  EOJ                  PIC 9   VALUE ZERO.
002000 77  RISPOSTA             PIC XX.
002100 77  RICERCA              PIC X(30).
002200*
002300 PROCEDURE DIVISION.
002400*------------------------- LIVELLO 0 -----------------------------
002500 MAIN.
002600     PERFORM INSERIMENTO-DATI
002700             VARYING IND-UTENTE FROM 1 BY 1
002800             UNTIL EOJ = 1.
002900     MOVE 0 TO EOJ.
003000     PERFORM SCANSIONE UNTIL EOJ = 1.
003100*
003200     STOP RUN.
003300*------------------------- LIVELLO 1 -----------------------------
003400 INSERIMENTO-DATI.
003500     DISPLAY IND-UTENTE, " INSERISCI IL COGNOME: ".
003600     ACCEPT COGNOME (IND-UTENTE).
003700     DISPLAY IND-UTENTE, " INSERISCI IL NOME: ".
003800     ACCEPT NOME (IND-UTENTE).
003900     DISPLAY IND-UTENTE, " INSERISCI UNA NOTA DESCRITTIVA: ".
004000     ACCEPT NOTA (IND-UTENTE).
004100*
004200     IF IND-UTENTE >= 60
004300       THEN
004400           MOVE 1 TO EOJ;
004500       ELSE
004600           DISPLAY "VUOI CONTINUARE? SI O NO",
004700           ACCEPT RISPOSTA;
004800           IF RISPOSTA = "SI"
004900             THEN
005000                 NEXT SENTENCE;
005100             ELSE
005200                 MOVE 1 TO EOJ.
005300*-----------------------------------------------------------------
005400 SCANSIONE.
005500     DISPLAY "INSERISCI IL COGNOME DA CERCARE:".
005600     ACCEPT RICERCA.
005700     IF RICERCA = SPACES
005800       THEN
005900           MOVE 1 TO EOJ;
006000       ELSE
006100           SET IND-UTENTE TO 1,
006200           SEARCH UTENTE
006300                 AT END
006400                       DISPLAY "IL COGNOME CERCATO ",
006500                               "NON SI TROVA NELLA TABELLA: ",
006600                               QUOTE RICERCA QUOTE;
006700                 WHEN COGNOME (IND-UTENTE) = RICERCA
006800                     DISPLAY "IL COGNOME ", RICERCA,
006900                             "SI TROVA NELLA POSIZIONE ",
007000                             IND-UTENTE.
007100*

Nell'esempio sono evidenziate le righe in cui si dichiara la tabella e quelle che eseguono la scansione. Si deve osservare che prima dell'istruzione SEARCH, l'indice deve essere collocato manualmente nella posizione iniziale.

L'esempio seguente mostra una variante del programma già descritto, in cui si vuole eseguire una ricerca binaria. Perché la ricerca possa avere successo, la tabella deve essere dichiarata con una dimensione variabile di elementi, inoltre non è più necessario impostare il valore iniziale dell'indice, prima della scansione.

000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID.   TEST-SEARCH-KEY.
000300 AUTHOR.       DANIELE GIACOMINI.
000400 INSTALLATION. NANOLINUX IV,
000500               OPENCOBOL 0.31,
000600 DATE-WRITTEN. 2005-03-12.
000700*
000800 ENVIRONMENT DIVISION.
000900*
001000 DATA DIVISION.
001100*
001200 WORKING-STORAGE SECTION.
001300 01  RECORD-UTENTI.
001400     02  UTENTE           OCCURS 1 TO 60 TIMES
001500                          DEPENDING ON UTENTI-MAX
001600                          ASCENDING KEY IS COGNOME
001700                          INDEXED BY IND-UTENTE.
001800         03  COGNOME      PIC X(30).
001900         03  NOME         PIC X(30).
002000         03  NOTA         PIC X(200).
002100 77  UTENTI-MAX           USAGE IS INDEX.
002200 77  EOJ                  PIC 9   VALUE ZERO.
002300 77  RISPOSTA             PIC XX.
002400 77  RICERCA              PIC X(30).
002500*
002600 PROCEDURE DIVISION.
002700*------------------------- LIVELLO 0 -----------------------------
002800 MAIN.
002900     PERFORM INSERIMENTO-DATI
003000             VARYING IND-UTENTE FROM 1 BY 1
003100             UNTIL EOJ = 1.
003200     MOVE 0 TO EOJ.
003300     PERFORM SCANSIONE UNTIL EOJ = 1.
003400*
003500     STOP RUN.
003600*------------------------- LIVELLO 1 -----------------------------
003700 INSERIMENTO-DATI.
003800     MOVE IND-UTENTE TO UTENTI-MAX.
003900     DISPLAY IND-UTENTE, " INSERISCI IL COGNOME: ".
004000     ACCEPT COGNOME (IND-UTENTE).
004100     DISPLAY IND-UTENTE, " INSERISCI IL NOME: ".
004200     ACCEPT NOME (IND-UTENTE).
004300     DISPLAY IND-UTENTE, " INSERISCI UNA NOTA DESCRITTIVA: ".
004400     ACCEPT NOTA (IND-UTENTE).
004500*
004600     IF IND-UTENTE >= 60
004700       THEN
004800           MOVE 1 TO EOJ;
004900       ELSE
005000           DISPLAY "VUOI CONTINUARE? SI O NO",
005100           ACCEPT RISPOSTA;
005200           IF RISPOSTA = "SI"
005300             THEN
005400                 NEXT SENTENCE;
005500             ELSE
005600                 MOVE 1 TO EOJ.
005700*-----------------------------------------------------------------
005800 SCANSIONE.
005900     DISPLAY "INSERISCI IL COGNOME DA CERCARE:".
006000     ACCEPT RICERCA.
006100     IF RICERCA = SPACES
006200       THEN
006300           MOVE 1 TO EOJ;
006400       ELSE
006600           SEARCH ALL UTENTE
006700                 AT END
006800                       DISPLAY "IL COGNOME CERCATO ",
006900                               "NON SI TROVA NELLA TABELLA: ",
007000                               QUOTE RICERCA QUOTE;
007100                 WHEN COGNOME (IND-UTENTE) = RICERCA
007200                     DISPLAY "IL COGNOME ", RICERCA,
007300                             "SI TROVA NELLA POSIZIONE ",
007400                             IND-UTENTE.
007500*

La ricerca binaria richiede che gli elementi della tabella siano ordinati in base alla chiave primaria; pertanto, si presume che l'inserimento dei cognomi avvenga tenendo conto dell'ordine lessicografico.

Appunti di informatica libera 2007.02 --- Copyright © 2000-2007 Daniele Giacomini -- <daniele (ad) swlibero·org>


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome tabelle_2.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico]

Valid ISO-HTML!

CSS validator!