A COBOL programozási nyelv

Példaprogramok

Árunyilvántartás

Az alábbi egyszerű Cobol program egy "aru" file-ból kiolvassa az árucikkeket, a "forgalom" file-ból pedig a forgalmat, és meghatározza az összes forgalmat. A fájlok sorainak szerkezete a következő:

DATA.COB:

000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. DataProgram.
000300*
000400 ENVIRONMENT DIVISION.
000500 INPUT-OUTPUT SECTION.
000600 FILE-CONTROL.
000700 SELECT ARU
000800 ASSIGN TO arufile
000900 ORGANIZATION IS LINE SEQUENTIAL.
001000 SELECT FORGALOM
001100 ASSIGN TO forgfile
001200 ORGANIZATION IS LINE SEQUENTIAL.
001300*
001400 DATA DIVISION.
001500 FILE SECTION.
001600 FD ARU.
001700 01 ARU-REKORD.
001800 02 CIKKSZAM PIC 9(5).
001900 02 ARUNEV PIC X(40).
002000 02 EGYSEGAR PIC 9(6).
002100 FD FORGALOM.
002200 01 FORGALOM-REKORD.
002300 02 CIKKSZAM PIC 9(5).
002400 02 MENNYISEG PIC 9(5)V9(2).
002500 WORKING-STORAGE SECTION.
002600 01 OSSZEG PIC 9(10).
002700 01 AR PIC 9(10).
002800*
002900 PROCEDURE DIVISION.
003000 MOVE 0 TO OSSZEG.
003100 OPEN INPUT ARU.
003200 ARUOLVAS.
003300 READ ARU AT END GO TO TERM-ARUOLVAS.
003400 OPEN INPUT FORGALOM.
003500 FORGALOMOLVAS.
003600 READ FORGALOM AT END GO TO TERM-FORGALOMOLVAS.
003700 IF CIKKSZAM OF ARU-REKORD = CIKKSZAM OF FORGALOM-REKORD THEN
003800 MULTIPLY EGYSEGAR OF ARU-REKORD BY MENNYISEG OF FORGALOM-REKORD GIVING AR
003900 ADD AR TO OSSZEG
004000 END-IF.
004100 GO TO FORGALOMOLVAS.
004200 TERM-FORGALOMOLVAS.
004300 CLOSE FORGALOM.
004400 GO TO ARUOLVAS.
004500 TERM-ARUOLVAS.
004600 CLOSE ARU.
004700 DISPLAY "Vasarlasok osszerteke: ".
004800 DISPLAY OSSZEG.
004900 STOP RUN.

A fenti program Fujitsu Cobol85 fordítóval készült. A futtatáskor kell meghatározni a (erre alkalmas ablak megjelenik) a 8. sorban lévő "arufile" és a 11. sorban lévő "forgfile" nevű "változók" értékét (meg kell adni a file-ok elérési útját).

Táblázatok

A legtöbb programpzási nyelvben az kifejezést ismétlődő vagy gyakori előfordulású, data-items-ekre használjuk. Erre a Cobol a

kifejezést használja, a következőkben bemutatjuk, hogy miért hasznos a table vagy array struktúra egyes problémák megoldására.

Célok: Kiderüljön, hogy

Bevezetés

Kezdjük a táblázatok tárgyalását és kezelését, megvizsgálva egy általános programozási probléma szemszögéből. Tegyük fel, hogy az a feladatunk, hogy írjunk egy programot, amely összegzi az emberek által befizetett adókat az egész országban. Az adatokat egy olyan fileből kapjuk amely tartalmazza az adóra kifizetett összeget az adozók által az egész országban. A TexFile egy szekvenciális file amely a PAYENum-ot követi és ennek az adatait.

01 TaxRec.
88 EndOfTaxFile VALUE HIGH-VALUES.
02 PAYENum PIC 9(8)
02 CountyCode PIC 99.
02 TaxPaid PIC 9(7)V99.

A program végrehajtás nagyon egyszerű. Amit csinálnunk kell, az az hogy beállítunk egy változót, amely értéke az összadó majd utána hozzáadjuk a TaxPaid-et minden recordból a TaxTotal-ba. A következő programrészlet ezt mutatja.

PROCEDURE DIVISION.
Begin.
OPEN INPUT TaxFile
READ TaxFile
AT END SET EndOfTaxFile TO TRUE
END-READ
PERFORM UNTIL EndOfTaxFile
ADD TaxPaid TO TaxTotal
READ TaxFile
AT END SET EndOfTaxFile TO TRUE
END-READ
END-PERFORM.
DISPLAY "Total taxes are ", TaxTotal
CLOSE TaxFile
STOP RUN.

Mi van ha nem az egész ország összadóját akarjuk megadni hanem ennek csak egy részét? Hogyan lehet ezt megoldani?

Egyik közeledés a problémához hogy készítünk egy megyei adóbevallást (County Tax Report) és megyekód szerint rendezzük a file-t (CountyCode). Ez pedig egy egyszerű problémához vezet. Soroljuk fel a megye minden rekordját, adjuk meg az eredményt majd lépjünk a következőre. Azonban a TaxFile több millió rekordot tartalmaz, amely részben lassú és sok lemezműveletet eredméynez. Utolsó látogatás szerint redezzük a file-t.

Van más mód a probléma megoldására? Igen!

A következő megoldás, amit elfogathatunk, az hogy 26 változót hozunk létre, hogy a megyei össz adót meghatározzuk. Utána a programban használhatunk egy EVALUATE megállapítást, hogy hozzáadhassuk a TaxPaid-et hogy meghatározzuk az összeget.

EVALUATE CountyCode
WHEN 1 ADD TaxPaid TO County1TaxTotal
WHEN 2 ADD TaxPaid TO County2TaxTotal
WHEN 3 ADD TaxPaid TO County3TaxTotal
..... 23 more WHEN branches
END-EVALUATE

De ez a megoldás nem tökéletes. Kell legyen egy WHEN águnk hogy eljárhassunk minden megyében és kell legyen 26 változónk hogy megállapíthassuk az összadót, és amikor ki akarjuk nyomtatni az eredményt, 26 DISPLAY megállapításunk kell legyen úgy mint:

DISPLAY "County 1 total is ", County1TaxTotal
DISPLAY "County 2 total is ", County2TaxTotal
DISPLAY "County 3 total is ", County3TaxTotal
..... 23 more DISPLAY statements

De a fenti megoldás a jó megoldás azon részét tartalmazza, amely a legkielégítőbb választ nyújtja nekünk. Érdekes észrevétel, hogy minden WHEN ág eljárása pontosan ugyan az. A TaxPaid-et hozzáadjuk a particular county total változójához. Visszaállíthatnánk mind a 26 WHEN ágat egyetlen állítással ha általánosíthatnánk valahogy úgy, hogy például: ADD the TaxPaid To the County Total location indicated by theCounty Code (add hozzá a TaxPaid-et a County Totalhoz)

Van még valami érdekesség amit megjegyezhetünk a 26 változóról: Mindegyiknek pontosan ugyan az a PICTURE-e és többé-kevésbé mindnek ugyan az a neve - CountyTaxTotal. Az egyetlen mód ahogy különbséget teszünk egy County1TaxTotal és egy másik között, hogy hozzáírunk egy számot mindegyikhez. például: County1TaxTotal, County2TaxTotal stb...

Amikor változók csoportját látjuk, melyeknek mind ugyan az a nevük és leírásuk és csak annyi a különbség egyik és a másik között, hogy néhány szám a névhez van adva, akkor lerí róla, hogy táblázat alapú megoldás szükséges.

Egy táblázatot úgy adhatunk meg, hogy a memória helyeket egymásután definiáljuk, amelyeknek mind ugyanaz a neve és amelyeket egyedi módon adunk meg azon névvel és helyzete alapján a sorban. A helyzeti indexet "subscript"-nek, és a táblázat egyedi összetevőit "elements"-eknek nevezzük.

A táblázatoknak a következő atribútumai vannak:

Tábla deklarálása

A COBOL-ban egy táblázatot úgy határozunk meg, hogy definiáljuk egyetlen elem (komponens) típusát (vagy strukturáját) a táblázatban és utána meghatározzuk a data-itemet amely x-szer ismétlődhet. Jelenleg a CountyTaxTable-t a következőképp határozzuk meg:

01 CountyTaxTable.
02 CountyTax PIC 9(8)V99 OCCURS 26 TIMES.

A CuntyTaxTable-t diagramm szerűen is ábrázolhatjuk, ahogy lent van. A táblázat minden elemének neve CountyTax és utalhatunk egy bizonyosra, ezt a nevet használva, egy INTEGER értékkel követve a táblázat celláiban. Így hát a CountyTax(2) a táblázat második elemére utal és CountyTax(23) pedig a 23-dik egységre. De amikor egy bizonyos elemre gondolunk, akkor nem kell numerikus kifejezést használnunk. Bármit használhatunk, ami 1 és a táblázat maximum szélessége között helyezkedik el. Még egy sima aritmetikus kifejezést is.

MOVE 10 TO CountyTax(3)
ADD TaxPaid TO CountyTax(CountyCode)
ADD TaxPaid TO CountyTax(CountyCode + 1)
ADD TaxPaid TO CountyTax(CountyCode - 2)
A County Tax Report Program

A County Tax Report előállításának problémájára vonatkozó megoldás az, hogy olyan táblázatot használunk, mely minden County-nak nyilvántartja az össz Tax-ét és hogy CountyCode-ot használunk, hogy a táblázat pontos elemét kiválaszthassuk.

Mikor rájövünk, hogy tudjuk a táblázatot használni, hogy a county tax totalokat megőrizzük, és hogy használhatjuk a CountyCode-okat a táblázat indexeként, a probléma leegyszerűsödik.

A program PROCEDURE DIVISION-ja, amely a Tax file-t olvassa a tax totalokat felhalmozza minden countyban és megadja a tax total-okat, ahogy alább meg van adva:

PROCEDURE DIVISION.
Begin.
OPEN INPUT TaxFile
READ TaxFile
AT END SET EndOfTaxFile TO TRUE
END-READ
PERFORM UNTIL EndOfTaxFile
ADD TaxPaid TO CountyTax(CountyCode)
READ TaxFile
AT END SET EndOfTaxFile TO TRUE
END-READ
END-PERFORM
PERFORM VARYING Idx FROM 1 BY 1
UNTIL Idx GREATER THAN 26
DISPLAY "County ", CountyCode
" tax total is " CountyTax(Idx)
END-PERFORM
CLOSE TaxFile
STOP RUN.

Amikor a fenti program a felhalmozott egész adót mutatja, ahelyett, hogy egy county name-et adna, egy county code-ot fog adni. Ezzel az a probléma, hogy ha a felhasználó erről beszámolót akar készíteni, emlékezni kell, hogy melyik kód, melyik megyét jelenti. Egy természetes közegben nem mutathatod a felhasználónak ezt a programot ebben a formájában. A megye neveket meg kell jelenítenie. Hogy csinálhatjuk meg mindezt?

Egy táblázat alapú megoldás

Egyik lehetőség az lenne, hogy használjunk egy EVALUATE-et, hogy megvizsgáljuk a CountyCode-okat, és utána megjelenítjük a közelítő üzenetet. Például:

EVALUATE CountyCode
WHEN 1 DISPLAY "Carlow tax total is " CountyTax(1)
WHEN 2 DISPLAY "Cavan tax total is " CountyTax(2)
.... 24 more WHEN branches
END-EVALUATE.

De ez a megoldás nem teljesen tökéletes. Könnyű visszatérni a 26 WHEN ág megoldáshoz, amit már korábban bemutattam. De ezúttal, tudjuk, hogy van egy sokkal elegánsabb megoldás is. És itt is van:

Ha megadunk egy CountyName táblát és kitöltjük a megyék nevével, akkor az EVALUATE megoldást (fent) helyettesíthetjük egy egyszerűbb megállapítással:

DISPLAY CountyName(Idx) " tax total is " CountyTax(Idx).

PROCEDURE DIVISION.
Begin.
OPEN INPUT TaxFile
READ TaxFile
AT END SET EndOfTaxFile TO TRUE
END-READ
PERFORM UNTIL EndOfTaxFile
ADD TaxPaid TO CountyTax(CountyCode)
READ TaxFile
AT END SET EndOfTaxFile TO TRUE
END-READ
END-PERFORM
PERFORM VARYING Idx FROM 1 BY 1
UNTIL Idx GREATER THAN 26
DISPLAY CountyName(Idx) " tax total is " CountyTax(Idx)
END-PERFORM
CLOSE TaxFile
STOP RUN.
Redefines használata

A következő útmutatóban azt vizsgáljuk, hogy hogy használhatjuk a REDEFINES parancsot, azért, hogy beállítsunk egy előre megadott értéktáblázatot. Jelenleg, nem fogunk azzal foglalkozni, hogy mechanikusan beállítsuk a CountyName táblázatokat, mert az alábbiak szerint diagrammosan is ábrázolhatjuk a következő ábra szerint:

A táblázat elemeire hivatkozhatunk a szokásos módon, így hát a DISPLAY CountyName(3) kijelentés meg fogja mutatni a Cork értéket és a DISPLAY CountyName(5) Dublint.

A táblázat belső indexének használhata egy másik indexben

A County Tax Report programban bebizonyosodott, hogy az adó rekordok kódot használtak, hogy megmutassák a megyét, ahelyett, hogy a megye nevét mutatták volna. A CountyCode-ot használva direkt indexként a CountyTax táblázatban képesek voltunk azt a megállapítást használni, hogy ADD TaxPaid TO CountyTax(CountyCode) hogy hozzáadjuk a TaxPaid-et az egészhez.

Néha azonban nem ilyen egyszerű. Tegyük fel, hogy a CountyCode helyett az adó rekord az alábbi CountyName-et tartalmazta:

01 TaxRec.
88 EndOfTaxFile VALUE HIGH-VALUES.
02 PAYENum PIC 9(8)
02 County PIC X(9).
02 TaxPaid PIC 9(7)V99.

Hogy oldhatjuk meg a problémát?

Egy EVALUATE alapú megoldás

Ha az adó rekord egy megye nevet tartalmaz, egy megye kód helyett, olyan módot kell találnunk, amely a nevet numerikus értékké alakít, amit aztán a táblázatban táblázat indexként tudunk használni. Amit tennünk kell, az, hogy az első megye nevet 1-es értékké alakítjuk a másodikat 2-essé és így tovább.

Egyik megközelítés, amit ki kell próbálnunk, az EVALUATE alapú megoldás. Pl:

EVALUATE County
WHEN "Carlow" MOVE 1 TO CountyNum
WHEN "Cavan" MOVE 2 TO CountyNum
..... 24 more WHEN branches
END-EVALUATE
ADD TaxPaid TO CountyTax(CountyNum)

De eddigre már rá kellet jönnünk, hogy létezik egy még elegánsabb megoldás. A kérdés, hogy miért?

Subscript-et használni egy táblázatból indexként, egy második táblázatba.

Ahhoz, hogy a megye nevét numerikus értékké változtassuk, a CountyNames táblázatot használhatjuk, amit az előző pontban írtunk. Összehasonlítjuk a megye nevét a rekordban minden egyes CountyName táblázat elem tartalmával és amikor találkoznak, a CountyName subscript értékét használjuk indexként a CountyTax táblázatban.

Hogy összehasonlíthassuk a County értékeket a CountyNames táblázat minden elemével, használhatunk PERFORM..VARYING-et. Pl.

PERFORM VARYING CountyNum FROM 1 BY 1
UNTIL CountyName(CountyNum) = County
END-PERFORM
ADD TaxPaid TO CountyTax(CountyNum)

Láthatod hogy hol illeszkedik a County Tax Report-ba a következő táblázatból:

PROCEDURE DIVISION.
Begin.
OPEN INPUT TaxFile
READ TaxFile
AT END SET EndOfTaxFile TO TRUE
END-READ
PERFORM UNTIL EndOfTaxFile

PERFORM VARYING CountyNum FROM 1 BY 1
UNTIL CountyName(CountyNum) = County
END-PERFORM
ADD TaxPaid TO CountyTax(CountyNum)
READ TaxFile
AT END SET EndOfTaxFile TO TRUE
END-READ
END-PERFORM
PERFORM VARYING Idx FROM 1 BY 1
UNTIL Idx GREATER THAN 26
DISPLAY CountyName(CountyNum)
" tax total is " CountyTax(CountyNum)
END-PERFORM
CLOSE TaxFile
STOP RUN.