L'algoritmo di fusione visto prima si può tradurre in un semplice programma in linguaggio COBOL.
Come già detto le strutture S1 e S2 e OUT in questo caso assumono la forma di tre file.
Il listato COBOL, ridotto ai minimi termini per semplicità ma comunque funzionante, è il seguente:
IDENTIFICATION DIVISION.
*--------------------------------------------------*
PROGRAM-ID. FUSIONE.
*--------------------------------------------------*
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
* FILE DI INPUT CONTENENTE LA STRUTTURA S1
SELECT S1 ASSIGN S1.
* FILE DI INPUT CONTENENTE LA STRUTTURA S2
SELECT S2 ASSIGN S2.
* FILE DI OUTPUT CONTENENTE LA FUSIONE S1+S2
SELECT OUT ASSIGN OUT.
*--------------------------------------------------*
DATA DIVISION.
FILE SECTION.
FD S1
LABEL RECORD IS STANDARD
RECORDING MODE IS F
BLOCK 0 RECORDS.
01 S1-REC.
05 S1-STRING PIC X.
FD S2
LABEL RECORD IS STANDARD
RECORDING MODE IS F
BLOCK 0 RECORDS.
01 S2-REC.
05 S2-STRING PIC X.
FD OUT
LABEL RECORD IS STANDARD
RECORDING MODE IS F
BLOCK 0 RECORDS.
01 OUT-REC PIC X.
*--------------------------------------------------*
WORKING-STORAGE SECTION.
*--------------------------------------------------*
*
01 KEY1 PIC X VALUE SPACES.
01 KEY2 PIC X VALUE SPACES.
*
*--------------------------------------------------*
PROCEDURE DIVISION.
*--------------------------------------------------*
P000-MAIN-LINE.
*
OPEN INPUT S1.
OPEN INPUT S2.
OPEN OUTPUT OUT.
READ S1 INTO KEY1 AT END MOVE HIGH-VALUE TO KEY1.
READ S2 INTO KEY2 AT END MOVE HIGH-VALUE TO KEY2.
DISPLAY 'INIZIO PROGRAMMA DI FUSIONE'
PERFORM UNTIL KEY1 = HIGH-VALUE AND KEY2 = HIGH-VALUE
IF KEY1 < KEY2
DISPLAY KEY1 ' < ' KEY2 ' - SCRIVO : ' KEY1
WRITE OUT-REC FROM KEY1
READ S1 INTO KEY1 AT END MOVE HIGH-VALUE TO KEY1
ELSE
IF KEY1 > KEY2
DISPLAY KEY1 ' > ' KEY2 ' - SCRIVO : ' KEY2
WRITE OUT-REC FROM KEY2
READ S2 INTO KEY2 AT END MOVE HIGH-VALUE TO KEY2
ELSE
WRITE OUT-REC FROM KEY1
DISPLAY KEY1 ' = ' KEY2 ' - SCRIVO : ' KEY1
READ S1 INTO KEY1 AT END MOVE HIGH-VALUE TO KEY1
READ S2 INTO KEY2 AT END MOVE HIGH-VALUE TO KEY2
END-IF
END-IF
END-PERFORM.
DISPLAY 'TERMINE PROGRAMMA DI FUSIONE'.
CLOSE S1.
CLOSE S2.
CLOSE OUT.
GOBACK.
*
P000-EXIT.
EXIT.
Nella PROCEDURE DIVISION è riportato l'algoritmo visto prima corredato di alcune DISPLAY per esporne in SYSOUT l'operato.
Un Job JCL di lancio può essere il seguente:
//SYSADMX JOB (12345678),SYSADM,MSGCLASS=H,
// MSGLEVEL=(1,1),CLASS=A,NOTIFY=&SYSUID
//STEP1 EXEC PGM=FUSIONE
//STEPLIB DD DSN=SYSADM.LIB.LOAD,DISP=SHR
//S1 DD DSN=SYSADM.PE000.S1,DISP=SHR
//S2 DD DSN=SYSADM.PE000.S2,DISP=SHR
//OUT DD DSN=SYSADM.PE000.OUT,
// DISP=(,CATLG,DELETE),SPACE=(CYL,(8,8),RLSE),
// DCB=(LRECL=1,RECFM=FB)
//SYSOUT DD SYSOUT=*
Come si vede in esso semplicemente dichiariamo i file elaborati dal programma e allochiamo il file prodotto in output.
Popoliamo i due files in input come segue:
S1 = 1,3,5,7,9
S2 = 2,4,6,7
E lanciamo il JCL.
Al termine dell'esecuzione il file OUT conterrà i valori:
OUT = 1,2,3,4,5,6,7,7,9
mentre in SYSOUT potremo vedere le DISPLAY poste nel programma:
********************************
INIZIO PROGRAMMA DI FUSIONE
1 < 2 - SCRIVO : 1
3 > 2 - SCRIVO : 2
3 < 4 - SCRIVO : 3
5 > 4 - SCRIVO : 4
5 < 6 - SCRIVO : 5
7 > 6 - SCRIVO : 6
7 = 7 - SCRIVO : 7
9 > 7 - SCRIVO : 7
9 < - SCRIVO : 9
TERMINE PROGRAMMA DI FUSIONE
********************************
Come già detto, questo è un programma minimale. Manca ad esempio la gestione degli errori in fase di I/O, tipicamente tramite FILE-STATUS ma rende bene l'idea dell'operato dell'algoritmo.
martedì 9 ottobre 2018
venerdì 5 ottobre 2018
Fusione, un algoritmo.
Con riferimento al post precedente, un algoritmo che realizzi la fusione fra due strutture dati potrebbe essere il seguente:
Supponiamo che le strutture S1 e S2 siano due file e che si voglia scrivere in output un nuovo file contenente l'unione dei due input.
L'idea di base è di memorizzare la chiave di fusione in una variabile "key1" per S1 e "key2" per S2 e lavorare sulle relazioni logiche che possono crearsi fra queste due variabili.
Supponiamo che le strutture S1 e S2 siano due file e che si voglia scrivere in output un nuovo file contenente l'unione dei due input.
L'idea di base è di memorizzare la chiave di fusione in una variabile "key1" per S1 e "key2" per S2 e lavorare sulle relazioni logiche che possono crearsi fra queste due variabili.
- Se key1 è minore di key2, S1 andrà in output e un nuovo valore di S1 sarà letto;
- Se key1 è maggiore di key2, S2 andrà in output e un nuovo valore di S2 sarà letto;
- Se key1 è uguale a key2, uno fra S1 e S2 andrà in output e un nuovo valore sia di S1 che di S2 sarà letto;
Questa serie di confronti andrà avanti fino a quando tutte le letture saranno completate.
Per gestire il caso, frequente, di file di grandezza diversa si avrà cura, nel caso uno dei due file termini prima dell'altro, di porre la chiave corrispondente ad un valore "tappo" (Tipicamente in COBOL si usa HIGH-VALUE).
In questo modo una delle due condizioni 1 e 2 sarà sempre verificata provocando lo scarico dell'altro file in output.
L'algoritmo precedente può essere espresso in pseudo-codifica nel modo seguente:
START
OPEN S1, S2,OUT;
READ S1 IN KEY1 AT END KEY1=HV;
READ S2 IN KEY2 AT END KEY2=HV;
PERFORM UNTIL KEY1=HV AND KEY2=HV
IF KEY1 < KEY2 THEN
WRITE OUT FROM S1;
READ S1 IN KEY1 AT END KEY1=HV;
ELSE
IF KEY1 > KEY2 THEN
WRITE OUT FROM S2;
READ S2 IN KEY2 AT END KEY2=HV;
ELSE
WRITE OUT FROM S1;
READ S1 IN KEY1 AT END KEY1=HV;
READ S2 IN KEY2 AT END KEY2=HV;
END-IF;
END-IF;
END-PERFORM;
CLOSE S1,S2,OUT
END
Iscriviti a:
Commenti (Atom)