.
- 1 -
6. Procedury i funkcje
6.1. Mapa pamięci programu napisanego w Turbo Pascalu
6.2. Wprowadzenie do pojęcia procedury i funkcji.
6.3. Definicja procedur i funkcji
6.3.1. Procedury i funkcje bezparametrowe
6.3.2. Przekazywanie parametrów przez wartości
6.3.3. Przekazywanie parametrów przez zmienne określonego typu
6.3.4. Przekazywanie parametrów przez zmienne nieokreślonego typu
6.4. Podsumowanie
6.5. Przykłady
6.1. Mapa pamięci programu napisanego w Turbo Pascalu
Zanim przejdziemy do przedstawienia sposobu definiowania procedur i funkcji oraz opisania różnych metod
ich definicji, przedstawimy, w jaki sposób programy napisane w Pascalu korzystają z pamięci komputera.
Pamięć komputera, jak wiadomo, jest pewnego rodzaju uporządkowanym ciągiem bajtów, komórek pamięci do
których możliwy jest dostęp przez podanie odpowiedniego adresu. Każdy adres składa się z dwóch części:
• adresu segmentu (segment to ciągły obszar pamięci o długości do 64KB),
• adresu względnego (przesunięcia, offsetu) określającego odległość danej komórki od początku segmentu.
W jaki sposób program, napisany w Turbo Pascalu i skompilowany w trybie rzeczywistym, umieszczany jest w
pamięci przedstawiono poniżej.
wolny obszar stosu
stos dla zmiennych dynamicznych
bufor nakładkowy
segment stosowy dla zmiennych lokalnych
wolny obszar segmentu stosowego
segment danych
blok kodu modułu System
blok kodu pierwszego modułu
blok kodu ostatniego modułu
blok kodu programu
blok wstępny programu (PSP)
bloki kodu kolejnych modułów
HeapEnd
HeapPtr
HeapOrg
SSeg:SPtr
SSeg:0000
DSeg:0000
PrefixSeg
OvrHeapEnd
OvrHeapOrg
literały zmienne
zmienne globalne
zawartość obrazu zbioru .EXE
Podczas wczytywania zbioru .EXE do pamięci, system operacyjny DOS tworzy blok wstępny programu.
Ten obszar pamięci służy do komunikacji pomiędzy systemem operacyjnym i programem. Blok PSP (Program
Segment Prefix) zajmuje zawsze 256 bajtów. Adres segmentu pamięci, od którego rozpoczyna się ten blok jest
pamiętany w predefiniowanej zmiennej PrefixSeg.
Blok kodowy zajmuje kod programu głównego.
- 2 -
W kolejnych blokach pamiętane są kody zadeklarowanych w programie modułów (w odwrotnej kolejności
niż zadeklarowane). W ostatnim bloku kodowym pamiętany jest standardowy moduł System (dla przypomnienia -
nie jest wymagana deklaracja tego modułuw programie).
W segmencie danych pamiętane są wszystkie literały zmienne zdefiniowane w programie i modułach oraz
zmienne globalne zadeklarowane w programie i modułach. Początek adresu tego segmentu jest wartością
standardowej funkcji DSeg. Rozmiar segmentu danych (podobnie jak poszczególnych segmentów kodowych) nie
może przekraczać 64 kB.
W segmencie stosowym pamiętane są zmienne lokalne. Kolejne zmienne zapamiętywane są w kierunku
malejących adresów pamięci. Rozmiar segmentu stosowego (max 64 kB) ustala się za pomocą dyrektywy
kompilatora M lub w menu systemu Turbo Pascal.
Do przechowywania segmentów nakładkowych programu jest wykorzystywany bufor nakładkowy. Jeśli
program nie posiada segmentów nakładkowych, rozmiar tego bufora jest równy zeru. Adresy początku i końca
bufora nakładkowego pamiętane są w predefiniowanych zmiennych OvrHeapOrg i OvrHeapEnd.
Stos zmiennych dynamicznych (sterta) służy do przechowywania zmiennych dynamicznych. Pamięć dla
tych zmiennych jest przydzielana za pomocą standardowych procedur New i GetMem. Zmienne dynamiczne mogą
zajmować cala resztę pamięci dostępna podczas wykonywania programu. Adres początku stosu pamiętany jest w
zmiennej HeapOrg a adres wierzchołka stosu w zmiennej HeapPtr..
Uwaga, żaden z bloków kodowych nie może zając więcej niż 64 kB pamięci, natomiast rozmiar wszystkich
bloków łącznie jest ograniczony jedynie wielkością pamięci komputera.
Na podstawie powyższej mapy pamięci można zauważyć, że zmienne globalne umieszczane są w segmencie
danych. Rozmiar tego segmentu jest niezwykle skąpy jak na wymagania przeciętnego programisty. Jednak w
Pascalu istnieją jeszcze dwa bardzo znaczące segmenty pamięci, to jest stos dla zmiennych lokalnych – w którym
rezerwowana będzie pamięć dla zmiennych deklarowanych wewnątrz procedur i funkcji, oraz stos dla zmiennych
dynamicznych (sterta).
6.2. Wprowadzenie pojęcia procedury i funkcji
Procedurą lub funkcją jest wyodrębniona część programu, stanowiącą pewną całość, posiadającą jednoznaczny
identyfikator i ustalony sposób wymiany informacji z pozostałymi częściami programu. Procedury i funkcje
stosowane są do najczęściej do wykonywania czynności, które wykorzystane mogą być w różnych programach
oraz wykonywania czynności wielokrotnie powtarzanych przez dany program. Szczególnie korzystne jest
zastosowanie procedur i funkcji w programach, w których można wyodrębnić kilka problemów, możliwych do
oddzielnego opracowania każdego z nich.
Dzięki stosowaniu procedur i funkcji można również efektywniej wykorzystać pamięć komputera, gdyż
obiektom określonym wewnątrz procedury lub funkcji pamięć przydzielana jest dopiero z chwilą wywołania danej
procedury lub funkcji, a zwalniana po wyjściu z niej.
Pamiętać należy, że aby procedury i funkcje były uniwersalne, powinny być możliwie najsłabiej związane z
danym programem.
6.3. Definicja procedur i funkcji
Opis funkcji lub procedury w programie następuje za pomocą definicji. W przypadku procedur zachodzi także
niekiedy konieczność ich zadeklarowania.
W nagłówku definicji procedury lub funkcji podaje się identyfikator oraz ewentualnie parametry formalne, tj.
wielkości od których zależeć będzie działanie procedury (funkcji). W przypadku funkcji, w nagłówku określa się
ponadto typ wyniku. Po nagłówku podaje się treść procedury (funkcji). Treść ta składa się z części opisowej, w
.
- 3 -
której definiuje i deklaruje się obiekty lokalne wewnątrz danej procedury lub funkcji oraz z części operacyjnej
(mającej zawsze postać instrukcji złożonej), która zawiera sekwencję instrukcji powodującą wykonanie czynności
przewidzianych przez dany algorytm. Czynności te mogą być wykonywane zarówno na obiektach lokalnych, jak i
na obiektach nielokalnych (zdefiniowanych lub zadeklarowanych na zewnątrz procedury lub funkcji).
Obiekty nielokalne występują w treści procedury lub funkcji w sposób jawny lub są do niej przekazywane
przez parametry.
Definicje procedury i funkcji mają następujące postacie ogólne:
procedure identyfikator_procedury ( lista_parametrów_formalnych);
{ część_opisowa }
begin
{ ciąg_instrukcji }
end;
function identyfikator_funkcji (lista_parametrów_formalnych): typ_wyniku;
{ część_opisowa }
begin
{ ciąg_instrukcji }
end;
W obu przypadkach część opisowa i lista parametrów formalnych jest opcjonalna. Część opisowa procedury lub
funkcji może zawierać takie same elementy jak część opisowa programu, z wyjątkiem deklaracji modułów. Lista
parametrów formalnych zawiera deklaracje parametrów formalnych, oddzielonych średnikami. W zależności od
sposobu przekazywania informacji, to znaczy zastępowania parametrów formalnych występujących w definicji
odpowiednimi parametrami wywołania (argumentami, parametrami aktualnymi) wyróżniamy m.in.
• parametry przekazywane przez wartości,
• parametry przekazywane przez zmienne określonego typu,
• parametry przekazywane przez zmienne nieokreślonego typu.
Deklaracje tych parametrów mają postać odpowiednio:
lista_parametrów : identyfikator_typu
var lista_parametrów : identyfikator_typu
var lista_parametrów
Zamiast identyfikatora typu może wystąpić słowo klucowe string. Dla parametrów tego typu łańcuchowego nie jest
dozwolona specyfikacja długości łańcucha (przyjmuje się domyślnie, że długość ta wynosi 255).
Różnica pomiędzy procedurą i funkcją polega na sposobie przekazywania wartości określanej przez procedurę
(funkcję). Zadaniem procedury jest wykonanie pewnej sekwencji czynności, polegających zwykle na obliczeniu
jednej lub wielu wartości. Z identyfikatorem procedury związany jest adres, gdzie się ona znajduje. Natomiast
zadaniem funkcji jest obliczenie jednej wartości (typu prostego lub wskaźnikowego). Oprócz adresu posiada ona
również identyfikator informujący o wyznaczonej wartości. Odmienne są też sposoby wywołania procedur i
funkcji. Procedury wywołuje się przez nazwę (podając ewentualnie listę parametrów formalnych), funkcję zaś
podstawia się pod zmienną typu zgodnego z typem funkcji. W przypadku funkcji, w ciągu instrukcji musi wystąpić
przynajmniej jedna instrukcja przypisania postaci:
indentyfikator_funkcji := wyrażenie
6.3.1. Procedury i funkcje bezparametrowe
W przypadku procedur (funkcji) bezparametrowych, korzystają one ze zmiennych globalnych
zadeklarowanych w programie lub modułach. Stosowanie tego typu rozwiązań powoduje, że program staje się
czytelniejszy, jednak jest mało uniwersalny.
- 4 -
Zastosowanie procedur i funkcji bezparametrowych przedstawmy dwóch przykładach.
Przykład 1.
Załóżmy, że naszym zadaniem jest wprowadzenie do programu dwóch macierzy A i B, obliczenie macierzy C
jako sumy A+B, a następnie wypisanie wartości wszystkich trzech macierzy na ekranie monitora. Realizujący
powyższy problem program może mieć następującą postać:
Wersja 1.
program procedury_bez_parametrow_formalnych;
uses Crt;
const maxW=10; maxK=5;
type macierz=Array[1..maxW,1..maxK] of Real;
var A,B,C:Macierz;
W,K:Word;
procedure czekaj;
var znak:Char;
begin
Write(' ... nacisnij dowolny klawisz ...');
znak:=Readkey
end;
procedure czytaj_WK;
var i,j:Word;
begin
Repeat
Write('Podaj liczbe wierszy (W<=',maxW,') W = ');
Readln(W);
Until W<=maxW;
Repeat
Write('Podaj liczbe kolumn (K<=',maxK,') K = ');
Readln(K);
Until K<=maxK;
end;
procedure czytaj_macierz_A;
var i,j:Word;
begin
Writeln('Wprowadz elementy macierzy A');
for i:=1 to W do
for j:=1 to K do
begin
Write('A[',i:2,',',j:2,'] = ');
Readln(A[i,j]);
end;
end;
procedure czytaj_macierz_B;
var i,j:Word;
begin
Writeln('Wprowadz elementy macierzy B');
for i:=1 to W do
for j:=1 to K do
begin
Write('B[',i:2,',',j:2,'] = ');
Readln(B[i,j]);
end;
end;
procedure dodaj;
var i,j:Word;
begin
for i:=1 to W do
for j:=1 to K do C[i,j]:=A[i,j]+B[i,j];
end;
procedure wypisz_A;
var i,j:Word;
begin
.
- 5 -
Writeln(' Macierz A');
for i:=1 to W do
begin
for j:=1 to K do Write(A[i,j]:10:2);
Writeln;
end;
end;
procedure wypisz_B;
var i,j:Word;
begin
Writeln(' Macierz B');
for i:=1 to W do
begin
for j:=1 to K do Write(B[i,j]:10:2);
Writeln;
end;
end;
procedure wypisz_C;
var i,j:Word;
begin
Writeln(' Macierz C = A + B ');
for i:=1 to W do
begin
for j:=1 to K do Write(C[i,j]:10:2);
Writeln;
end;
end;
begin
czytaj_WK;
czytaj_macierz_A;
czytaj_macierz_B;
dodaj;
wypisz_A;
wypisz_B;
wypisz_C;
czekaj;
end.
Przykład 2.
Zadanie polega na napisaniu programu rozwiązującego równanie kwadratowe.
Problem ten można rozwiązać następująco:
Wersja 1.
program funkcje_bez_parametrow_formalnych;
uses Crt;
var a,b,c,delta:Real;
x1,x2:Real;
procedure czekaj;
var znak:Char;
begin
Write(' ... nacisnij dowolny klawisz ...');
znak:=Readkey;
end;
procedure dane;
begin
Writeln('Wprowadz parametry rownania kwadratowego');
Write('a = ');
Readln(a);
Write('b = ');
Readln(b);
Write('c = ');
Readln(c);
end;
procedure sprawdz;
begin
if delta < 0 then
- 6 -
begin
Writeln(' Brak pierwiastkow rzeczywistych ');
czekaj;
halt;
end;
if a = 0 then
begin
Writeln(' To nie jest rownanie kwadratowe');;
czekaj;
halt;
end;
end;
function wartosc_delta:Real;
begin
wartosc_delta:=b*b-4*a*c;
Writeln('delta = ',(b*b-4*a*c):10:2);
end;
function pierwiastek_x1:Real;
begin
pierwiastek_x1:=-b-sqrt(delta)/(2*a);
end;
function pierwiastek_x2:Real;
begin
pierwiastek_x2:=-b+sqrt(delta)/(2*a);
end;
begin
dane;
delta:=wartosc_delta;
sprawdz;
x1:=pierwiastek_x1;
x2:=pierwiastek_x2;
Writeln(' x1 = ',x1:10:2);
Writeln(' x2 = ',x2:10:2);
czekaj;
end.
Z powyższych przykładów łatwo wyciągnąć wniosek, że programy te są bardzo mało uniwersalny. Procedury
wykonujące działania na macierzach operują na zmiennych globalnych, przez co są bardzo silnie związane z
programem. Ponadto, procedury czytające macierze z klawiatury oraz wypisujące wartości macierzy na ekranie są
dublowane. Podobna sytuacja występuje w przypadku drugiego przykładu.
6.3.2. Przekazywanie parametrów przez wartości
W wywołaniu procedury lub funkcji odpowiadający mu argument (parametr wywołania, parametr aktualny)
musi być wyrażeniem zgodnym w sensie przypisania z typem tego parametru. Parametry formalne przekazywane
przez wartość traktowane są jako zmienne lokalne. Ich wartość początkowa jest równa wartości argumentu
wywołania. Operacje wykonywane na nich nie powodują zmiany wartości parametrów aktualnych.
W przypadku przekazywania parametru przez wartość, na stosie dla zmiennych lokalnych tworzona jest kopia
wartości argumentu. Procedura lub funkcja otrzymuje tę kopię, natomiast program nie ma do niej dostępu. Po
wyjściu z procedury (funkcji) przechowywane w kopii wartości są tracone. Jeżeli parametr wywołania jest
wyrażeniem, wówczas w kopii na stosie dla zmiennych lokalnych przechowywana jest wartość tego wyrażenia,
obliczana podczas wywołania procedury (funkcji).
.
- 7 -
stos dla zmiennych lokalnych
segment danych
kopia
blok kodu programu lub modułu
zmienna globalna
procedura
Korzystając z możliwości przekazywania parametrów przez wartość, zrealizujmy zadania postawione w
poprzednim punkcie.
Przykład 1 - wersja 2.
program procedury_z_parametami_przekazywanymi_przez_wartosc;
uses Crt;
const maxW=10;
maxK=5;
type macierz=Array[1..maxW,1..maxK] of Real;
var A,B,C:Macierz;
W,K:Word;
procedure czekaj;
var znak:Char;
begin
Write(' ... nacisnij dowolny klawisz ...');
znak:=Readkey;
end;
procedure czytaj_WK;
begin
Repeat
Write('Podaj liczbe wierszy(W<=',maxW,') W = ');
Readln(W);
Until W<=maxW;
Repeat
Write('Podaj liczbe kolumn (K<=',maxK,') K = ');
Readln(K);
Until K<=maxK;
end;
procedure czytaj_macierz_A;
var i,j:Word;
begin
Writeln('Wprowadz elementy macierzy A');
for i:=1 to W do
for j:=1 to K do
begin
Write('A[',i:2,',',j:2,'] = ');
Readln(A[i,j]);
end;
end;
procedure czytaj_macierz_B;
var i,j:Word;
begin
Writeln('Wprowadz elementy macierzy B');
for i:=1 to W do
for j:=1 to K do
begin
Write('B[',i:2,',',j:2,'] = ');
Readln(B[i,j]);
end;
end;
- 8 -
procedure dodaj;
var i,j:Word;
begin
for i:=1 to W do
for j:=1 to K do C[i,j]:=A[i,j]+B[i,j];
end;
procedure wypisz(tablica:macierz;opis:String);
{parametry: tablica i opis przekazywane sa przez wartosc }
var i,j:Word;
begin
Writeln(opis);
for i:=1 to W do
begin
for j:=1 to K do Write(tablica[i,j]:10:2);
Writeln;
end;
end;
begin
czytaj_WK;
czytaj_macierz_A;
czytaj_macierz_B;
dodaj;
wypisz(A,'Macierz A');
wypisz(B,'Macierz B');
wypisz(C,'Macierz C= A +B');
czekaj;
end.
Przykład 2 - wersja 2.
program funkcje_a_parametrami_przekazywanymi_przez_wartosc;
uses Crt;
var a,b,c,delta:Real;
x1,x2:Real;
procedure czekaj;
var znak:Char;
begin
Write(' ... nacisnij dowolny klawisz ...');
znak:=Readkey;
end;
procedure dane;
begin
Writeln('Wprowadz parametry rownania kwadratowego');
Write('a = '); Readln(a);
Write('b = '); Readln(b);
Write('c = '); Readln(c);
end;
procedure sprawdz;
begin
if delta < 0 then
begin
Writeln(' Brak pierwiastkow rzeczywistych ');
czekaj;
halt;
end;
if a = 0 then
begin
Writeln(' To nie jest rownanie kwadratowe');;
czekaj;
halt;
end;
end;
function wartosc_delta(a,b,c:Real):Real;
begin
wartosc_delta:=b*b-4*a*c;
Writeln('delta = ',(b*b-4*a*c):10:2);
end;
.
- 9 -
function pierwiastek(ktory:Byte):Real;
begin
if ktory=1
then pierwiastek:=-b-sqrt(delta)/(2*a)
else pierwiastek:=-b+sqrt(delta)/(2*a)
end;
begin
dane;
delta:=wartosc_delta(a,b,c);
sprawdz;
x1:=pierwiastek(1);
x2:=pierwiastek(2);
Writeln(' x1 = ',x1:10:2);
Writeln(' x2 = ',x2:10:2);
czekaj;
end.
6.3.3. Przekazywanie parametrów przez zmienne określonego typu
Argumenty odpowiadające parametrom przekazywanym przez zmienną określonego (lub nieokreślonego) typu
muszą być zmiennymi typu zgodnego z danym. Operacje wykonywane w treści procedury (funkcji) na parametrach
przekazywanych przez zmienną powodują po wywołaniu wykonanie operacji na odpowiadających im
argumentach, tj. na wielkościach zmiennych, nie kopiach. Dzięki temu uzyskujemy możliwość przekazywania
wyników. W tym przypadku procedura (funkcja) otrzymuje nie kopię a adres do oryginału zmiennej. Adres ten jest
umieszczany w segmencie stosowym i tracony po wyjściu z procedury (funkcji). Przez cały czas działania
procedury (funkcji) ma ona dostęp (przez adres) do oryginalnego parametru wywołania znajdującego się w
segmencie danych, gdzie są zgromadzone zmienne globalne. W tym czasie parametr ten może być on dowolnie
modyfikowany.
Po raz trzeci napiszmy program z przykładu 1, korzystając tym razem również z możliwości przekazywania
parametrów przez zmienne.
Przykład 1 - wersja 3.
program procedury_z_parametami_przekazywanymi_przez_zmienne;
uses Crt;
const maxW=10;
maxK=5;
type macierz=Array[1..maxW,1..maxK] of Real;
var A,B,C:Macierz;
W,K:Word;
procedure czekaj; { procedura bez parametrow formalnych }
var znak:Char;
begin
Write(' ... nacisnij dowolny klawisz ...');
znak:=Readkey;
stos dla zmiennych lokalnych
segment danych
adres
blok kodu programu lub modułu
zmienna globalna
procedura
- 10 -
end;
procedure czytaj_WK(var N_wierszy,N_kolumn:Word);
{parametry N_wierszy i N_kolumn przekazywane sa przez zmienne }
begin
Repeat
Write('Podaj liczbe wierszy (W<=',maxW,') W = ');
Readln(N_wierszy);
Until N_wierszy<=maxW;
Repeat
Write('Podaj liczbe kolumn (K<=',maxK,') K = ');
Readln(N_kolumn);
Until N_kolumn<=maxK;
end;
procedure czytaj_macierz(var tablica:macierz;
oznaczenie:String);
{ parametr tablica jest przekazywany przez zmienna,
parametr oznaczenie - przez wartośc }
var i,j:Word;
begin
Writeln('Wprowadz elementy macierzy ',oznaczenie);
for i:=1 to W do
for j:=1 to K do
begin
Write(oznaczenie,'[',i:2,',',j:2,'] = ');
Readln(tablica[i,j]);
end;
end;
procedure dodaj(X,Y:Macierz;var Z:Macierz);
{ parametry X,Y przekazywane sa przez wartości,
parametr Z - przez zmienna }
var i,j:Word;
begin
for i:=1 to W do
for j:=1 to K do Z[i,j]:=X[i,j]+Y[i,j];
end;
procedure wypisz(tablica:macierz;opis:String);
{ parametry przekazywane sa przez wartości }
var i,j:Word;
begin
Writeln(opis);
for i:=1 to W do
begin
for j:=1 to K do Write(tablica[i,j]:10:2);
Writeln;
end;
end;
begin
czytaj_WK(W,K);
czytaj_macierz(A,'A');
czytaj_macierz(B,'B');
dodaj(A,B,C);
wypisz(A,'Macierz A');
wypisz(B,'Macierz B');
wypisz(C,'Macierz C= A +B');
czekaj;
end.
Zauważmy, że w powyższym przykładzie nie wszystkie parametry przekazywane są przez zmienne. Te
parametry, które wewnątrz procedur nie powinny ulec zmianie, przekazywane są przez wartości. Przez zmienne
przekazywane są parametry, które są wynikiem działania procedury.
Porównując program w którym nie stosowano parametrów formalnych z programem wykorzystującym różne
.
- 11 -
możliwości przekazywania parametrów, widać zdecydowaną przewagę tego drugiego. Program jest nie tylko
znacznie krótszy, ale przede wszystkim bardziej uniwersalny.
6.3.4. Przekazywanie parametrów przez zmienne nieokreślonego typu
Ten sposób przekazywania parametrów stosuje się przede wszystkim w takich procedurach i funkcjach, które
przetwarzają struktury danych o róznych rozmiarach. Parametry nieokreślonego typu nie są zgodne (w treści
procedury lub funkcji) z żadnymi zmiennymi. Aby parametrom tym nadać odpowiednie typy, należy zastosować
konstrukcję postaci:
identyfikator_typu(odwołanie_do_zmiennej)
Zmienna do której następuje odwołanie może być zmienną całościową lub indeksowaną. Po zastosowaniu
powyższej konstrukcji zmienna będzie taraktowana tak jak zmienna typu określonego przez identyfikator typu.
Rozmiar zmiennej musi być przy tym zgodny z rozmiarem typu o podanym identyfikatorze.
Zastosowanie tego sposobu przekazywania parametrów przedstawmy na przykładzie procedury, której
zadaniem jest wczytanie elementów macierzy kwadratowej różnych stopni.
const N1=5; { stopien macierzy }
N2=10;
type macierz1= Array[1..n1,1..n1] of Real;
macierz2= Array[1..n2, 1..n2] of Real;
{ ... }
var A:macierz1;
B:macierz2;
procedure czytaj_macierz(N:Byte; var tablica; oznaczenie:String);
{ parametr tablica jest przekazywany przez zmienną nieokreślonego typu }
var i,j:Word;
begin
if N>10 then Writeln('Za duzy stopien macierzy')
else
begin
Writeln('Wprowadz elementy macierzy ',oznaczenie);
for i:=1 to N do
for j:=1 to N do
begin
Write(oznaczenie,'[',i:2,',',j:2,'] = ');
case N of
1..5 :
Readln(macierz1(tablica)[i,j]);
6..10:
Readln(macierz2(tablica)[i,j])
end;
end;
end; { else }
end;
begin
{...}
czytaj_macierz(5,A, 'macierz pierwsza');
czytaj_macierz(9,B, 'macierz druga');
{...}
end.
6.3.5 Podsumowanie
Niektóre przykłady mogą sugerować, że stosowanie procedur bezparametrowych jest niecelowe ze względu
na ewentualną konieczność wykonywania dodatkowych operacji przed i po ich wywołaniu. Najczęściej tak jednak
nie jest. Procedury (funkcje) bezparametrowe, wykorzystywane są często do wykonywania
niesparametryzowanych, powtarzających się operacji. W zasadzie w typowych programach stosowanie parametrów
w procedurach uzasadnione jest tylko dla wielkości, które będą się zmieniać przy kolejnych wywołaniach
procedur.
Uwaga ta nie dotyczy procedur i funkcji bibliotecznych, które tworzone są w celu późniejszego ich dołączania
do różnych programów. W tego typu procedurach i funkcjach parametry reprezentują przede wszystkim wielkości
- 12 -
charakterystyczne dla danego algorytmu, chociaż w danym programie mogą być one wykorzystywane dla stałych
parametrów aktualnych (argumentów).
Na koniec jeszcze jedna praktyczna rada. Procedury i funkcje powinny być "zamknięte", to znaczy nie
powinny korzystać wprost ze zmiennych globalnych. Przenikanie zmiennych globalnych do procedur (funkcji)
znacznie utrudnia analizę programu oraz może prowadzić do nieprzewidzainych zmian wartości tych zmiennych.
Aby lepiej zrozumieć ten problem, proponuję samodzielnie rozwiązać poniższe zadanie, korzystając z kartki
papieru, po czym porównać odpowiedź z efektem działania programu.
program test;
uses crt;
{ Jaka bedzie postac ekranu monitora po wykonaniu programu ? }
var a,b:String;
function zero:String;
var b: String;
begin
b:='Tomasz';
zero:='Maria';
Writeln('funkcja zero : ',a,b);
end;
function jeden(var a:String; b:String):String;
begin
a:='Jan';
b:='Marcin';
jeden:='Ewa';
Writeln('funkcja jeden : ',a,b);
end;
procedure dwa;
var a :String;
begin
a:='Adam';
Writeln('procedura dwa : ',a,b);
end;
procedure trzy(a:String);
begin
Writeln('procedura trzy : ',a,b);
a:='Filip';
Writeln('procedura trzy : ',a,b);
end;
procedure cztery(var a:String);
begin
Writeln('procedura cztery : ',a,b);
a:='Mateusz';
Writeln('procedura cztery : ',a,b);
end;
begin
a:='Anna';
b:=zero;
b:=jeden(a,b);
Writeln(a,b);
dwa;
Writeln(a,b);
cztery(a);
Writeln(a,b);
trzy(a);
Writeln(a,b);
end.
6.3.6 Przykłady