Programvezérlés
Az eddig látott példaprogramok többségének végrehajtási sorrendje megegyezett a szerkezetek kódbafoglalásának a sorrendjével. Ebben a leckében megismerkedünk azokkal a vezérlô szerkezetekkel, amelyekkel a lépések végrehajtási sorrendjébe avatkozhatunk be. Az elsô alapfogalom, amelyet tisztáznunk kell, az állítás. Az állítás értéke az igazságtartalomtól függôen 0 (hamis) vagy 1 (igaz) lehet. Az állítást tulajdonképpen úgy is definiálhatjuk, mint egy operátor, amelynek végeredménye kizárólag 0 vagy 1 lehet. A leggyakrabban elôforduló állítások relációs operátorokkal végzett összehasonlításon alapszanak. Bonyolultabb esetekben a relációs operátorokkal képzett összehasonlításokat kombináljuk logikai operátorokkal is. Lássuk hogyan!
Relációs és logikai operátorok használata
A relációs operátorok szerepe tulajdonképpen megegyezik egy olyan kérdésfelvetéssel, amelyben azt kérdezzük, hogy két adat milyen viszonyban (pl. egyenlô, kisebb stb.) van egymással. Az alábbi táblázatban összefoglaltuk a REXX-ben elôforduló relációs operátorokat, jelölésüket és jelentésüket.
| Operátor | Jelentés | Példa |
| = | egyenlô | a = b |
| > | nagyobb | a > b |
| < | kisebb | a < b |
| <>, ><, \=, ª= | nem egyenlô | a <> b |
| \>, ª> | nem kisebb | a \> b |
| >= | nagyobb vagy egyenlô | a >= b |
| <= | kisebb vagy egyenlô | a <= b |
Egyes operátoroknak több megjelenési formája is lehet. A legjobb példa erre a nem egyenlôség kifejezése, melyet négyféleképpen is megtehetünk. A relációs operátorokat az aritmetikai operátorokhoz hasonlóan használhatjuk, s az összehasonlítás eredményét változóban is eltárolhatjuk, s a késôbbiekben újra felhasználhatjuk. A sok elmélkedés után lássunk erre egy példát!
/* Relációs operátorok használata */ SAY 'Gépelj be egy számot!' PULL szam SAY szam '= 10 eredménye; ' (szam = 10) SAY szam '< (2 ** 32 - 1) eredménye: ' (szam < (2 ** 32 - 1)) SAY szam '> 0 eredménye: ' (szam > 0) EXIT
Ez a példaprogram bekér egy számot és ez alapján kiértékeli a három összehasonlítást. Az eredménytôl függôen 0-át (hamis állítás) vagy 1-et (igaz állítás) kapunk vissza.
A logikai operátoroknak három fajtája ismert a REXX-ben: & (logikai és - AND), | (logikai vagy - OR), && (kizáró vagy - XOR). Tulajdonképpen ide tartozik még a negálás is (\ vagy ª), mely segítségével ellenkezôjére változtathatjuk egy összehasonlítás eredményét (invertálás). A logikai operátorok nagyon fontosak, mivel segítségükkel kombinálhatjuk az összehasonlításokat, és így egy lépésben írhatunk el bonyolult feltételeket. Ha kombinálunk, akkor mindig érdemes (bár nem kötelezô) zárójeleket használni, hogy néhány nap eltelte után is könnyedén tudjuk értelmezni a kifejezést:
potencialis_times_vasarlo = (kor < 100) & (kor > 1)
Az alábbi táblázatban összefoglaltuk a logikai operátorokat:
| Kifejezés | Jelentés | Érték igaz, ha... |
| feltétel1 & feltétel2 | feltétel1 AND feltétel2 | mindkét feltétel igaz |
| feltétel1 | feltétel2 | feltétel1 OR feltétel2 | egyik vagy mindkét feltétel igaz |
| feltétel1 && feltétel2 | feltétel1 XOR feltétel2 | csak az egyik feltétel igaz |
| ª feltétel, \ feltétel | NOT feltétel | a feltétel hamis |
A relációs és logikai operátorok viszonya
Az ötödik leckében volt szó az operátorok kiértékelési sorrendjérôl. A relációs és logikai operátorok valamint az egyéb operátorok között is létezik elsôbbségi sorrend, amelyet az alábbi táblázat tartalmaz:
| Operátor csoport | Példák | Sorrend |
| unáris operátorok | - + \ ª | Legelsô |
| hatványozás | ** | |
| szorzás, osztás | * / % // | |
| összeadás, kivonás | + - | |
| összehasonlítás | = <> \> >= | |
| logikai és | & | |
| vagy, kizáró vagy | | && | Legutolsó |
Mint ahogyan azt már megtanultuk, a kiértékelés sorrendje megváltoztatható zárójelezéssel. A &, | és && operátorok használatakor a sorrend nem mindig magától értetôdô, ezért ekkor is használjunk zárójeleket! A táblázatból az is látszik, hogy a logikai és összehasonlító operátorok precedenciája alacsonyabb, mint az aritmetikai operátoroké. Ez azt jelenti, hogy pl. az a_kisebb_mint = a < 1 + 5 * 4 kifejezést a REXX minden további nélkül helyesen fogja kiértékelni, azonban a könnyû értelmezhetôség érdekében itt is érdemes zárójelezni.
Az IF utasítás
A relációs és logikai operátorokkal felépített állítások tesztelésére és a szerkezetek végrehajtásának sorrendjébe való beavatkozásra használjuk az IF utasítást. Az IF ugyanis a feltételtôl függôen végrehajtatja vagy figyelmen kívül hagyatja a kapcsolt szerkezetet. Lássunk erre egy példát:
IF modem = 'BUSY' THEN SAY 'A hívott szám foglalt!'
A végrehajtás során elôször a modem = 'BUSY' összehasonlítás kerül kiértékelésre. Ha az eredmény igaz, akkor a kapcsolt szerkezet végrehajtódik és a 'A hívott szám foglalt!' üzenet jelenik meg. Ha az eredmény nem igaz, akkor a kapcsolt szerkezet nem hajtódik végre, hanem a vezérlés a sorban következô szerkezetre ugrik. Az IF utasítások egymásba is ágyazhatók. Íme egy példa:
IF time >= '09:00' THEN IF time <= '17:00' THEN SAY 'Munkaidô'
A kiértékelés során elôször az elsô feltétel kerül megvizsgálásra. Ha az eredmény igaz, akkor a második lépés a második feltétel kiértékelése. Csak ha ez is teljesül, akkor jelenik meg a 'Munkaidô' üzenet. Az egymásbaágyazással ugyanazt az eredményt érjük el (csak sokkal bonyolultabban), mint a logikai és operátorral:
IF time >= '9:00' & time <= '17:00' THEN SAY 'Munkaidô'
Figyeljük meg az egymásbaágyazott IF utasítások struktúráját! Minden szinten egy kicsit beljebb kezdtük a szöveget, hogy a logikai felépítést ezzel is visszaadjuk. Elvileg erre nem lenne szükség; az IF-eket egyszerûen egymás alá is írhattuk volna, a program ettôl ugyanolyan jól futna. A kód könnyû értelmezhetôségére való tekintettel azonban nagyon is kívánatos, hogy programíráskor mindenki a fenti sémához tartsa magát.
Az ELSE utasítás
Az ELSE utasítás szorosan együttmûködik az IF-fel. Amikor az IF feltétele hamis, akkor az ELSE-hez kapcsolt szerkezet kerül végrehajtásra. Ha pl. az idôpont alapján közölni akarjuk, hogy munkaidô van-e vagy sem, akkor azt a következôképpen oldhatjuk meg:
IF time >= '9:00' & time <= '17:00' THEN SAY 'Munkaidô' ELSE SAY 'Nem munkaidô'
Természetesen ugyanezt ELSE nélkül, csak IF-ekkel is megoldhatjuk, bár ekkor többet kell írni:
IF time >= '9:00' & time <= '17:00' THEN SAY 'Munkaidô' IF time > '9:00' | time < '17:00' THEN SAY 'Nem munkaidô'
Természetesen az ELSE utasításokat is egymásba lehet ágyazni, ekkor azonban nagyon ügyelni kell arra, hogy a program valóban azt csinálja, amit akarunk. Az ELSE utasítás ugyanis mindig az utolsó IF-hez kapcsolódik, s ezt sokan figyelmen kívül hagyják! Tekintsük meg az alábbi kódrészletet!
IF a = b THEN IF c = d THEN SAY 'Találat' ELSE SAY 'Nincs találat'
A struktúra alapján nyilvánvaló, hogy a programozó szándéka az volt, hogy a 'Találat' szöveg jelenjen meg, ha a = b és c = d, minden más esetben pedig a 'Nincs találat'. Az ELSE utasítás azonban a második IF-hez tartozik, ezért - a programozó elgondolásával ellentétesen - a 'Nincs találat' csak akkor fog megjelenni, ha c <> d. A probléma megoldása lehet egy ál ELSE beiktatása:
IF a = b THEN IF c = d THEN SAY 'Találat' ELSE NOP ELSE SAY 'Nincs találat'
A NOP utasítás hatására nem történik semmi, viszont elértük, hogy a második ELSE a megfelelô (elsô) IF-hez kapcsolódjon.
Csoportos utasítások
Gyakran fordul elô, hogy az IF vagy az ELSE utasítás után egynél több szerkezetet is végre akarunk hajtatni. Ekkor jön jól a DO - END utasításpár, amely a szerkezetek csoportosítására szolgál. Minden DO - END pár közé írt szerkezetcsoport kívülrôl egy szerkezetnek látszik, így tehát jól használható a fenti példaprobléma ál-ELSE nélküli áthidalására is:
IF a = b THEN DO IF c = d THEN SAY 'Találat' END ELSE SAY 'Nincs találat'
A SELECT utasítás
Sokszor jön elô az is, hogy a program végrehajtása során ellenôrizni akarjuk egy változó értékét és a lehetséges értékektôl függô kódrészletet akarunk végrehajtani. Ez természetesen megoldható egy hosszú, egymásba ágyazott IF - ELSE struktúrával:
IF input = '1' THEN SAY 'Micimackó' ELSE IF input = '2' THEN SAY 'Lacimaci' ELSE IF input = '3' THEN SAY 'Cooper ügynök' ELSE SAY 'Ismeretlen'
A kódrészlet futásakor az input változó értékétôl függô nevek vagy az 'Ismeretlen' felirat jelenik meg a képernyôn. Ettôl sokkal elegánsabban megoldható a feladat a SELECT utasítással:
SELECT WHEN input = '1' THEN SAY 'Micimackó' WHEN input = '2' THEN SAY 'Lacimaci' WHEN input = '3' THEN SAY 'Cooper ügynök' OTHERWISE SAY 'Ismeretlen' END /* SELECT */
Minden SELECT szerkezetet END-nek kell lezárnia. A kiértékelés során a REXX sorban teszteli a feltételeket és végrehajtja a kapcsolt utasítást, ha az eredmény igaz. Ezután a vezérlés az END-re ugrik, s a többi feltétel nem kerül feldolgozásra. Ha egyik feltétel sem igaz, akkor az OTHERWISE-hoz kapcsolt utasítás hajtódik végre. A SELECT utasítás nem kívánja meg, hogy ugyanazt a változót teszteljük a struktúrán belül. Lássunk erre az utasításra egy példát egy kissé komolyabb programban, amely a már korábban megismert Zeller eljárás segítségével megmondja a bevitt születési dátum alapján, hogy melyik napon született az adott személy. Reméljük, hogy a program mûködése az elôzôek alapján mindenkinek érthetô lesz!
/* A születés napja */
SAY 'Gépeld be a születési dátumodat! (hó nap év sorrendben)'
SAY 'Példa: 03 24 1968'
PULL honap nap ev
tmp = Zeller()
SELECT
WHEN tmp = 0 THEN
valasz = 'Hétfô'
WHEN tmp = 1 THEN
valasz = 'Kedd'
WHEN tmp = 2 THEN
valasz = 'Szerda'
WHEN tmp = 3 THEN
valasz = 'Csütörtök'
WHEN tmp = 4 THEN
valasz = 'Péntek'
WHEN tmp = 5 THEN
valasz = 'Szombat'
OTHERWISE
valasz = 'Vasárnap'
END
SAY 'Születésed napja: 'valasz
EXIT
Zeller:
IF honap > 2 THEN
DO
kepzett_honap = honap - 2
kepzett_ev = ev
END
ELSE
DO
kepzett_honap = honap + 10
kepzett_ev = ev - 1
END
evszazad = kepzett_ev % 100
ev_a_szazadban = kepzett_ev - 100 * evszazad
a_het_napja = ((13 * kepzett_honap - 1) % 5 + nap +,
ev_a_szazadban + ev_a_szazadban % 4 - evszazad -,
- evszazad + 77) // 7
RETURN a_het_napja
REXX GYÍK:
K1. Hogyan különbözteti meg a REXX az értékadást az összehasonlítástól? Mindkettô a = jellel történik!
V1. A REXX ezt a szövegkörnyezetbôl állapítja meg. Minden olyan szerkezet, amelyben egy változót az egyenlôségjel követ, értékadásként lesz értelmezve. Minden más helyzetben pedig összehasonlításként.
Gyakorlatok:
1. Melyik operátor élvez végrehajtási elsôbbséget?
a. < vagy +
b. \ vagy **
c. && vagy &
d. \> vagy <>
2. A következô programban hiba van. Keresse meg!
/* Hibás program */ SAY 'Tegyél be egy lemezt!' SAY 'Nyomja meg az ENTERT-t, ha kész!' PULL . XCOPY C:\OS2\*.INI A:\ > NUL IF RC <> 0 THEN SAY 'Error' EXIT
| Kádár Zsolt 1998. 03. 08. | [ Elôzô lecke | Következô lecke | Tartalom ] |