Podprogramy – procedury i funkcje

W trakcie tworzenia złożonych algorytmów niejednokrotnie zdarza się, że pewne zadania przez nie realizowane powtarzają się w wielu miejscach. Kiedy dotyczy to sekwencji prostych operacji, to można oczywiście zastosować pętlę, w której algorytm zostanie wykonany wielokrotnie.

Taka sytuacja nie zawsze ma jednak miejsce – zazwyczaj powtarzający się fragment kodu znajduje się w różnych miejscach algorytmu i zastosowanie wcześniej opisanych konstrukcji nie pozwala rozwiązać tego problemu.

Dlatego jednym z podstawowych udogodnień dostarczanych przez języki programowani są podprogramy czyli wydzielone algorytmy, które mogą być wielokrotnie wywoływane. W rzeczywistości procedury opisane wcześniej takie jak write czy read są właśnie podprogramami. Jednakże używanie tylko i wyłącznie wbudowanych procedur nie pozwoliłoby rozwiązać omawianego tutaj problemu, gdyż do efektywnego korzystania z podprogramów poza mechanizmem ich wywoływania potrzebny jest również mechanizm ich definiowania.

Podprogramy nie byłyby jednak tak użyteczne, gdyby nie to, że mogą być wywoływane z różnymiparametrami, które modyfikują działanie podprogramu. Na parametry podprogramu można również spojrzeć jak na dane wejściowe, które mają ulec przetworzeniu.

W języku Pascal istnieją dwa typy podprogramów: procedury i funkcje. Różnią się od siebie tym, że funkcje, w przeciwieństwie do procedur, zwracają wartości (dane wyjściowe). Ich działanie podobne jest zatem do funkcji matematycznych, które dla określonych argumentów produkują pewien określony wynik.

Zazwyczaj funkcje wykorzystuje się do przetworzenia danych wejściowych na dane wyjściowe, natomiast procedury nie produkują danych wyjściowych. Nie znaczy to jednak, że za ich pomocą nie można modyfikować wartości pewnych zmiennych. Jest tak dlatego, że argumenty do funkcji i procedur mogą być przekazywane przez wartość i przez referencję. W pierwszym przypadku przekazywana jest sama wartość zmiennej, która pojawiła się w wywołaniu funkcji lub procedury. Natomiast w drugim przypadku przekazywana jest zmienna, co pozwala na modyfikację jej wartości. Zagadnienie to jest szczegółowo przedstawione dalej.

Procedury

Definicja procedury składa się z nagłówka, części deklaracyjnej oraz ciała procedury. Nagłówek procedury składa się ze słowa kluczowego procedure, nazwy procedury, ujętej w nawiasy okrągłe list oddzielonych średnikami argumentów postaci nazwa_argumentu : typ.

Część deklaracyjna procedury może się składać z tych samych deklaracji co program, czyli: deklaracji stałych i zmiennych oraz definicji typów.

Ciało procedury składa się z ciągu instrukcji języka Pascal ujętych w słowa kluczowe begin oraz end. Ogólna postać definicji procedury przedstawiona jest poniżej:

procedure nazwa_procedury(argument_1 : typ_1; argument_2 : typ_2, ...);
type 
  {definicje typów}
const 
  {deklaracje stałych}
var 
  {deklaracje zmiennych}
begin
  {ciało procedury}
end

W ciele procedury dostępne są wszystkie zmienne zadeklarowane w części deklaracyjnej programu, w części deklaracyjnej tej procedury, a także zmienne, które są parametrami procedury. Te ostatnie zmienne przyjmują wartości takie jak wartości argumentów przekazanych w wywołaniu procedury.

Nazwa procedury wraz z listą jej parametrów stanowi jej sygnaturę.

Jeśli chcemy wywołać wcześniej zdefiniowaną procedurę musimy podać jej nazwę oraz ujęte w nawiasy okrągłe argumenty. Argumenty mogą być stałymi lub zmiennymi, których ilość i typ odpowiada dokładnie ilości i typowi argumentów pojawiających się w sygnaturze procedury.

Ogólna postać wywołania procedury jest następująca:

nazwa_procedury(argument_1, argument_2, ...);

Przykład wykorzystania procedury:

program liczby;
procedure wypisz_liczbe(liczba : integer);
begin
  write("Liczba posiada wartość ");
  writeln(liczba);
end;
begin
  wypisz_liczbe(5);
  wypisz_liczbe(10); 
  wypisz_liczbe();
  {wywołanie niepoprawne - brak argumentu}
  wypisz_liczbe('a');
  {wywołanie niepoprawne - niewłaściwy typ argumentu}
end.

W powyższym programie definiujemy procedurę wypisz_liczbe, która wypisuje komunikat “Liczba posiada wartość ” oraz podaje wartość liczby. Dwa wywołania występujące w programie są niepoprawne. Pierwsze posiada inną liczbę argumentów niż sygnatura procedury, w drugim – typ argumentu przekazanego w wywołaniu nie pokrywa się z typem argumentu występującym w sygnaturze.

Po usunięciu błędnych wywołań, wykonanie programu wyglądałoby następująco:

Liczba posiada wartość 5
Liczba posiada wartość 10

Funkcje

Funkcje od procedur różnią się tym, że ich wykonanie kończy się zwróceniem pewnej wartości, która może być wykorzystana w instrukcji przypisania.

Definicja funkcji nie różni się bardzo od definicji procedury. Jedyna różnica polega na tym, że po liście argumentów funkcji pojawia się dwukropek i typ argumentu, który jest zwracany przez funkcję.

Ogólna postać definicji funkcji jest następująca:

function nazwa_funkcji(argument_1 : typ_1; argument_2 : typ_2, ...) : typ_wyniku;
{deklaracje}
begin
  {ciało funkcji}
end

W ciele funkcji dostępne są wszystkie zmienne, które wymienione były w opisie procedur oraz zmienna, której nazwa jest taka sama jak nazwa funkcji. Wartość zwracana przez funkcję to ostatnia wartość przypisana do tej zmiennej. Należy pamiętać aby każda ścieżka wykonania algorytmu zapewniała przypisanie pewnej wartości do tej zmiennej. Najlepiej zatem w pierwszej instrukcji przypisać pewną domyślną wartość tej zmiennej.

Wywołanie funkcji musi spełniać te same założenia co wywołanie procedury. Jeśli chcemy wykorzystać wartość zwracaną przez funkcję, musimy przypisać ją do zmiennej, której typ jest taki sam, jak tym wartości zwracanej przez funkcję. Dla ogólnej funkcji zdefiniowanej powyżej moglibyśmy użyć następującego wywołania:

var 
  zmienna : typ_wyniku;
{deklaracja funkcji - j.w.}
begin
  zmienna = nazwa_funkcji(argument_1, argument_2, ...);
end.

Przykład wykorzystania funkcji:

program potega;
var 
  wartosc : integer;
function potega(podstawa : integer; wykladnik : integer);
var 
  indeks : integer;
begin
  potega := 1;
  for indeks := 1 to wykladnik do
    potega := potega * podstawa;
end
begin
  wartosc := potega(2,3);
  write("Trzecią potęgą liczby 2 jest : ");
  writeln(wartosc);
  wartosc := potega(3,4);
  write("Czwartą potęgą liczby 3 jest : ");
  writeln(wartosc);
end.

Wykonanie powyższego programu wygląda następująco:

Trzecią potęgą liczby 2 jest : 8
Czwartą potęgą liczby 3 jest : 81

Author: ZSE

Share This Post On
Skip to content