10. Eljárások és függvények
Eljárások és paraméterek
Nagyobb feladatot célszerû (már algoritmus-szinten is) lépésekre bontani. Továbbá, vannak olyan tevékenységek, melyeket a programban több helyen is el kell végezni. Ilyen lehet a figyelmeztetõ sípolás:
sound(880); delay(50); nosound;
Az ilyen rész-tevékenységeket külön egységbe foglalhatjuk, ezek neve alprogram (subroutine) avagy eljárás (procedure). Az eljárásoknak azonosítójuk van, és a deklarációs részben adjuk meg õket a következõképpen:
Mint látható, a saját deklarációs rész miatt az eljárás valóban önálló programként viselkedhet. A saját deklarációs részben nem szerepelhet a Program és a Uses utasítás. Példa a sípoló eljárásra:
Procedure Beep; {ennek az eljárásnak
nincsenek paraméterei}
Begin {sem deklarációs
része}
sound(880); delay(50); nosound;
End;
Az eljárásokat a nevükkel indíthatjuk el a fõprogramból vagy más eljárásokból (természetesen csak akkor, ha az eljárás deklarációja megelõzte az eljárásra való hivatkozást). Ez az eljáráshívás:
VAR a:integer;
BEGIN
Repeat
readln(a);
if a=0 then beep; {eljáráshívás}
Until a<>0;
Writeln(1/a); beep; beep;
END.
Így az eljárások pontosan úgy mûködnek, mint a Pascal saját utasításai. Ha úgy tetszik, a Pascal utasításkészletét bõvítettük, amikor egy azonosítóhoz hozzárendeltünk egy tevékenységet.
Ha azután az egyszerû sípszót bonyolultabb dallamra akarjuk átírni, csak a Beep eljárásban kell elvégezni a változtatásokat. Például füttyszóhoz:
Procedure Beep;
var i:integer;
Begin
for i:=300 to 500 do begin
sound(i); delay(5); nosound;
end;
End;
Ez az eljárás használ egy saját változót is. Miután az eljárást megírtuk, nem foglalkozunk többet vele, hanem a program más részeire összpontosítjuk figyelmünket. Éppen így segítenek az eljárások a programozásban: a feladatot részekre (a programot eljárásokra) bontva mindig csak egy részfeladattal foglalkozunk. De mi történik, ha a fõprogramban máshol is használunk egy i változót?
Az eljárás belsejében deklarált saját, avagy lokális változók kívülrõl, vagyis az eljárást hívó programból láthatatlanok: az eljárás hívásakor keletkeznek, és az alprogram lefutása után megszûnnek. Ha a fõprogramnak van azonos nevû változója, azt a Pascal az eljárás mûködésének idejére elraktározza.
Az eljárás tudja használni mindazokat a saját változóitól eltérõ nevû változókat, melyeket az eljáráson kívül, elõtte deklaráltunk. Ezek az eljárás szempontjából külsõ, azaz globális változók. Példa:
VAR a,b:integer;
Procedure Valami;
Var a:integer;
Begin
a:=5; {lokális változó}
b:=7; {a fõprogram
globális változója}
End;
BEGIN
a:=1;
b:=2;
Valami;
Writeln(a,b);
END.
A program 1-et ír ki (mert a fõprogram globális a változóját nem zavarta az eljárás azonos nevû lokális a változója), és 7-et (mert a b az eljárásban is globális változó volt).
A Pascal legtöbb utasítása paramétert is kap híváskor. Hasonlóképpen az eljárást is lehet paraméterezni. A paraméterlista a változódeklarációhoz hasonlóan a paraméterek azonosítóját és típusát tartalmazza. Példa egy karaktert adott helyre kiíró eljárásra:
Procedure Kiirxy(x,y:integer;c:char);
Begin
gotoxy(x,y); write(c);
End;
A paraméterek az eljárásban lokális változókként viselkednek, azzal a különbséggel, hogy nem az eljáráson belül kapnak értéket, hanem az eljárás hívásakor, kívülrõl:
VAR i:integer;
BEGIN
For i:=1 to 10 do
Kiirxy(10,i,'*');
END.
Például amikor az i értéke 3, az eljárás hívásakor az egyes paraméterek értéke: x=10, y=3, c='*' lesz. Vagyis, eljáráshíváskor a hívó utasításban lévõ értékeket veszik fel az eljárás paraméterei. Ez az érték szerinti paraméterátadás.
Elõfordul, hogy az eljárásnak változókat szeretnénk átadni, és ezekkel kell valamilyen mûveletet végezni, tehát a hívó program változóit kell változtatni. Ezt megoldhatjuk úgy is, hogy globális változókat használunk, melyeket tud kezelni az eljárás, de akkor a program áttekinthetetlenebb lesz, mert az eljárás önállósága megszûnik. Erre a célra használható a cím szerint paraméterátadás, más néven a változóparaméterek. Ekkor paraméterként nem értéket adunk át, hanem változót, és ezt a paraméterlistában Var szóval jelöljük:
Procedure Csere(Var a,b:integer);
Var m:integer;
Begin
m:=a; a:=b; b:=m;
End;
VAR p,q:integer;
BEGIN
p:=8;
q:=4;
Csere(p,q);
Writeln(p,q);
END.
Ez a program a 4,8 számokat írja ki. Ha a var szócskát nem írtuk volna a paraméterlista elejére, a fõprogram változóival semmi nem történt volna, csak az eljárás lokális változóiban cseréltük volna fel az értékeket. A var szó hatására a következõ történik: eljáráshíváskor létrejön az eljárás lokális a és b változója, de ezek a változók ugyanarra a memóriacímre mutatnak, mint a fõprogram p és q változói. Tehát akármilyen mûveleteket végzünk az a és b változókkal, ugyanaz fog történi a fõprogram p és q változóival. Így a Csere eljárást nem is lehet számokkal meghívni, csak integer típusú változókkal.
Használhatunk változó- és közönséges paramétereket egyszerre is: a
procedure valami(s:string;var c:integer)
deklarációnál s közönséges, c pedig változóparaméter. A Pascal több utasítása is használ változóparamétert, pl. az Initgraph.
Függvények
A függvények pontosan úgy mûködnek, mint az eljárások, azzal a különbséggel, hogy visszatérési értéket is szolgáltatnak. A visszatérési értéket a függvény törzsében a függvénynév:=érték utasítással állíthatjuk be. A függvény deklarálásakor jelezni kell a visszatérési érték típusát, mely csak elemi típus lehet.
Function Kob(a:real):real;
Begin
Kob:=a*a*a;
End;
BEGIN
writeln(Kob(65));
END;
A függvény ezeken kívül ugyanúgy mûködik, mint egy eljárás. Nem elegáns azonban, ha a függvény a visszatérési érték kiszámításán kívül mást is csinál (mellékhatások). Ilyen esetekben inkább használjunk eljárást, és a visszatérési értéket változóparaméterrel adjuk vissza a hívó programnak.
A Pascalban megfelelõ beállítás esetén a függvényeket eljárásként is meghívhatjuk: ekkor csak a függvény mellékhatása jelentkezik. Például a Readkey függvényt utasításként használva a program egy billentyû lenyomásáig várakozik.
Még egy példa:
Function maxi(a,b:integer):integer;
Begin
if a>=b then Maxi:=a else Maxi:=b;
End;
A Pascal kiegészítésként felsorolt néhány szövegkezelõ eljárása és függvénye jó példát ad a változóparaméterek használatára. Láthatjuk: vagy függvényt, vagy változóparaméteres eljárást használunk a visszatérési érték megkapásához.