background image

Procedury i funkcje 

 

Pisanie własnych procedur i funkcji w pascalu 

 

Procedura i funkcja to kilka instrukcji połączonych w grupę, instrukcji -które robią określoną 
rzecz. Np. wypisują coś na ekranie, zmieniają kolor, rysują tabelki. Procedura może 
wykorzystywać inne napisane przez Ciebie procedury i funkcje. 

 

Może zastanowisz się po co wogóle pisać procedurę czy funkcję. Przecież można napisać 
program jednym ciągiem. Faktycznie dla bardzo małych zadań jest to nawet praktyczne. 
Sprawa utrudnia się gdy chcesz stworzyć rozbudowaną grę lub nawet niewielki program. 

 

Przy dużych ilościach kodu, w którym wszystko jest w każdym miejscu nie jest łatwo 
zapamiętać pozycji każdej najdrobniejszej instrukcji. Dodatkowo, gdy chcesz żeby program w 
kilku miejscach robił to samo musisz kopiować kod i go wklejać. Potem gdy będziesz chciał 
zrobić jakąś poprawkę, będziesz musiał znaleźć każde miejsce z błędem i je udoskonalić. 

 

Procedury rozwiązują ten problem. Jedna procedura może wykonywać jedną konkretną 
czynność. Małe procedurki mogą być wywoływane przez większe i w rzeczywistości często 
dobre gry składają tylko z trzech procedur: inicjacji, startu gry i finalizacji czyli czyszenia 
pamięci. Procedury pozwalają więc zachować porządek 

 

Istnieje możliwość wyjścia z procedury, bez wykonania pełnego kodu. Służy do tego 
Instrukcja Exit; Wykorzystuje się ją w przypadku, gdy któryś z parametrów podanych do 
procedury nie spełnia założeń programisty. Gdy wywołasz Exit, wykonywanie kodu wznowi 
się zaraz przed zakończeniem kodu procedury -w miejscu end; tej instrukcji. 

 
 
Czym różni się funkcja od procedury 

Procedura wykonuje czynność i się zakańcza. Funkcja po wykonaniu się zwraca jakiś wynik 
operacji, dzięki czemu można ją traktować prawie jak zmienną. Jednak nie zawsze tą wartość 
zwróconą musisz wykorzystać. Możesz po prostu wykonać funkcję w taki sposób jak 
uruchamiałbyś procedurę. 

 

background image

przykłady 
 procedura:   Czysc_Ekran; WriteLn('tekst'); 
 funkcja: x:= PozycjaMyszyX; y:= PozycjaMyszyY lub size := FileSize(...) 
 
 
Schemat budowy procedury 

Na początku programu można zdefiniować nagłówek, jeśli ta procedura ma być widoczna w 
całym pliku (koniecznie gdy piszesz moduł i będziesz jej używał poza modułem). Liczba 
parametrów procedury może być dowolna. Każdy z parametrów ma określony typ. 

 

Nazwa jaką nadamy parametrowi (np. parametr1) nie ma żadnego znaczenia na zewnątrz tej 
procedury. Użyjemy jej tylko w kodzie wewnętrznym. Gdy będziemy później odwoływali do 
tej procedury, będziemy mogli jako parametr używać różnych nazw zmiennych. 

 

program nazwa; 
uses Crt; {moduły} 
 
var {deklaracja zmiennych} 
  zmienna : Byte; 
 
{nagłówek procedury} 
procedure NazwaProcedury(parametr1:typ; parametr2:typ2); 
 
{Inne procedury} 
 
{...} 
{ciało procedury} 
procedure NazwaProcedury(parametr1:typ; parametr2:typ2); 
begin {początek procedury} 
 {tu może być kod wykonywalny} 
end; {koniec} 
 
begin 
  {główna część programu} 
 
 {wywołanie tej procedury} 
 NazwaProcedury(parametr1, parametr2); 
end. 
 

Inne przykłady procedur: 

 
 
Czekanie na wciśnięcie klawisza Enter 

background image

procedure CzekajNaEnter; 
begin 
 WriteLn('Prosze wcisnac ENTER'); 
 ReadLn; 
end; 
 
begin 
 WriteLn('Witaj w programie'); 
 CzekajNaEnter; 
end. 
 

wynik działania programu: 

 
Witaj w programie 
Prosze wcisnac ENTER 
 

w tym wypadku procedura CzekajNaEnter; będzie wyświetlała komunikat i oczekiwała na 
wciśnięcie klawisza. 

 
 
Schemat budowy funkcji 

Na początku programu można zdefiniować nagłówek, jeśli ta funkcja ma być widoczna w 
innych plikach (koniecznie gdy piszesz moduł) lub wywołujesz ją gdzieś na początku kodu a 
jej treść jest za wywołaniem (tak samo jak w przypadku procedury) 

 

Wewnątrz kodu funkcji powinno znaleźć się przypisanie jej jakiejś wartości zwrotnej 

 
{nagłówek} 
function NazwaFunkcji(parametr1:typ; parametr2:typ2): typ 3; {funkcja musi zwrocic jakas 
wartosc, wiec posiada swoj typ} 
 
{...} 
{ciało funkcji} 
function NazwaFunkcji(parametr1:typ; parametr2:typ2): typ 3; 
begin {początek funkcji} 
 {tu może być treść} 
 NazwaFunkcji:=wartosc; 
end; {koniec} 
 
begin 
 a:=NazwaFunkcji(zmienna1, zmienna2); 
 {dopuszczalne również} 

background image

 NazwaFunkcji(zmienna1, zmienna2); 
end. 
 
 
Mnożenie dwóch liczb 
function Pomnoz(a, b : integer) : Longint; 
begin 
  Pomnoz := a*b; 
end; 
 
begin 
  WriteLn('wynik 2*5 to ', Pomnoz(2, 5)); 
end. 
 

wynik działania programu: 

 

wynik 2*5 to 10 
 
 
Obliczanie silni za pomocą rekurencji 

W rozdziale dotyczącym pętli została opisana metoda rekurencji (wywołania w procedurze 
lub funkcji samej siebie).  Poniżej pokazano jak poradzić sobie z obliczeniem silni za pomocą 
rekurencji. 

 

program obliczanie_silni; 
 
function silnia(l : LongInt) : Longint; 
begin 
 if l <= 1 then silnia:= 1 
 else silnia := silnia(l - 1) * l; {wywołanie samej siebie} 
end; 
 
begin 
 WriteLn(silnia(5)); {wynik: 120} 
end. 
 

Przekazywanie parametrów 

 
Standardowe przekazywanie parametrów 

Można przekazywać dowolną ilość parametrów do funkcji lub procedury. Oddziela się je 
średnikami. Każdy z parametrów ma własny typ. Zmienne podawane zazwyczaj w 
parametrach są kopiowane w inny obszar pamięci i właśnie do tego obszaru ma dostęp 

background image

programista. Ponieważ komputer wykonuje kopię parametrów, nie należy przekazywać zbyt 
dużej ilości danych, by nie spowolnić działania programu. Zaleca się przekazywać do ośmiu 
bajtów. 

 
 
Przekazanie przez referencję 

Gdy przekazujemy parametry do funkcji lub procedury, może zajść potrzeba zmiany 
wielkości jakiegoś parametru. Wtedy trzeba ominąć mechanizm tworzenia kopii parametru, 
by pracować na orginalnej zmiennej. Używa się do tego słowa kluczowego var. Teraz zmiana 
parametru wewnątrz funkcji, zmieni go także na zewnątrz. 

 
var tmp : string; 
 
procedure WczytajNapis(var s : string); 
begin 
 WriteLn('Prosze podac napis'); 
 ReadLn(s);{wczytujemy do zmiennej na zewnątrz} 
end; 
 
procedure WczytajNapisBezVar(s : string); 
begin 
 WriteLn('Prosze podac napis'); 
 ReadLn(s); {Wczytujemy do kopii zmiennej} 
end; 
 
begin 
 tmp := 'Ala ma kota'; 
 WczytajNapisBezVar(tmp); {nazwa tmp może być inna niż w nagłówku procedury} 
 WriteLn(tmp); {tmp dalej ma wartość Ala ma kota pomimo zmian wewnątrz procedury} 
 
 WczytajNapis(tmp); 
 WriteLn(tmp); {Teraz tmp będzie takie jakie wczytano z klawiatury} 
end. 
 

Gdybyśmy nie użyli słowa kluczowego var przed podaniem parametru s: string, 
pracowalibyśmy na kopii zmiennej podanej do procedury. Wtedy zmienienie jej wewnątrz 
procedury nie miałoby znaczenia po powrocie do normalnego programu. Zmienna tmp dalej 
miałaby tą wartość co przed wywołaniem procedury. 

 
 
Przekazanie parametru przez stałą 

Gdy przekazujemy do procedury lub funkcji duże ilości danych, np. napisy, czyli typ string, 
komputer wykonuje kopię napisu, 256 bajtów. Dla dzisiejszych komputerów to nie dużo, ale 
gdyby taka procedura wykonywała się milion razy w ciągu sekundy, spowodowałaby duże 

background image

spowolnienie z powodu niepotrzebnego kopiowania pamięci. Dlatego właśnie można 
przekazywać dane za pomocą słowa kluczowego const. Spowoduje to przekazanie jedynie 
adresu pamięci, w którym jest zmienna. Niestety program nie pozwoli nam na edycję 
parametru, bo nie pracujemy na kopii. 

 
var tmp : string; 
 
procedure WyswietlString(const s : string); {przekazanie parametru przez const} 
begin 
 WriteLn('Napis to ', s); 
end; 
 
begin 
 tmp := 'Ala ma kota'; 
 WyswietlString(tmp); 
end. 
 
 
Przekazywanie parametru przez wskaźnik (pointer) 

Przekazanie zmiennej za pomocą wskaźnika oznacza, że do procedury przesyłamy adres 
pamięci, w której będzie interesująca wartość. Wiąże się to również z pewnym ryzykiem. 
Przekazując błędny adres działanie programu zostanie przerwane przez system. 

 

Temat wskaźników został objaśniony w rozdziale struktur danych. 

 

Kiedy pisać nową procedurę 

 

Właściwe wykorzystanie mechanizmu procedur pozwoli efektywnie i szybko tworzyć kod 
programu. Procedurę tworzymy, gdy ma to uzasadnienie. 

 

• 

Jeśli choć 2 razy używamy tego samego kodu programu 

• 

gdy ma określone zadanie -jest osobnym tematem 

• 

gdy w przyszłości planujemy pewne zmiany w obliczaniu jakiejś wartości 

 

Procedury należy konstruować tak, by mogły z nich korzystać inne procedury. Staraj się tak je 
układać, by były wykorzystywane jak najczęściej i oszczędzały jak najwięcej pisania kodu. 
Czasem warto zbudować kilka poziomów procedur, z których każda będzie odpowiadała za 
coraz to poważniejsze operacje. 

background image

 


Document Outline