Alapvető vezérlési szerkezetek

Ebben a fejezetben az Object Pascal (későbbiekben OP) nyelv legalapvetőbb vezérlőegységeivel ismerkedhetünk meg. Ezeknek az egységeknek a pontos megtanulása, megértése és egyértelmű alkalmazása nagyon fontos, hiszen egy komolyabb program felépítésében mindezek felhasználása nélkülözhetetlen. A következő részekben teljes egészében tárgyalom a következőket:

1.                 Feltételes elágazás (if)

2.                 Többágú szelekció (case)

3.                 Ciklusok (for, while, repeat)

4.                 A break és a continue utasítások

5.                 A with utasítás

6.                 A goto utasítás

Feltételes elágazás

Egy program végrehajtása során a gép az elemi utasításokat sorban, egymás után hajtja végre. Ennek során számos esetben előfordulhat olyan eset, amikor valamilyen döntést kell hozni, hogy az alapján elágaztassuk a programunkat egy vagy több irányban. Ilyen esetekben nem mindegy, hogy melyik rész kerül végrehajtásra. Az ilyen, feltételes elágaztatásra találták ki a Pascalban az if utasítást, melynek általános formája a következő:

if feltétel then

utasítás1

else

utasítás2;

Az if utasítás megvizsgálja az őt követő feltétel-t (mely egy logikai kifejezés), s ennek eredményeképpen hoz döntést. Ha a kifejezés kiértékelésének eredménye igaz, akkor a then ág utáni utasítás1, egyébként az else ág utáni utasítás2 kerül végrehajtásra. Fontos, hogy az else szó előtt ne legyen pontosvessző (;), mert akkor azt a fordító az if utasítás rövidített változatának tekinti, s mivel az else szó önmagában semmire sem használható, ezért a fordítás hibaüzenettel leállna. A rövidített változat abban különbözik az előzőtől, hogy feltétel vizsgálat után csak akkor van elágazás a programban, ha a feltételvizsgálat eredménye igaz, egyébként az eredeti folytatódik tovább.

if feltétel then

utasítás;

Ugyancsak fontos még, hogy ha az if utasítás után még újabb utasításokat szeretnénk elhelyezni, akkor azokat programblokkba (begin end) tegyük. Megjegyzem, hogy az if utasítások egymásba is ágyazhatók.

Az 1. és 2. ábrán az if általános, illetve rövid formájának folyamatábrája látható:

1. ábra

 

2. ábra

 

Az elmondottakra vonatkozóan nézzünk meg egy konkrét feladatot! A program kérjen be egy egész számot a felhasználótól, majd állapítsa meg róla, hogy páros-e vagy páratlan.

program Vizsgal;

{$APPTYPE CONSOLE}

 

const

v = ’A megadott szam ’;

 

var

szam : Integer;

 

begin

Writeln (’Szam viszgalata’);

Writeln;

Write (’Kerek egy szamot: ’);

Readln (szam);

if szam mod 2 = 0 then

Writeln (v + ’paros!’)

else

Writeln (v + ’paratlan!’);

Readln;

end.

Többágú szelekció

A többágú szelekciót akkor használjuk, amikor egy adott kifejezés eredményét elemezzük ki, amelynek során több lehetséges értéket kívánunk megvizsgálni, amelyek száma akár több száz is lehet. A feladatot megoldhatjuk az előző részben ismertetett if utasítással is, de a szelekciós változat jobb, kényelmesebb megoldást biztosít.

case kifejezés of

érték1 : utasítás1;

érték2 : utasítás2;

...

értékN : utasításN;

else

egyébként_utasítás;

end;

A case szó után álló kifejezés egy sorszámozott típus lehet. Ez alapján dönti el a fordító, hogy az érték1, érték2, …, értékN a vizsgált kifejezés-sel megegyezik-e. Ha igen, akkor az azt követő kettőspont (:) után álló utasítást hajtja végre. Ha pedig nem, akkor az else résznél lévő utasítások kerülnek (egyébként_utasítás) végrehajtásra, amennyiben van ilyen. Ennél az utasításnál az else elé muszáj pontosvesszőt rakni (mivel az else rész elhagyható), valamint az utasítást az end–del kell lezárni! A 3. ábrán látható a case utasításnak a folyamatábrája.

Feladat: írjunk egy kalkulátort, mely a case szekvenciát használja a művelet eldöntésére!

program Kalkulator;

{$APPTYPE CONSOLE}

 

var

a, b, e : Extended;

muv     : Char;

 

begin

e := 0.0;

Writeln (’Kalkulator’);

Writeln;

Write (’1. adat: ’); Readln (a);

Write (’2. adat: ’); Readln (b);

Write (’Muveleti jel: ’); Readln (muv);

case muv of

’+’ : e := a + b;

’-’ : e := a – b;

’*’ : e := a * b;

’/’ : if b <> 0

then

e := a / b

else

begin

Writeln (’Hiba, az oszto nulla!’);

Halt;

end;

else

Writeln (’Ervenytelen muveleti jel!’);

Halt;

end;

Writeln;

Writeln (’Az eredmeny: ’, e : 8 : 2);

Readln;

end.

3. ábra

 

Ciklusok

Ebben a részben tárgyaljuk a ciklusokat, vagy más néven az iterációkat. Ciklusokat akkor szokás alkalmazni, amikor ugyanazt a programrészt többször kell végrehajtani. Az OP nyelv három ciklus használatát teszi lehetővé. Ebből az egyik a számláló ciklus (for), a másik kettő az úgynevezett „tesztelős” ciklus (while, repeat). Az utolsó két ciklus neve onnan ered, hogy valamilyen feltételtől függően működnek. A továbbiakban tekintsük át ezeket részletesebben!

 

A for ciklus

Ezt a ciklust akkor használjuk, amikor pontosan meg tudjuk nevezni az ismétlések számát. Remek példa erre a tömbök kezelése. A for, while, repeat ciklusban lévő végrehajtandó utasításokat szokták a ciklus magjának is nevezni. Két fajtája létezik, mégpedig a következők:

 

for ciklusváltozó := kezdőérték to végérték do

utasítás;

 

for ciklusváltozó := kezdőérték downto végérték do

utasítás;

Ezek a ciklusok úgy működnek, hogy először a ciklusváltozó fölveszi a kezdőértéket , majd ha a kezdőértékvégérték (1. ciklus), vagy kezdőértékvégérték (2. cikus), akkor a ciklus magjában lévő utasítások kerülnek végrehajtásra, ami után a ciklusváltozó 1-gyel nő (1. eset) vagy csökken (2. eset). Fontos, hogy a ciklusváltozó, a kezdőérték és a végérték is sorszámozott típusú legyen. A ciklusváltozót a ciklusmagon belül és kívül egyaránt fel lehet használni. A 4. ábrán látható ennek folyamatábrája.

1 feladat: deklaráljunk egy 20 elemű egész vektortömböt, majd töltsük azt fel véletlen-számokkal! A feltöltés után adjuk össze a tömb elemeit, majd jelenítsük meg azt a képernyőn!

program Tomb;

{$APPTYPE CONSOLE}

 

var

t    : array [0..19] of Word;

ossz : LongInt;

i    : Integer;

 

begin

Randomize;

ossz := 0;

Writeln (’Tomb feltoltese veletlenszeru szamokkal’);

Writeln;

for i := 0 to 19 do

begin

t[i] := Random (High (Word)) + 1;

Writeln (i + 1, ’. elem: ’, t[i]);

Inc (ossz, t[i]);

end;

Writeln;

Writeln (’Az osszeg: ’, ossz);

Readln;

end.

2 feladat: Írjuk ki a képernyőre egymás alá az ASCII kódtáblázat elemeit 90-től 70-ig!

program ASCII;

{$APPTYPE CONSOLE}

 

var

i : Integer;

 

begin

for i := 90 downto 70 do

Writeln (Chr (i));

Readln;

end.

4. ábra (cvciklusváltozó, kezdőérték, - végérték)

 

 

A while ciklus

A while ciklust akkor használjuk, amikor nem tudjuk pontosan megadni az ismétlődések számát, vagy a ciklus végrehajtásának száma egy feltételtől függ. A while ciklust előltesztelőnek nevezzük, mivel a ciklus lefutása előtt egy feltétel alapján dől el, hogy a ciklusmag lefusson-e vagy sem. Szerkezete:

 

while feltétel do

utasítás;

 

A feltétel (mint az if utasításnál is) egy logikai kifejezés. Ha ennek a kiértékelésének az eredménye hamis, akkor a ciklus egyszer sem fog lefutni. Igaz érték esetén mindaddig fut, amíg hamissá nem válik. Vigyázzunk, mert ha a ciklus nem tartalmaz olyan utasítást, amely a feltétel kiértékelési eredményét megváltoztatná, akkor úgynevezett végtelen ciklust kapunk. Folyamatábráját az 5. ábra mutatja. Általánosságban elmondható az is, hogy a for ciklusok while ciklusokká írhatók át.

Feladat: készítsünk egy olyan programot, ami addig kéri a felhasználótól a jelszót, amíg el nem találja!

program Jelszo;

{$APPTYPE CONSOLE}

 

const

j = ’Object Pascal’;

 

var

jsz : string;

 

begin

Writeln (’Jelszo megadasa’);

Writeln;

jsz := ’’;

while jsz <> j do

begin

Write (’Kerem a jelszot: ’); Readln (jsz);

if jsz <> j then

Writeln (’Hibas jelszo!’);

end;

Writeln (’Eltalaltad!’);

Readln;

end.

 

5. ábra

 

A repeat ciklus

Erről a ciklusról is ugyanaz mondható el, mint a while ciklusról. A kettő közötti különbség csak az, hogy ez nem elől-, hanem hátultesztelős, vagyis a feltétel vizsgálata a ciklus legvégén van. Ebből az következik, hogy a ciklus legalább 1-szer le fog futni. A következő szerkezettel látták el:

 

repeat

utasítás;

until feltétel;

 

Működése is majdnem megegyezik az előző cikluséval. Lényeges eltérés, hogy a ciklus addig fut, amíg a feltétel igazzá nem válik. A ciklusmagban szereplő utasításokat nem kötelező programblokkba helyezni. Folyamatábráját a 6. ábra szemlélteti.

Feladat: a program addig kérjen be adatokat a felhasználótól, míg az 0 és 1000 közé nem esik!

program Ellenoriz;

{$APPTYPE CONSOLE}

 

var

szam : LongInt;

 

begin

Writeln (’Kerek egy szamot 0 es 1000 kozott!’);

Writeln;

repeat

Write (’Szam: ’); Readln (szam);

until (szam > 0) and (szam < 1000);

Writeln;

Writeln (’Na Vegre!’);

Readln;

end.

6. ábra

A break és a continue utasítások

Számos olyan helyzet állhat elő, amikor egy ciklusból valamilyen ok miatt ki kell lépni, vagy esetleg ki kell hagyni a hátralévő utasításokat. Ilyen esetekre kiváló megoldást kínál a break és a continue utasítás.

A break utasítás kiléptet az aktuális ciklusból és a program végrehajtása a ciklus utáni következő utasításra tér.

A continue utasítás hatására a program átugorja a ciklusmag további utasításait (amennyiben van ilyen).

1. feladat: a continue utasítást használva írjuk ki a képernyőre 1-től 20-ig a páratlan számokat!

program Paratlan;

{$APPTYPE CONSOLE}

 

var

i : Integer;

 

begin

Writeln (’1-20-ig a paratlan szamok:’);

Writeln;

for i := 1 to 20 do

begin

if i mod 2 = 0 then

continue;

Writeln (i);

end;

Readln;

end.

2. feladat: egy felhasználó által megadott szövegből (maximum 255 karakter) a program addig írja vissza a képernyőre ugyanazt a szöveget, addig, amíg számjegyet nem talál!

program Ir;

{$APPTYPE CONSOLE}

 

var

s : string;

i : Integer;

 

begin

Writeln (’Szoveg megadasa’);

Writeln;

Write (’Kerem a szoveget: ’); Readln (s);

Writeln;

Write (’A beirt szoveg az elso szamjegy elofordulasaig: ’);

for i := 1 to Length (s) do

begin

if (s[i] >= ’0’) and (s[i] <= ’9’) then break;

Write (s[i]);

end;

Writeln;

Readln;

end.

A with utasítás

A rekordok mezőihez hozzáférni mindig a rekord_változó.mező utasítással tudunk. Több mezővel rendelkező rekord esetén ez a felírási mód igencsak fárasztó és hosszadalmas. Ennek kiküszöbölésére találták ki a with utasítást, melynek formája:

 

with rekord_változó do

utasítás;

 

Használatakor a rekord mezői közvetlenül érhetőek el a rekord_változó kirakása nélkül is. Objektumok, osztályok esetében is megállja a helyét.

 

Feladat: a felhasználó által bevitt adatok egy ’szemely’ nevű rekordba kerüljenek, a with utasítás felhasználásával! A megadott adatok íródjanak az ’Adat.dat’ nevű állományba!

 

program WithPelda;

{$APPTYPE CONSOLE}

 

uses SysUtils;

 

type

RSzem = record

nev : string;

kor : Integer;

nem : 0..1;       //0 – férfi, 1 - nő

end;

 

var

szemely : RSzem;

F       : TextFile;

 

begin

Writeln (’Szemely adatainak megadasa’);

Writeln;

AssignFile (F, ’Adat.dat’);

if FileExists (’Adat.dat’) then

Append (F)

else

ReWrite (F);

with szemely do

begin

Write (’Neve : ’); Readln (nev); Writeln (F, nev);

Write (’Kora : ’); Readln (kor); Writeln (F, kor);

Write (’Neme : ’); Readln (nem); Writeln (F, nem);

end;

Readln;

CloseFile (F);

end.

A goto utasítás

A goto utasítás segítségével egy címkével kijelölt területre ugorhatunk, átlépve a soron következő utasítást, vagy visszatérve az előző utasítás(ok)ra (a címkét felhasználása előtt deklarálni kell):

 

goto utasításcímke;

 

Ez az utasítás lehetővé teszi a belső blokkból a külsőbe való ugrást, de fordítottan ez nem lehetséges. Eljárásokból, függvényekből (közös néven alprogramokból) nem ugorhatunk ki, de be sem!

Az alábbi példa illusztrálja a goto működését:

 

program GotoPelda;

{$APPTYPE CONSOLE}

 

label

ide, oda, amoda;

 

begin

Writeln (’1. blokk’);

begin

Writeln (’2. blokk’);

begin

Writeln (’3. blokk’);

goto ide;

Writeln (’Ez az uzenet soha nem fog megjelenni!’);

end;

Writeln (’Ez is!’);

ide:

Writeln (’2. blokk kozepe’);

goto amoda;

end;

amoda:

Writeln (’1. blokk vege!’);

Readln;

end.

 

Ezekben a részekben megtanulhattuk az OP nyelv legalapvetőbb vezérlési szerkezeteit, példákkal illusztrálva azokat. A későbbiekben is sikeres programozást, és jó munkát kívánok!

Veres Ádám