Pascal pro začátečníky 8 - Procedury a funkce
Zdroj: SOOM.cz [ISSN 1804-7270]
Autor: Kub@z
Datum: 13.4.2004
Hodnocení/Hlasovalo: 1.95/65
Pojem procedura znamená část kódu, který tvoří jakýsi podprogram.
Zatím jsme zadávali příkazy pouze mezi "begin" a "end.". Ale když
budete chtít nějakou část programu vykonat několikrát, nemusíte ji...
Procedury
Pojem procedura znamená část kódu, který tvoří jakýsi podprogram.
Zatím jsme zadávali příkazy pouze mezi "begin" a "end.". Ale když
budete chtít nějakou část programu vykonat několikrát, nemusíte ji
několikrát psát, ale vložíte ji do procedury. Vše objasní příklad:
procedure ahoj;
begin
writeln('Ahoj lidi');
writeln('Jak se mate?');
end;
begin
ahoj;
ahoj;
ahoj;
end.
Tento program vypíše 3x text uvedený v proceduře "ahoj".
Procedura se tedy deklaruje klíčovým slovem "procedure",
následuje jméno procedury a parametry. Parametry jsou
hodnoty předané proceduře:
procedure ahoj(kdo: string);
begin
writeln('Ahoj '+kdo);
end;
begin
ahoj('Petře'); (* vypíše "Ahoj Petře" *)
ahoj('Jano'); (* vypíše "Ahoj Jano" *)
ahoj('Honzo'); (* vypíše "Ahoj Honzo" *)
end.
Program vypíše 3x Ahoj + zadaný text. Deklarace parametrů se
píše za jméno do závorek, jako deklarace proměnných a také
uvedený parametr používáme jako proměnnou. Pokud chcete použít
více parametrů, oddělují se čárkami:
procedure ahoj(kdo,pozdrav: string)
a pokud chcete použít více parametrů různého typu, oddělují se středníkem:
procedure ahoj(kdo: string; cislo: integer)
V proceduře je také možné deklarovat lokální proměnné.
Lokální proměnná je proměnná použitelná pouze v proceduře,
kde je deklarována a nikde jinde. Naproti tomu globální
proměnnou je možné použít kdekoliv - jak v hlavním programu, tak ve všech procedurách:
var text: string;
procedure ahoj;
begin
writeln(text); (* vypíše proměnnou text *)
end;
begin
text := 'ahoj lidi';
ahoj;
writeln(text);
end.
Lokální proměnnou lze použít pouze v místě, kde je nadeklarována:
procedure ahoj;
var text: string;
begin
writeln(text); (* vypíše proměnnou text *)
end;
begin
text := 'ahoj lidi'; (* zde překladač zahlásí chybu *)
ahoj; (* proměnná text pro tuto část programu neexistuje *)
end.
Funkce
Teď už snad chápete, jak procedury fungují. Nyní se podívejme na
funkce. Funkce má stejnou stavbu jako procedura, akorát ještě vrátí
hodnotu způsobem "jménofunkce := hodnota". Pozor! Funkce může být
pouze základních typů Pascalu a ne vlastních strukturovaných.
Deklaruje se "function jmeno(parametry): typ". Příklad:
function dvakrat(co: integer): integer;
begin
dvakrat := co*2;
end;
begin
writeln(dvakrat(5));
end.
Tato funkce moc užitečná není, ale dají se samozřejmě
napsat i užitečnější. Příklad: zkuste vymyslet funkci,
která by počítala stranu "c" pravoúhlého trojúhelníka
a jako parametry by dostala strany "a" a "b". Napovím:
funkce pro odmocninu je "sqrt(číslo)" a datový typ pro
desetinná čísla je "real". Nevíte pořád jak na to? Chce
to vzpomenout si na známou rovnici "a
2+b
2=c
2" ze které
snadno zjistíte stranu "c": je to odmocnina z "a
2+b
2".
Pořád nic? No dobře, tady je řešení:
function stranac(a,b: real): real;
begin
stranac := sqrt(a*a+b*b);
end;
begin
writeln('Strana c (a=3,b=4): ',stranac(3,4));
end.
Zde bych ještě měl zmínit příkaz exit, který vyskočí
z procedury nebo funkce. To je vhodné především pro
ošetřování chyb. Příklad:
function vydel(co,cim: real): real;
begin
if cim = 0 then begin (* pokud se dělitel = 0 tak se z funkce vyskočí *)
writeln('Nelze delit nulou'); (* a vypíše se text "Nelze delit nulou" *)
vydel := 0; (* funkce vydel vrátí hodnotu 0, aby bylo jasné že neproběhla *)
exit; (* vyskočení *)
end;
vydel := co / cim; (* pokud se dělitel není nula, provede se dělení *)
end;
begin
writeln(vydel(50,8));
writeln(vydel(88.2,0)); (* zkusíme dělit nulou *)
end.
Kdyby to nebylo ošetřeno vyskočením z funkce, aplikace by hodila
"runtime error 200: division by zero". Tím se dostávám k dalšímu
problému. Jak se chránit před runtime errory pokud nemůžete nijak
zajistit ošetření chyby před jejím provedením? K tomu složí
direktiva překladače "{$I+}" a "{$I-}". Teď se asi ptáte,
co je to direktiva překladače. Direktiva slouží ke sdělení
zprávy o něčem překladači a není to příkaz - proto se píše
do komentáře (musí to být komentář typu "{ }"). Popis jednotlivých
direktiv najdete v nápovědě k překladači. Direktiva $I slouží ke
změně ošetření vstupních a výstupních chyb. Pokud použijete
direktivu "{$I-}", můžete pomocí funkce "ioresult" zjistit
zda nastala při poslední operaci chyba. Funkce "ioresult"
vrátí číslo chyby, a pokud chyba nenastala, vrátí hodnotu 0:
var f: file;
begin
assign(f,'neexistujici');
{$I-}
reset(f);
{$I+}
if ioresult <> 0 then writeln('soubor se nepodarilo otevrit');
end.
Zde uvedené funkce slouží k práci se soubory a
budou popsány v příští lekci. Program se pokusí
otevřít neexistující soubor. Nemohl jsem zde použít
minulý příklad, protože "{$I-}" nezachytí chybu při
dělení nulou, takže tu opravdu musíte ošetřit podmínkou.
Odkaz na proměnnou
No jo, ale jak to udělat, aby nám funkce vrátila hodnotu
jinou, než normálního Pascalovského typu? Použijeme odkaz
na proměnnou. V deklaraci procedury použijeme slovíčko "var":
procedure ahoj(var x: mujtyp);
Tím jsme řekli překladači, že "x" není proměnná jako parametr, ale
je to odkaz na proměnnou uvedenou ve volání procedury. Zjednodušeně
řečeno to znamená, že když přiřadíme hodnotu do "x" tak změníme
obsah proměnné uvedené v parametru zavolání funkce. Vím, zní to
sice trochu složitě, ale z příkladu je to hned jasné:
var prom: string;
procedure zmen(var txt: string);
begin
txt := 'Zmeneny text'; (* ve skutečnosti měníme hodnotu proměnné "prom" *)
end;
begin
prom := 'ahoj';
zmen(prom); (* Jako "var" parametr musí být vždy uvedena proměnná *)
writeln(prom); (* Vypíše "Zmeneny text" *)
end.
Stejným způsobem je to možné použít i u strukturovaných datových typů.
Kub@z