Wykład XIII
Object Pascal –
Podprogramy (funkcje i
procedury)
Podstawy informatyki
Semestr II Elektrotechnika
2
O czym będzie?
Funkcje
Procedury
Biblioteki (moduły)
3
Podprogram
Wyodrębniona część programu
stanowiącą pewną całość,
posiadającą jednoznaczną nazwę
i ustalony sposób wymiany
informacji z pozostałymi
częściami programu.
4
Rodzaje podprogramów
Istnieje dwa rodzaje podprogramów:
– procedura – wykonanie pewnej
sekwencji czynności
– funkcja - obliczenie jednej wartości
Procedury i funkcje stanowią wydzielone
części aplikacji, wykonujące ściśle
określony, zamknięty blok instrukcji.
Dodatkowo, funkcja zwraca pod swą
nazwą wartość określonego typu.
5
Procedury
Nagłówek procedury rozpoczyna się od słowa
kluczowego procedure, po którym występuje nazwa
procedury i – nieobowiązkowo – lista parametrów
formalnych, zamknięta w nawiasy okrągłe; całość
kończy się średnikiem.
Lista ta ma znaczenie podczas wywoływania
procedury, kiedy to poszczególnym parametrom
formalnym przyporządkowane zostaną wg. określonych
zasad (o czym później) konkretne parametry aktualne.
Część opisowa – zawiera listę deklaracji
Blok procedury składa się z instrukcji złożonej (begin
... end) wykonywanej przy wywołaniu procedury.
6
Szablon procedury
procedure nazwa-procedury (lista-
parametrów);
cześć-opisowa
begin
ciąg-instrukcji
end;
7
Funkcje
Mają naturę zbliżoną do procedur, inny jest jednak ich sens
w programie; podczas gdy procedura symbolizuje pewien
zamknięty zestaw czynności funkcja ucieleśnia pod swą
nazwą konkretną wartość, określonego typu – inna rzecz, że
najczęściej wyliczoną również w ramach wykonania ciągu
instrukcji.
Ma to wpływ na postać nagłówka, w którym po słowie
kluczowym function następuje nazwa funkcji, potem
nieobowiązkowo lista parametrów (identycznie jak w
procedurze), jednak przed średnikiem następuje jeszcze
wskazanie na typ wyniku funkcji (poprzedzone
dwukropkiem). Typ funkcji nie może być typem plikowym
ani też typem strukturalnym zawierającym w sobie typ
plikowy.
8
Funkcje cd.
Część opisowa – zawiera takie same elementy
jak w procedurach
Instrukcja złożona – ma takie samo znaczenie
jak w procedurze jednak z pewną istotną różnicą
otóż w ramach jej instrukcji musi nastąpić
przynajmniej raz przypisanie funkcji konkretnej
wartości. Może się to odbyć przez podstawienie
wartości funkcji pod jej nazwę lub słowo
kluczowe Result (symbolizującego niejako
zmienną przechowującą aktualny wynik funkcji).
9
Szablon funkcji
function nazwa- funkcji(lista-
parametrów):typ-wyniku;
część-opisowa
begin
ciąg-instrukcji
przypisanie funkcji (chociaż raz w ciągu
instrukcji)
end;
10
Część opisowa dla funkcji i
procedur
Część opisowa podprogramów może zawierać te same
deklaracje co program.
Możemy w niej zatem umieścić deklaracje:
– etykiet (label)
– typów (type)
– stałych (const)
– zmiennych (var)
– funkcji (function) i procedur (procedure)
Sposób deklarowania poszczególnych elementów jest
analogiczny do definicji w głównym bloku programu
(omówionych na wykładzie pt. „Podstawy
programowania w Object Pascalu”).
11
Przypisanie funkcji
nazwa-funkcji:= wyrażenie
lub
Result:=wyrażenie
musi wystąpić przynajmniej raz w części
wykonawczej funkcji
przynajmniej jedna z instrukcji przypisania
powinna zostać wykonana po wywołaniu
funkcji
12
Typ wyniku
określony jest za pomocą
identyfikatora typu (nie mogą to
być typy plikowe ani strukturalne
zawierające typ plikowy)
decyduje o typie zwracanego
przez funkcję wyniku
13
Rodzaje parametrów
parametry przekazywane przez wartość,
lista - parametrów : typ;
parametry przekazywane przez zmienną
określonego typu
var lista - parametrów : typ
parametry przekazywane przez wartość
stałą,
const lista - parametrów : typ;
parametry przekazywane przez zmienną
nieokreślonego typu
var lista-parametrów
14
Kojarzenie parametrów
przez wartość
Przekazywanie parametru przez wartość
wiąże się z automatycznym utworzeniem
jego lokalnej kopii, dostępnej pod
oryginalną nazwą parametru formalnego.
Innymi słowy wszystkie operacje
wykonywane wewnątrz treści
podprogramu na parametrze wykonywane
są na jego lokalnej kopii, a parametr
oryginalny pozostaje nienaruszony.
15
Przekazywanie parametrów przez
adres (zmienną, referencję,
odwołanie, wskazanie)
Przekazywanie parametru przez adres powoduje, że w treści
podprogramu pod nazwą parametru formalnego kryje się
rzeczywisty parametr aktualny, a wszystkie operacje
wykonywane są bezpośrednio na nim, bez tworzenia
jakichkolwiek kopii.
Jest to więc właściwy sposób na przekazanie przez
procedurę wartości zwrotnej do programu wywołującego.
Parametrem aktualnym może być jedyne zmienna (lub
konstrukcja równoważna*)
procedure Powieksz(var X: Integer);
begin
X:=X*2;
{procedura podwaja wartość swojego parametru}
end;
16
Przekazywanie parametrów przez
adres cd.
Przy przekazywaniu parametru przez odwołanie
zasada zgodności w sensie przypisania jest
niewystarczająca: typ parametru formalnego i
aktualnego musi być bowiem dokładnie taki sam.
Z punktu widzenia implementacji parametr
formalny kojarzony przez odwołanie
reprezentowany jest w treści podprogramu przez
adres parametru aktualnego, a skojarzenie
sprowadza się do przekazania tego adresu.
17
Przekazywanie
parametrów przez stałą
Ten sposób przekazywania parametrów łączy w sobie
zalety dwu poprzednich sposobów.
Z jednej strony parametr taki podlega tym samym
regułą składniowym jak parametry przekazywane
przez wartość.
Z drugiej strony techniczny sposób jego
przekazywania jest taki sam jak dla zmiennej
przekazywanej przez adres – nie jest tworzona kopia
lokalna, zamiast tego w treści procedury zabronione
są konstrukcje mogące doprowadzić do zmiany
parametru (powodują one błąd kompilacji).
18
Parametry amorficzne
(przekazywane przez zmienną
(lub stałą) nieokreślonego typu)
Możliwe jest określenie parametru formalnego bez
podania jego typu.
Parametr taki musi być przekazywany przez
odwołanie lub przez stałą.
Konstrukcja ta rozluźnia reguły składniowe Pascala. W
charakterze parametru może wystąpić dowolny
parametr dozwolony dla wywołania przez odwołanie.
Należy zauważyć, że w treści podprogramu parametr
amorficzny nie posiada określonego typu i nie jest
zgodny z żadnym typem zmiennych i w większości
przypadków konieczne jest poddanie go operacji
rzutowania typów.
19
Parametry amorficzne -
przykład
procedure WypelnijObszar(var X; Rozmiar: Integer);
var i, k : Integer; Y: array[1..1] of Byte absolute X;
begin
k:=0;
for i:=1 to Rozmiar do
begin
Y[i]:=k;
k:=(k+1) mod 255;
end;
end;
20
Typy amorficzne –
Uwaga!!!
Niewątpliwa elastyczność jaką niosą typy
amorficzne wymaga od programisty
zwiększonej ostrożności, bowiem
zaniechanie kontroli typu przez
kompilator stanowi równocześnie brak
ochrony przed wieloma
niebezpieczeństwami, jak np.
przekroczenie obszaru pamięci
zajmowanego przez zmienną.
21
Zasady o których warto
pamiętać podczas tworzenia
funkcji i procedur
Stosujmy odpowiednie nazwy. Nazwa podprogramu może
oddawać jego przeznaczenie;
Można umieścić komentarze opisujące przeznaczenie i
parametry podprogramu,
Starajmy się deklarować obiekty lokalne;
Dobierajmy poprawnie rodzaj parametrów pamiętając o
sprawdzeniu czy:
a)
parametr musi być przekazywany przez zmienną
czy przez
wartość;
b)
parametr będzie ulegał zmianom podczas
wykonania
podprogramu
Unikamy przekazywania przez wartość dużych struktur
danych.
22
Zasięg deklaracji (ang.
scope)
Zasięg deklaracji jest pojęciem związanym z
obowiązywaniem poszczególnych deklaracji w
poszczególnych fragmentach programu.
I tak zmienne globalne zadeklarowane w głównym
projekcie (lub bibliotece) widoczne są w całym programie,
podczas gdy zmienne lokalne zadeklarowane w
podprogramie nie są widoczne na zewnątrz niego.
Może się zdarzyć, że w danym bloku programu np.
wewnątrz procedury zdefiniowany zostanie lokalny
identyfikator o takiej samej nazwie, jak – widoczny z
wnętrza tej procedury – identyfikator globalny; ten ostatni
przestanie być wtedy dostępny w procedurze, zostanie
bowiem przesłonięty lokalną deklaracją.
23
Zasięg deklaracji -
przykład
var Licznik: Integer;
{zmienna globalna}
...
procedure A(X: Integer);
var Licznik: Byte;
begin
...
Licznik:=Licznik+X;
{tu modyfikowana
jest wartość zmiennej lokalnej z
procedury A, zmienna globalna nie
jest dostępna gdyż została
przysłonięta przez lokalną deklarację}
...
end;
begin
...
Licznik:=Licznik+3;
{tu modyfikujemy
zmienną globalną;
lokalna nie jest
dostępna gdyż
jesteśmy poza jej
zasięgiem – poza
procedurą A}
...
end.
24
Przykład 1
function fun1 (const x : Double) : Double;
begin
if x<0.5 then Result:=(0.2*x-1)*x+0.1
else Result:=x*x / (x*x-0.1)
end;
5
.
0
1
.
0
5
.
0
1
.
0
2
.
0
)
(
1
2
2
2
x
dla
x
x
x
dla
x
x
x
fun
25
Przykład 2
Obliczanie wartości wielomianu Lagendre’a n-
tego stopnia
x
x
P
x
P
x
P
n
x
xP
n
x
nP
n
n
n
1
0
2
1
1
)
1
(
1
2
26
Przykład 2 cd
function Legendre (const n
: Byte; const x : Double) :
Double;
var i:Byte;
p0,p1,p2 : Double;
begin
if n=0 then Legendre:=1
else
if n=1 then Legendre:=x
else begin
P1:=1 p2:=x;
for i:=2 to n do
begin
p0:=p1;
p1:=p2;
p2:=((2*n-1)*x*p1-(n-
1)*p0)/n
end;
Legendre:=p2
end ;
end;
27
Funkcje rekurencyjne
Pojęcie rekurencji szczegółowo
wyjaśniono na wykładzie pt.
„Algorytmy i dane”
W części operacyjnej funkcji
następuje wywołanie funkcji przez
samą siebie.
28
Przykład funkcji
rekurencyjnej
function silnia (n : Byte) : Integer;
begin
if n>12 then silnia:=0
else
if n=0 then silnia:=1
else silnia:=n*silnia(n-1)
end;
29
Wywołanie funkcji
Następuje za pomocą, podania nazwy
funkcji (wraz z odpowiednią do deklaracji
listą parametrów aktualnych) jako
argumentu dowolnego wyrażenia .
Przykład
X:=Legendre(4,
12.5)*3+Sin(X)+Silnia(5);
30
Przykład 3
program FunkcjeDemo3;
var alfa,beta,gamma,delta,y,z : Real;
function mianownik (zeta : Real) : Real;
begin
mianownik:=(sqr(zeta)
+sqrt(1+(2+3*zeta)*zeta))
end;
begin
...
alfa:=(6.9+y)/mianownik(y);
beta:=((2.1+z*sqr(z))*z)/mianownik(z);
ganma:=sin(y)/mianownik(sqr(y));
delta:=1/mianownik(sin (y) );
...
end.
( )
( )
( )
( )
y
y
y
y
y
y
y
y
z
z
z
z
z
y
y
y
y
2
2
4
2
4
2
2
4
2
2
sin
3
sin
2
1
sin
3
2
1
sin
3
2
1
1
.
2
3
2
1
9
.
6
+
+
+
=
+
+
+
=
+
+
+
+
=
+
+
+
+
=
31
Przykład 4
uses Dialogs; ...
procedure Srednia(var wynik :Double; ilosc: Byte);
var a, i: Byte;S:string;
begin
wynik:=0;
for i:=1 to ilosc do
begin
InputQuery(‘Liczba’, ‘Podaj a:’,S);
a:=StrToFloat(S); wynik:=wynik+a;
end;
wynik:= wynik/ilosc;
end;
32
Wywoływanie procedury
Do wywoływania służy instrukcja postaci:
nazwa-procedury
lub
nazwa procedury(lista-parametrów-
aktualnych)
Przykłady
Srednia(wynik, 4 );
ShowMessage(FloatToStr(wynik));
33
Przykład 5
procedure rk(const a, b, c: Double;
var x1, x2, Delta : Double);
begin
delta:=b*b-4*a*c;
if delta=0 then
begin
x1:=-b/(2*a);
x2:=x1;
end
else
if delta>0 then
begin
delta:=sqrt(delta);
x1:=(-b-delta)/
(2*a);
x2:=(-b+delta)/
(2*a)
end ;
end;
34
Moduły w Delphi (ang.
units)
Moduły (biblioteki) stanowią podstawowe
jednostki programu grupujące deklaracje
oraz funkcje i procedury oraz
przechowywania formularzy.
Są osiągalne z programu głównego, a także
nawzajem pomiędzy modułami.
Nazwa modułu musi być tożsama z nazwą
pliku, w którym on się znajduje; moduł o
nazwie banki musi być zapisany w pliku
banki.pas.
35
Budowa modułu
Każdy moduł składa się z
Dyrektywy unit
części publicznej (opisowej)
części prywatnej (implementacyjnej)
Ponadto w module mogą wystąpić
następujące elementy
część inicjacyjna
część kończąca
36
Szkielet modułu
Unit
nazwa-modulu;
część opisowa modułu
część implementacyjna
część inicjująca (opcjonalnie)
część kończąca (opcjonalnie)
end.
37
Dyrektywa unit
Stanowi pierwszą linię modułu
Składa się ze słowa kluczowego unit i
nazwy modułu.
38
Cześć publiczna
Rozpoczyna się od dyrektywy interface i zawiera
te części modułu (stałe, zmienne, typy, nagłówki
funkcji i procedur, itp.), które mają być dostępne
dla innych modułów oraz programu głównego.
W odniesieniu do funkcji i procedur część publiczna
zawiera jedynie ich nagłówki, gdyż tylko one są
istotne dla reszty programu; szczegółowe definicje
podprogramów (funkcji i procedur) znajdują się w
części prywatnej modułu.
Wszystkie elementy wewnątrz części publicznej są
opcjonalne.
39
Część opisowa modułu
interface
deklaracje użycia innych modułów
(uses)
definicje-interface
literały, stałe (const)
definicje typów (type)
deklaracje zmiennych (var)
lista nagłówków procedur i funkcji
(procedure, function)
40
Część implementacyjna
Część implementacyjna rozpoczyna się słowem
kluczowym implementation i zawiera te definicje
modułu , które mają dla niego znaczenie lokalne
Wszystkie definicje modułów, do których odwołuje się
część prywatna powinny wystąpić w początkowej
dyrektywie uses występującej bezpośrednio po słowie
kluczowym implementation.
Zawiera deklaracje etykiet, literałów i zmiennych oraz
definicje typów, funkcji i procedur wewnętrznych.
Zawiera treść funkcji i procedur udostępnianych na
zewnątrz (ich nagłówki znajdują się w sekcji interface)
41
Część inicjująca
Składa się ze słowa kluczowego
initialization, po którym występują
instrukcje,która będą wykonane
jednokrotnie przed rozpoczęciem
programu głównego w celu zainicjowania
modułu (np. przydzielenie pamięci,
wczytanie zasobów)
Występowanie tej części jest opcjonalne.
42
Część kończąca
Składa się ze słowa kluczowego finalization, po
którym występują instrukcje, która będą podczas
kończenia pracy modułu (po zakończeniu
programu głównego np. zwalnianie pamięci,
zwalnianie zasobów)
Występowanie tej części jest opcjonalne, wystąpić
może jednak tylko łącznie z sekcją inicjującą.
kolejność wykonywania części kończących jest
odwrotna w stosunku do kolejności wykonania
części inicjujących.
43
Szkielet modułu
unit Nazwa;
interface
...
implementation
...
initialization
...
finalization
...
end.
44
Przykład 6
unit cplxproc;
interface
procedure addcplx (aRe,aIm,bRe,bIm: Double; var
cRe,CIm: Double);
procedure subcplx(aRe,aIm,bRe,bIm: Double; var
cRe,CIm: Double);
procedure multcplx (aRe,aIm,bRe,bIm: Double; var
cRe,CIm: Double);
procedure divcplx (aRe,aIm,bRe,bIm: Double; var
cRe,CIm: Double);
45
Przykład 7 cd
implementation
procedure addcplx;
begin
cRe:=aRe+bRe;
cIm:=aIm+bIm;
end;
procedure subcplx;
begin
cRe:=aRe-bRe;
cIm:=aIm-bIm
end;
46
Przykład 7 cd
procedure multcplx;
begin
cRe:=aRe*bRe-aIm*blm;
cIm:=aRe*bIm+aIm*bRe;
end;
procedure divcplx;
var diwv : Real;
begin
diw:=sqr(bRe)+sqr(bIm);
cRe:=(aRe*bRe+aIm*bIm)/diw; cIm:=(alm*bRe-
aRe*bIm) /diw;
end;
end.
47
Moduły wzajemnie zależne
Wykorzystują wzajemnie elementy w nich
zdefiniowane.
W części implementacyjnej pierwszego modułu
występuje deklaracja drugiego modułu, a w części
implementacyjnej drugiego modułu deklaracja
pierwszego.
Dzięki takiej konstrukcji ewentualne procedury
zdefiniowane w wykropkowanej części
implementacyjnej pierwszego modułu dostępne są
w wykropkowanej części implementacyjnej
drugiego modułu i na odwrót.
48
Szkielet konstrukcji modułów
wzajemnie zależnych
unit modul1;
interface
...
implementation
uses modul2;
...
end.
unit modul2;
interface
...
implementation
uses modul1;
...
end.