Az összetett változó fogalma
A programok egyik fô feladata az adatok strukturált tárolása és feldolgozása. Típusában különbözô, bizonyos szempontból azonban mégis egy csoportba tartozó adatok tárolására hozták létre az összetett változókat. Szerepük körülbelül az OS/2 Munkaasztalán is használt gyûjtôk (folder) szerepével egyezik meg, ugyanis az összetett változók segítségével egy helyen gyûjthetjük össze az adatokat és a már meglévô adatokhoz könnyûszerrel adhatunk hozzá újabbakat. Minden olyan változó, amelynek nevében pont szerepel, egyben összetett változó is. Lássunk néhány példát:
nev.vezetek nev.kereszt fajl.1 konyv.fejezet.oldal.bekezdes.sor
Az összetett változók elsô pont elôtti részét nevezik tônek (stem). Ennek minden esetben egy a REXX szabályainak megfelelô változónévnek kell lennie. Az elsô pont utáni rész a farok (tail), amelynek minden esetben a REXX számára értelmes szimbólumnak kell lennie. A farok tehát lehet bármilyen érvényes változónév, vagy akár konstans is. A közönséges változókhoz hasonlóan, az összetett változók értékadás elôtti tartalma a változó nagybetûs neve. Az összetett változó által reprezentált összes változók kezdôértékét beállíthatjuk a fô résznek adott értékkel, vagyis egyetlen utasítással:
fajl. = 'config.sys'
Ha ezek után kiíratjuk a fajl.1, fajl.2 stb. értékeket, akkor minden esetben config.sys-t kapunk vissza. Amennyiben a farokban szereplô konstansoknak értéket adunk, a REXX automatikusan behelyettesíti az értéket az összetett változó nevébe:
i = 5 fajl.i = 'autoexec.bat'
A fenti példa kiértékelése után azt az eredményt kapjuk, hogy az autoexec.bat karakterlánc a FAJL.5 változóban került eltárolásra, mivel az i-nek 5-öt adtunk meg értékül. Az i-nek természetesen nem muszáj számot megadni:
i = 'CONFIG' fajl.i = 'fontos'
Ezzel a konstrukcióval azt értük el, hogy a fajl.config változó értéke a fontos karakterlánc lett. Az összetett változók használatakor vigyázzunk arra is, hogy különbség van a névben szereplô nagy és kisbetûk között. Ha erre nem figyelünk, akkor bizonyos esetekben váratlan meglepetések érhetnek bennünket.
Tömbök
A tömbök segítségével is csoportosíthatunk adatokat, és az egyes elemekre az indexük (sorszámuk) alapján hivatkozhatunk. A legtöbb programozási nyelvvel ellentétben a REXX-ben nincs szükség a tömb méretének elôzetes deklarálására. Ez többek között azért is lehetséges, mert a tömbök tulajdonképpen az összetett változókon alapuló konstrukciók. A tömb ugyanis nem más, mint egy összetett változó, amelynek fô része a tömb neve, a farok rész pedig a tömb indexe:
fajl.1 = 'config.sys' fajl.2 = 'autoexec.bat' fajl.3 = 'startup.cmd'
A behelyettesítési mechanizmus kihasználásával a tömb elemei könnyedén kilistázhatóak egy egyszerû ciklus segítségével:
DO k = 1 TO 3 SAY k'. elem: 'fajl.k END
A tömb méretének megállapítására nem létezik beépített függvény, ezért ezt saját magunknak kell nyilvántartani. A legtöbb programozó azt a hagyományt követi, amely a 0. sorszámú elemben tárolja a tömb méretét:
fajl.0 = 3 DO k = 1 TO fajl.0 SAY k'. elem: 'fajl.k END
Mivel a tömbök tulajdonképpen összetett változók, ezért a tömb elemeinek inicializálását is elintézhetjük egyetlen utasítással. Az alábbi példaprogramban is ezt használják ki, amikor is a mindenkori dátum alapján angolul kiíratjuk, hogy most éppen melyik hónap hányadik napja van:
/* Példaprogram tömbök használatára */ /* A tömb elemeinek inicializálása */ th. = 'th' /* A speciális esetek inicializálása */ th.1 = 'st' /* 1st */ th.2 = 'nd' /* 2nd */ th.3 = 'rd' /* 3rd */ th.21 = 'st' /* 21st */ th.22 = 'nd' /* 22nd */ th.23 = 'rd' /* 23rd */ th.31 = 'st' /* 31st */ PARSE VALUE Date() WITH nap honap ev SAY 'Today is the' nap || th.nap 'of' honap'.' EXIT
Többdimenziós tömbök
Az összetett változók farka természetesen több tagot is tartalmazhat, így lehetôség van többdimenziós tömbök definiálására is. Ha pl. egy táblázatot akarunk eltárolni, akkor erre a célra kiválóan megfelel egy kétdimenziós tömb. A két dimenzióhoz természetesen két index is tartozik, így ha el akarjuk érni a táblázat minden elemét, akkor ehhez két egymásba ágyazott ciklusra van szükség:
DO j = 1 TO 10 DO k = 1 TO 10 tabla.j.k = j * k END END
Ez a kódrészlet egy 10*10-es táblázatot hoz létre, melynek elemei megegyeznek az elemekhez tartozó indexek szorzatával. A táblázat tartalmát a feltöltés során ki is nyomtathatjuk, ha egy kicsit kibôvítjük a programot:
DO j = 1 TO 10 sor = '' DO k = 1 TO 10 tabla.j.k = j * k sor = sor || FORMAT(tabla.j.k, 4) END SAY sor END
Struktúrák
Amikor olyan adatokat kell tárolnunk, amelyek nem azonos típusúak, azonban valamilyen okból kifolyólag mégiscsak összetartoznak, akkor használjuk a struktúrákat (más nyelvekben rekordokat). A struktúrák a tömbökhöz hasonlóan az összetett változókon alapszanak. Egy tipikus példája a struktúrák használatára az az eset, amikor egy személy adatait kell rendezett formában eltárolnunk:
szemely.nev = 'Kiss Pista' /* Név */ szemely.kor = '99' /* Életkor */ szemely.szul = '1899 12 31' /* Születési dátum */
Az alábbi példaprogram bekéri a felhasználó néhány adatát, struktúrák felhasználásával eltárolja azokat, majd a program végén visszaírja az eltárolt adatokat:
/* Példaprogram a struktúrák használatára */ SAY 'Adja meg a nevét!' PULL info.nev SAY 'Adja meg a korát!' PULL info.kor SAY 'Adja meg a testmagasságát cm-ben!' PULL info.magassag SAY 'Adja meg a nemét! (F/N)' PULL info.neme IF info.neme = 'F' THEN info.cim = 'Uram, ' ELSE IF info.neme = 'N' THEN info.cim = 'Asszonyom, ' ELSE info.cim = '' SAY '' SAY 'Köszönöm tisztelt 'info.nev'!' SAY info.cim'™n 'info.kor' éves és 'info.magassag'cm magas.' EXIT
Kombináljuk!
Természetesen senki sem gátol meg bennünket abban, hogy összeházasítsuk a két koncepciót, és pl. struktúrák tömbjét vagy tömbök struktúráját hozzuk létre. I'me egy példa egy struktúrára, amely egy olyan tömböt tartalmaz, amelyben egy adott hallgató osztályzatait tároljuk:
hallgato.neve = 'Pityipál Palkó' hallgato.osztalyzat.0 = 3 hallgato.osztalyzat.1 = 'Angol 3' hallgato.osztalyzat.2 = 'Orosz 5' hallgato.osztalyzat.3 = 'Ének 2'
A fordított kombinációval, tehát struktúrák tömbjével kisebb adatbázisokat hozhatunk létre, mivel így bármelyik struktúrát elérhetjük egyetlen ciklus felhasználásával:
hallgato.0 = 3 hallgato.1.neve = 'Pityipál Palkó' hallgato.2.neve = 'Sóvágó Aranka' hallgato.3.neve = 'Békés Julianna' DO i = 1 TO hallgato.0 SAY hallgato.1.name END
A rend (vagy inkább a káosz a fejünkben :) akkor válik teljessé, amikor olyan struktúrát hozunk létre, amelynek elemei tömbök, viszont a tömbök újabb struktúrákat tartalmaznak. Ez ugyan kicsit bonyolultan hangzik, ugyanakkor az alábbi kódrészlet alapján rögtön ismerôs lesz, mivel gyakorlatilag a többdimenziós tömbök kezelésekor már megismert módszer ismétlôdik:
DO i = 1 TO hallgato.0 SAY hallgato.i.nev DO j = 1 TO hallgato.i.osztaly.0 SAY ' 'hallgato.i.osztaly.j END END
A struktúrák és tömbök kedvezô tulajdonságait másképpen is ötvözhetjük. Amennyiben az adattárolás folyamán az indexet "beépítjük" az összetett változók nevébe is, akkor egy sokkal gyorsabban kereshetô adatbázist hozhatunk létre. Vizsgáljuk meg ezt a lehetôséget egy példa kapcsán!
/* Példaprogram-részlet személynevek indexelt tárolására */ elemszam = 1000 /* adat */ elemnev = 'Pista' /* adat */ adatelem.0 = 5000 /* tömbméret definiálása */ adatelem.9.szam = elemszam /* adattárolás a tömbben */ adatelem.9.nev = elemnev /* adattárolás a tömbben */ /* Az elemszam ismeretében az elemnev adat az alábbi módon kereshetô meg */ DO l = 1 TO adatelem.0 IF adatelem.l.szam = elemszam THEN DO SAY 'Találat:' adatelem.l.szam '-' adatelem.l.nev LEAVE END END
Abban az esetben, amikor a keresést az elemnev alapján kell elvégezni, akkor a helyzet sokkal rosszabb, mivel egy olyan ciklust kell írni, amely sorban összehasonlítja a tömbökben tárolt neveket a keresett névvel. Ez a folyamat pedig igen lassú lehet, ha az adatbázis nagy. Mind az elemszam, mind pedig az elemnev ismeretében sokkal gyorsabban kereshetünk, ha speciális összetett változókkal építjük fel az adatbázist:
adatelem.szamok.elemszam = 9 /* index1 */ elemnev = TRANSLATE(elemnev) /* nagybetûs alakra alakítjuk */ adatelem.nevek.elemnev = 9 /* index2 */
Mint látjuk, az elsô összetett változó a farokrészben a tárolt elem számát, a második pedig a tárolt elem nevét is tartalmazza. Az elemnevet minden esetben nagybetûs alakra hozzuk, hogy az ez alapján készített összetett változó mindig nagybetûs legyen. Ha megtartjuk a példa elején megadott adatokat, akkor az újonnan definiált változónevek a következôk lesznek:
ADATELEM.SZAMOK.1000 ADATELEM.NEVEK.PISTA
Mindkét összetett változóban eltároltuk a 9-et, amely a tulajdonképpeni adattárolást végzô tömbnek a jelenleg vizsgált adathoz tartozó indexe. Ez pedig azt jelenti, hogy ha a keresett elem számát, vagy nevét ismerjük, akkor egybôl össze tudjuk rakni a fenti változók egyikét, amelybôl aztán kiolvashatjuk a tároló tömbelem valódi indexét. Ez viszont azt is jelenti, hogy ha az adatbázis létrehozásánál elkészítjük ezeket a speciális összetett változókat is, akkor minden esetben, ciklus létrehozása nélkül, egy lépésben tudjuk megtalálni a keresett elemet:
/* Keresés név alapján */ elemnev = TRANSLATE(elemnev) index = adatelem.nevek.elemnev SAY 'Találat: 'adatelem.index.nev '-' adatelem.index.szam /* Keresés szám alapján */ index = adatelem.szamok.elemszam SAY 'Találat: 'adatelem.index.szam '-' adatelem.index.nev
Végezetül nézzünk meg egy komplett példaprogramot az elôzôekben bemutatott (sokak által asszociatív memóriának is nevezett) programozási technika használatára, amelyben a felhasználó megadhatja, hogy a tárolt adatbázis oszlopai milyen sorrendben jelenjenek meg:
/* Adatbázis listázása */ info.1 = 'VEZETEKNEV' info.2 = 'KERESZTNEV' info.3 = 'TELEFONSZAM' SAY 'A választási lehetôségek:' DO i = 1 TO 3 SAY ' ' i info.i END SAY '' DO i = 1 TO 3 SAY 'Válassz egy sorszámot az 'i'. oszlopnak! (1/2/3)' PULL valasz oszlop.i = info.valasz SAY oszlop.i END adat.0 = 3 adat.1.Vezeteknev = 'Kádár' adat.1.Keresztnev = 'Zsolt' adat.1.Telefonszam = '099123' adat.2.Vezeteknev = 'Gates' adat.2.Keresztnev = 'Bill' adat.2.Telefonszam = '999999' adat.3.Vezeteknev = 'Kiss' adat.3.Keresztnev = 'Béla' adat.3.Telefonszam = '199123' DO i = 1 TO adat.0 sor = '' DO j = 1 TO 3 o = oszlop.j sor = sor || Left(adat.i.o, 15) END SAY sor END EXIT
A futtatáskor elôször be kell adni, hogy milyen sorrendben akarjuk az oszlopokat megjelentetni. A kívánt sorrend az oszlop. összetett változóban kerül eltárolásra. Az adatbázist a program tartalmazza, amely jelen esetben három elembôl áll. A program végén egy ciklus lépked végig az elemeken és az ebbe beágyazott másik ciklus keresi ki az oszlopok indexeit. A megtalált adatokat a sor változóban tároljuk és minden egyes elem megtalálása esetén kinyomtatjuk.
Gyakorlatok:
1. Készítsen egy programot, amely számolja, hogy a felhasználó hányszor gépelte be az ABC egyes betûit! A program kimenete az alábbi módon nézzen ki:
A(z) 'A' betût 10x gépelte be. A(z) 'B' betût 5x gépelte be. stb.
A kis és a nagy betûk között ne tegyen különbséget!
| Kádár Zsolt 1998. 06. 07. | [ Elôzô lecke | Következô lecke | Tartalom ] |