4. Utasítások, vezérlési szerkezetek
Ez a fejezet az ELAN nyelv algoritmikus elemeit ismerteti, melyek az alábbiak:
4.1. Értékadás
4.2. Szekvencia
4.3. Elágazások
4.4. Ciklusok
4.5. Beolvasás, kiírás
4.6. Finomítás
4.7. Megjegyzés
4.1. Értékadás
Értékadással változók kaphatják egy kifejezés értékét. Az ELAN jellemzője, hogy a változónak és a kifejezésnek azonos típusúnak kell lennie.
változó := kifejezés
Az azonos típusúság azt jelenti, hogy vagy a típusok neve azonos, vagy pedig névtelen típus esetén a szerkezetük. nyelv ezt még azzal is szigorítja, hogy a kifejezésen belül is azonos típusú részkifejezéseknek, változóknak, konstansoknak kell lenni. Az értékadásban tetszőleges - akár összetett - típusú adatok is szerepelhetnek.
Példa:
INT VAR i::5;
INT VAR j;
REAL CONST y::2*pi;
REAL var X;
x:=y+real(i);
j:=round(x/y);
Az értékadásbeli kifejezések speciális változata a feltételes kifejezés:
változó := IF feltétel THEN kifejezés1 ELSE kifejezés2 FI
Példa:
max := IF a > b THEN a ELSE b FI
Megjegyzés: FI helyett ENDIF is írható.
Az értékadások másik változatát az értékmódosítások jelentik, amelyek egy változó növelését, csökkentését, ... jelölik:
változó OPERÁTOR kifejezés
Ezek mindig valamilyen "normál" értékadás felírását rövidítik, s mivel a módosítandó változót csak egyszer kell leírni, így biztonságosabbá és hatékonyabbá is teszik.
Példa:
i := i+1 # ehelyett #
i INCR 1 # ezt írhatjuk #
x := x-3.5 # ehelyett #
x DECR 3.5 # ezt írhatjuk #
Az INCR és a DECR művelet egész és valós típusra alkalmazható, az előző fejezetben pedig találkoztunk a szöveg típus CAT műveletével is.
4.2. Szekvencia
Lépések egymás utáni végrehajtását jelöli, közéjük pontosvesszőt írunk. Az ilyen felsorolást szakasznak vagy más néven szekvenciának nevezzük.
4.3. Elágazások
Az ELAN nyelv kétféle elágazást definiál: a kétfeléágazást (IF), és a sokfeléágazást (SELECT).
Az IF utasítás szolgálhat egy utasításcsoport végrehajtásának feltételhez kötésére, vagy pedig két utasításcsoport közötti választásra:
Az 1. esetben az IF utasítás az alábbi mintának megfelelően használható:
IF feltétel
THEN utasítások
FI
A 2. esetben az IF utasítás az alábbi mintának megfelelően használható:
IF feltétel
THEN utasítások1
ELSE utasítások2
FI
A feltétel teljesülése esetén mindkét esetben a THEN utáni utasításokat kell végrehajtani, majd a FI mögöttiek következnek.
A feltétel nem teljesülése esetén az 1. esetben a FI utániak következnek, a 2. esetben pedig az ELSE és a FI közöttiek. A THEN alapszó akkor is kötelező, ha utána semmit nem írunk, azaz ha az utasítások ill. az utasítások1 helye üres.
Példa:
IF 0>i
THEN i := -i
FI
IF a>b
THEN max:=a; min:=b
ELSE max:=b; min:=a
FI
Az IF utasítás szolgálhat kettőnél több irányú elágazás leírására is. Ekkor az ELSE-ágon levő IF alapszót összekötjük az ELSE alapszóval (azaz: az ELSE és IF alapszavakat összevonjuk egy közös ELIF alapszóvá):
IF feltétel1 THEN utasítások1
ELIF feltétel2 THEN utasítások2
...
ELIF feltételn THEN utasításokn
ELSE utasítás
FI
Ebben az esetben felülről lefelé haladva az első igaz feltételű ágat hajtjuk végre, s ha egyik sem teljesül, akkor az ELSE ágat.
Példa:
IF i>0 THEN put("pozitív")
ELIF I=0 THEN put("nulla")
ELSE put("negatív")
FI;
A feltétel lehet logikai változó és konstans reláció, valamint alkalmazott logikai műveletek eredménye.
Példa:
IF logikai
THEN ...
IF a>b
THEN ...
IF a>b AND NOT logikai
THEN ...
A programozási nyelvekben szokásos másikfajta elágazás egy kifejezés értéke szerint választja szét az egyes programágakat. A kifejezés csak egész értékű lehet.
SELECT kifejezés OF
CASE eset1: utasítások1
CASE eset2: utasítások2
...
OTHERWISE utasításokn
ENDSELECT
Az OTHERWISE-ág elmaradhat, ebben az esetben az elágazás hatástalan, ha a kifejezés értéke nincs a felsorolt esetek között.
Az egyes ágakat kiválasztó feltétel lehet egy érték, valamint értékek felsorolása.
Példa:
SELECT i OF
CASE 1 : put("1")
CASE 2,3,5,7 : put("kis prím")
OTHERWISE put("egyéb érték")
ENDSELECT;
Ez az utasítás is lehet feltételes kifejezést adó, ekkor minden ágán egy-egy kifejezésnek kell lennie. Ebben az esetben az OTHERWISE-ág nem maradhat el.
4.4. Ciklusok
Az ELAN négyféle ciklust ismer, a szokásos háromfélét (elöltesztelős, hátultesztelős, számlálós) kiegészíti egy ciklusváltozó nélküli, adott darabszámszor lefutó ciklussal.
Mindegyik ciklus magját azonos utasítások (REP, ENDREP) veszik körül.
Az elöltesztelős ciklus alakja az alábbi:
WHILE feltétel
REP
utasítások
ENDREP
A hátultesztelős ciklus alakja az alábbi:
REP
utasítások
UNTIL feltétel
ENDREP
Ahogy az a legtöbb programozási nyelvben szokásos, ELAN-ban az elöltesztelős ciklusnál a ciklusban való bentmaradás feltételét, a hátultesztelős ciklusnál pedig a ciklusból való kilépés feltételét kell megadnunk.
A feltétel ugyanolyan formájú lehet, mint azt az elágazásoknál már megismertük.
Példa: (a 100-nál nem nagyobb számok közül az utolsó Fibonacci-szám meghatározása)
INT PROC fib:
f0:=0; f0:=1;
WHILE f0+f1 <= 100
REP
f:=f0+f1; f0:=f1; f1:=f
ENDREP;
f
ENDPROC fib;
Példa: (logaritmikus keresés részlete)
i:=1; u:=n;
REP
k:=(i+u) DIV 2;
IF a[k] < x THEN u:=k-1
ELIF a[k] > x THEN e:=k+1
FI
UNTIL NOT (i <= u AND a[k] <> x)
ENDREP;
A számlálós ciklus kétféle lehet: egyesével növekvő vagy pedig egyesével csökkenő lépésközű:
Az egyesével növekvő számlálós ciklus alakja az alábbi:
FOR cv FROM kezdet UPTO vég
REP
utasítások
ENDREP
Az egyesével csökkenő számlálós ciklus alakja az alábbi:
FOR cv FROM kezdet DOWNTO vég
REP
utasítások
ENDREP
Mindkét FOR-ciklus elöltesztelős, azaz ciklusmagjuk nem hajtódik végre egyszer sem, ha nincs rá szükség. A mintákban cv-nek nevezett ciklusváltozó csak egész típusú lehet, a "kezdet" és a "vég" helyén pedig tetszőleges kifejezés állhat.
Példa: (az n!-t meghatározó programrészlet)
fakt := 1;
FOR i FROM 2 UPTO n
REP
fakt := fakt * i
ENDREP;
Sokszor a számlálós ciklusnál nincs szükség a ciklusváltozóra sem, csupán a ciklusmag n-szeri végrehajtására:
A ciklusváltozó nélküli számlálós ciklus alakja az alábbi:
UPTO darabszám
REP
utasítások
ENDREP
4.5. Beolvasás, kiírás
A nyelv beolvasó és kiíró utasításokat nem tartalmaz, helyettük ezekre a célokra szabványos eljárásokat definiál. Alaphelyzetben egy elemi típusú vagy szöveg típusú változó beolvasására és egy kifejezés kiírására van lehetőségünk:
Egy elemi típusú vagy szöveg típusú változó beolvasásának alakja az alábbi:
get(változó)
Egy kifejezés kiírásának alakja az alábbi:
put(kifejezés)
A get magától nem ír ki semmit. Ezért ha a beolvasás előtt kérdést szeretnénk kiírni, akkor arra a put eljárást kell használnunk:
Példa:
put("Kérek egy számot: ");
get(szám);
A beolvasásnak többféle változata létezik: megadható a beolvasandó karakterek maximális darabszáma, illetve a beolvasás végét jelző karakter:
A beolvasandó karakterek maximális darabszámának megadásával történő beolvasás alakja az alábbi:
get(változó, maximális hossz)
Megjegyzés: a maximális hossz tetszőleges pozitív egész értékű kifejezés lehet.
A beolvasás végét jelző karakter megadásával történő beolvasás alakja az alábbi:
get(változó, végjel)
Megjegyzés: a végjel tetszőleges szöveg (célszerűen egy karakter).
Példa:
put("Kérek egy mondatot: ");
get(mondat,"."); # a mondat végét itt most pont jelzi #
A beolvasás egy speciális esete a karakterenkénti beolvasás, amely tetszőleges karakter beolvasására képes, eljárásként és függvényként is használható:
Eljárásként való használatának alakja az alábbi:
k := inchar
Függvényként való használatának alakja az alábbi:
inchar(k)
A put a kiírás után az utolsó kiírt karakter utáni pozíción marad, s a következő kiírás vagy beolvasás itt fog kezdődni. Ha nem ezt szeretnénk, akkor a képernyőn tovább kell lépnünk. Erre használhatjuk a soremelés (azaz: line), a pozícionálás (azaz: cursor) és a képernyőtörlés (azaz: page) utasításokat.
A line nevű utasítás használatának alakja az alábbi:
line
A cursor nevű utasítás használatának alakja az alábbi:
cursor(x,y)
A page nevű utasítás használatának alakja az alábbi:
page
Függvények segítségével lekérdezhetjük a kurzor aktuális pozícióját, a képernyő x-, illetve y-koordinátái legnagyobb értékét:
A kurzor aktuális pozícióját lekérdező getcursor függvény használatának alakja az alábbi:
getcursor(x,y)
A képernyő x-koordinátái legnagyobb értékét lekérdező xsize függvény használatának alakja az alábbi:
xsize
A képernyő y-koordinátái legnagyobb értékét lekérdező ysize függvény használatának alakja az alábbi:
ysize
4.6. Finomítás
A finomítások az ELAN programozási nyelv speciális elemei. Eljárás-, illetve függvényszerűek, de azoknál lényegesen szűkebb lehetőségekkel rendelkeznek, más célra is szolgálnak.
Az ELAN-ban a finomítás tulajdonképpen olyan eljárás, amelynek nincsenek paraméterei és lokális változói, és rekurziót sem tartalmazhat, továbbá az adott programegység minden változóját szabadon használhatja, valamint a programegység más finomításai is használhatják az ő változóit. A finomítás tulajdonképpen egy utasításcsoport névvel ellátására alkalmas, s mint ilyen, az algoritmikus absztrakciónak, a felülről lefelé történő kifejtésnek az eszköze.
A finomítás lényege tehát az, hogy egy logikailag összefüggő, a program során többször végrehajtható szakasznak (azaz: utasításcsoportnak) nevet ad, és definiálása után ezt a nevet leírva (azaz: az adott finomítást meghívva) az adott szakasz utasításait (azaz: a finomítás törzsrészét) hajtja végre a gép. A finomítás mint nyelvi eszköz alkalmazásának az előnye az, hogy finomítások alkalmazása esetén a program áttekinthetőbb, jobban olvasható lesz.
A finomítás definíciójában a finomítás nevét a finomítás törzsétől kettőspont választja el, a finomítás törzsét pedig pont (azaz: .) zárja le.
Egy finomítás belsejében további finomításokat is meghívhatunk.
A finomítás általános definiálásának alakja az alábbi:
név:
szakasz
.
Megjegyzés: a szakasz itt a finomítás törzsét jelenti.
ELAN-ban az adott finomítás alkalmazása a program szövegében megelőzheti az adott finomítás definiálását.
A BASIC nyelv "eljárásai" és az ELAN nyelvbeli finomítások közötti különbségek az alábbiak:
- A finomítás adhat értéket eredményül.
- A finomításra a finomítás nevével tudunk hivatkozni.
- Az ELAN fordítóprogramja eldönti, hogy egy finomításra hivatkozás esetén eljáráshívást végez-e, vagy pedig beépíti az adott finomítást a program szövegébe. A fordító a két lehetséges megoldás közül gazdaságossági szempontok alapján választ.
ELAN-ban a finomításnak az alábbi két fajtája van:
- Eljárásszerűen definiált finomítás
- Függvényszerűen definiált finomítás
1.) Eljárásszerű finomítás
A finomítások eljárásszerű definiálásának alakja az alábbi:
név:
utasítások
.
Megjegyzés: eljárásszerű finomítás esetén a finomítás neve utasítások helyett használható.
2.) függvényszerű finomítás
A finomítást nemcsak eljárásként, hanem függvényként is használhatjuk.
A finomítások függvényszerű definiálásának alakja az alábbi:
név:
utasítások
kifejezés
.
A függvényszerű finomítás utolsó utasítása helyén tehát egy kifejezésnek kell állnia, ami a finomítás értéke lesz, azaz az adott függvényszerű finomítás meghívásakor ennek a kifejezésnek az értéke adódik vissza eredményként. Fontos, hogy a függvényszerű finomításnak csak az utolsó utasítása helyén állhat kifejezés. Ha a függvényszerű finomítás végén elágazás van, akkor az adott elágazásban minden ágnak ugyanolyan típusú kifejezéssel kell végződnie.
Az utolsó utasítás feltételes kifejezés is lehet.
Példa:
nagyobb:
a>b.
A 'nagyobb' nevű függvény egy logikai értéket ad vissza eredményül. Ez a logikai érték akkor egyenlő TRUE-val (azaz a nagyobb függvény akkor ad vissza logikai igaz értéket), ha az 'a' nagyobb b-nél, és akkor egyenlő FALSE-zal (azaz a nagyobb függvény akkor ad vissza logikai hamis értéket), ha az 'a' nem nagyobb b-nél (azaz ha az 'a' kisebb mint b, vagy ha az 'a' egyenlő b-vel). A 'nagyobb' nevű függvényt ezután például elágazások feltételéül használhatjuk:
IF nagyobb
THEN ...
Megjegyzés: függvényszerű finomítás esetén a finomítás neve kifejezések elemeként használható.
Példa:
program:
put("Kérek 35 forintot!");
get(ft);
line;
IF sok
THEN Adj vissza
ELIF kevés THEN Kérj még
FI
.
sok:
ft>35
.
kevés:
ft<35
.
Adj vissza:
put("Visszaadok ");
put(ft-35);
put(" forintot");
line
.
Kérek még:
put("Még kérek ");
put(35-ft);
put(" forintot");
line
.
Megjegyzés: a fenti példában függvényszerű finomítások a sok és a kevés, és eljárásszerű finomítások az Adj vissza és a Kérek még.
Megjegyzés: Az ELAN fordító a finomításokat speciálisan kezeli, hatékonysági szempontok alapján eldönti, hogy külön helyre fordítja és a használat helyére egy eljáráshívó utasítást generál, vagy pedig bemásolja a hívás helyére.
4.7. Megjegyzés
A megjegyzéseket ELAN-ban #-jelek közé kell tenni, tetszőleges utasítás helyén szerepelhetnek:
A megjegyzések használatának alakja az alábbi:
# tetszőleges szöveg #