Wstęp
do programowania
Wykład
5 – procedury i funkcje
Podprogramy
Często wygodnie jest zapisać część
programu jako
podprogram
czyli jako
funkcje
lub
Procedurę
Podprogram -
wyodrębniona część programu, stanowiąca
całość (tzw.blok), posiadająca nazwę
i ustalony sposób wymiany informacji z pozostałymi
częściami programu.
Cechy
Funkcje
i
procedury
.
umieszcza się je w części deklaracyjnej programu
lub w odrębnej jednostce kompilacyjnej
funkcja zazwyczaj operuje na pewnych
argumentach (nie modyfikując ich) i zwraca
pewną obliczoną wartość (jedną)
procedura zazwyczaj operuje na pewnych
argumentach, może je modyfikować i w ten
sposób zwrócić pewną wyliczoną wartość lub
wartości
Deklaracja procedury
nagłówek
procedury
End;
begin
ciąg instrukcji
Część
deklaracyjna
Blok
procedury
Procedura
-
podprogram wykonujący jedną lub więcej czynności i
zwracający od jednego do kilku wyników;
lub nie zwracająca żadnego wyniku
nazwa używana jest w charakterze instrukcji w programie.
Procedure
nagłółwek_proc
Cześć deklaracyjna
{const type var
– zmienne
lokalne}
Begin
Ciąg instrukcji
end;
....
Wywołanie procedury
{użycie jako instrukcja w
programie}
Deklaracja procedury
Nagłówek procedury
Procedure
nazwa_procedury
(lista parametrów formalnych);
Procedure
nazwa_procedury (
var
lista; parametrów; formalnych);
Wywołanie
nazwa_procedury
( lista, parametrów, aktualnych);
•Lista parametrów formalnych pozwala w sposób jawny przekazywać dane do
procedury lub funkcji.
•W wywołaniu podprogramu listę
parametrów formalnych
zastępuje lista
parametrów aktualnych
•Parametr aktualny
musi być takiego samego typu
jak odpowiadający mu na
liście parametr formalny.
•Parametry aktualne w wywołaniu podprogramu oddzielone są
przecinkami
.
Deklaracja procedury
Procedure
nazwa_procedury
(lista parametrów formalnych);
Są dwa sposoby przekazywania parametrów do procedury
Parametry przekazywane przez wartość
(lista parametrów formalnych)=
=(Identyfikator_1: typ1; Identyfikator_2,..., Identyfikator_n :
Typ);
Parametry przekazywane przez zmienną
var
lista parametrów formalnych=
=
(
var
Identyfikator_1: typ1
;
var
Identyfikator_2
,
...
,
Identyfikator_n:
Typ);
procedury
Parametry przekazywane przez
wartość
:
(przekazywanie w jedną stronę, praca na kopii parametru)
procedure
dodaj
(a: integer; b: Single);
procedure
generator
(x: real);
procedure
napisy
;
//procedura bez parametrów
Type Matrix
=array[1..5,1..4] of Double;
procedure
wypisz
(M: Matrix);
// zła deklaracja: procedure
wypisz
(M: array[1..5,1..4] of Double);
W wyniku wywołania procedury lub funkcji parametrom formalnym zostaje
przypisana wartość początkowa równa wartościom odpowiednich parametrów
aktualnych.
Operacje wykonywane w treści funkcji lub procedury wykonywane
są na kopii umieszczonej na stosie i w związku z tym nie powodują zmian
wartości odpowiadających im parametrów aktualnych.
procedury
Parametry przekazywane przez
zmienną
:
(przekazywanie w obie strony, praca na oryginale parametru)
procedure
zapisz
(var x: byte);
procedure
dodaj
(var a: integer; var b: Single);
procedure
dodaj
(a, b: integer; var c: Single);
Type Matrix
=array[1..5,1..5] of byte;
procedure
dodajM
(A, B : Matrix; var M : Matrix);
Operacje wykonywane w treści funkcji lub procedury wykonywane są
bezpośrednio na przekazywanych do procedury lub funkcji parametrach
aktualnych.
Efektem takiego działania jest zmiana wartości parametrów aktualnych po
wywołaniu procedury lub funkcji.
Parametry procedury/funkcji
•Parametry formalne
-
pojawiają się w nagłówku deklaracji funkcji bądź
procedury i są używane w instrukcjach funkcji lub procedury jak zwykłe
zmienne.
•Liczba parametrów formalnych nie jest ograniczona i ich kolejność
występowania jest dowolna. Parametr formalny jest obowiązkowo
zmienną.
•Parametry aktualne
-
są parametrami występującymi w bloku, z
którego wywoływana jest funkcja lub procedura i używane są podczas
wywołania procedury lub funkcji.
•Liczba parametrów aktualnych musi być taka sama jak liczba
parametrów formalnych i należy pamiętać o zgodności typów.
Parametrem aktualnym
może być wyrażenie, zmienna bądź stała.
•Wywołanie procedury
– polega na wpisaniu nazwy procedury z
odpowiednią listą parametrów aktualnych jako instrukcji programu.
np.:
wypisz(a,b,c);
Przykłady procedur
program Podpr1;
{$APPTYPE CONSOLE}
uses SysUtils;
procedure www(k, m :Integer);
begin
writeln('k=',k);
k := k+m;
writeln('k=',k);
end;
procedure zzz(var k, m :Integer);
begin
writeln('k=',k);
k := k+m;
writeln('k=',k);
end;
var
var
a, b :Integer;
begin
a := 1; b := a+1;
www(a, b+1);
writeln('a=',a);
www(a, b+1);
writeln('a=',a);
zzz(a, b);
writeln('a=',a);
zzz(a, b);
writeln('a=',a);
readln;
end.
Procedura z domyślną wartością
parametru wywołania
program Podpr2;
{$APPTYPE CONSOLE}
Procedure demo(
const
napis:
string
=‘Wartosc domyslna demo’
);
Begin
writeln(napis);
end;
Var s: string;
begin
s:=‘ procedura demo’;
demo(s);
demo;
demo(‘dowolny napis’)
readln;
end.
W Delphi istnieje możliwość podania
domyślnej wartości parametru
wywołania procedury lub funkcji.
poprzez użycie słowa kluczowego
Const
w nagłówku procedury
przed nazwą parametru oraz
podanie jego wartości po znaku
=
Przykłady procedur
wyświetlanie macierzy
program Podpr2;
{$APPTYPE CONSOLE}
uses SysUtils;
Const RM=5;
Type matrix=array[1..RM,1..RM]of
Byte;
procedure gener(var M : matrix);
Var i, k :byte;
//zmienne lokalne
Begin
Randomize;
for i:=1 to RM do
for k:=1 to RM do
M[i,k]:=random(10);
end;
procedure wypisz(M :matrix);
Var i,k: byte;
begin
for i:=1 to RM do
begin
for k:=1 to RM do
write(M[i,k]:4);
writeln;
end;
writeln;
End;
Var A, M : Matrix;
Begin
//cz. wykonawcza
wypisz(M);
gener(M);
wypisz(M);
gener(A);
wypisz(A); readln;
end.
Przykłady procedur
zmienne globalne
-zmienne globalne
to zmienne
zdefiniowane
przed def. Procedur
użwane wewnątrz
z możliwością ich
zmiany.
Powinno się unikać
używania zm.
Globalnych
przez używanie
zm. Lokalnych i
parametrów
formalnych
i przekazywanie ich
przez zmienną
program proc2;
{$APPTYPE CONSOLE}
uses sysutils;
var zm_globalna :integer;
Procedure proc_glob;
Var zm_lok :Integer;
Begin
zm_lok:=1;
zm_globalna:=zm_globalna+1;
writeln('zm_lok=',zm_lok);
writeln('zm_glob=',zm_globalna);
end;
var zm_globalna1 :integer;
begin
zm_globalna:=5;
writeln('zm_glob=',zm_globalna );
proc_glob;
writeln('zm_g=',zm_globalna );// 6
zm_globalna:=9;
writeln(zm_globalna ); //9
proc_glob; //10
writeln(zm_globalna ); //10
readln;
END.
Deklaracja Funkcji
nagłówek funkcji
end
.
begin
ciąg instrukcji
Część
deklaracyjna
Blok
funkcji
Funkcja
-
podprogram wykonujący jedną lub więcej czynności i
zwracający dokładnie jedną wartość.
nazwa używana jest w charakterze wyrażenia lub instrukcji.
Result := wyrażenie
Deklaracja Funkcji
Funkcja
-
podprogram wykonujący jedną lub więcej czynności i
zwracający dokładnie jedną wartość.
•nazwa używana funkcji jest w charakterze wyrażenia lub wartości.
Function
nazwa_funkcji :
typ_wyniku
//Cześć deklaracyjna
{const type var
– zmienne lokalne}
Begin
Ciąg instrukcji
Result := wyrażenie;
end;
Function
nazwa_funkcji :
typ_wyniku
Begin
Ciąg instrukcji
nazwa_funkcji
:= wyrażenie;
end;
Deklaracje funkcji
Nagłówek funkcji
Function
nazwa_funkcji
(lista; parametrów; formalnych) :
typ;
Wywołanie funkcji
– polega na wpisaniu nazwy funkcji z
odpowiednią listą parametrów aktualnych w wyrażeniu.
nazwa_funkcji
( lista, parametrów, aktualnych);
• Lista parametrów formalnych pozwala w sposób jawny przekazywać
dane do funkcji.
• W wywołaniu funkcji listę
parametrów formalnych
zastępuje lista
parametrów aktualnych
• Parametr aktualny
musi być takiego samego typu
jak odpowiadający
mu na liście parametr formalny.
Zwracanie wyniku przez funkcję
Zwracanie wartości funkcji odbywa się za
pomocą instrukcji
Result
Która jest zamienna lokalną
:
Result
:= zwracany_wynik
Wykonanie takiej instrukcji kończy działanie funkcji
(//pascasl -dalsze jej instrukcje, jeśli istnieją, nie będą
wykonywane).
Jeśli typ wyrażenia
zwracany_wynik
nie zgadza się z typem
zwracanego wyniku podanym w deklaracji funkcji, to
zwracany_wynik
jest odpowiednio konwertowany,
jeśli jest
to możliwe.
Deklaracje funkcji
Parametry przekazywane przez
wartość
:
(przekazywanie w jedną stronę)
function
dodaj
(a: byte; b: single) : single;
Begin
Result:=a+b;
// dodaj:=a+b;
end;
//Wywołania
Var a, x : byte;
b, y : single;
.....
Wynik:=dodaj(x,y);
Writeln(wynik);
Writeln( dodaj(a,b));
Deklaracje funkcji
przekazywanie tablic do funkcji
Type Tablica=array[1..10]of Samllint;
function
Iloczyn_skalarny
(A,B:Tablica ) : SmallInt;
//Wywołania
Var A, B : Tablica;
wynik : SamllInt;
.....
Wynik:=
Iloczyn_skalarny
(A,B);
lub
Writeln(‘wynik=‘, Iloczyn_skalarny(A,B));
Przykłady funkcji
program Podpr2;
{$APPTYPE CONSOLE} {$O-,Q+,R+}
uses SysUtils;
function suma2(k, m :Integer) : Integer;
Begin
Result := k+m;
Result := Result *2;
//suma2 := suma2*4; //nie polecane
end;
Var a, b, x :Integer;
Begin
x:=suma2(1,4);
Writeln('suma=',x);
A:=2; b:=3;
writeln(suma2(2,3));
writeln(suma2(a,b)); readln;
end.
program Podpr3;
{$APPTYPE CONSOLE} {$O-,Q+,R+}
function jaka_wartosc : Integer;
Begin
Result := 1; {niejdnozancze okrerlenie wartosci funkcji}
jaka_wartosc:= 2;
Result :=3 ; //ta wartość zostanie zwrócona
writeln('funkcja
– jaka_wartosc ');
end;
Var x :Integer;
Begin
x:= jaka_wartosc; //wywołanie funkcji jak funkcji i zwrot wartości
Writeln('x=',x);
jaka_wartosc ;
readln;
//wywołanie funkcji jak procedury, bez zwrotu wartości
Writeln(jaka_wartosc ); readln;
end.
Wywołanie funkcji
Przeciążanie funkcji
program Podpr4;
{$APPTYPE CONSOLE} {$O-,Q+,R+}
function dodaj(a,b :byte) : byte; Overload;
Begin
Result := a+b;
end;
function dodaj(a,b :string) : string; Overload;
Begin
Result := a+b;
end;
Begin
Writeln('dodaanie liczb=',dodaj( 1, 2 ));
Writeln('dodawanie łancuchow =',
dodaj('1','2'));
readln;
end.
Przeciążanie –
wielokrotne
Definiowanie funkcji lub
procedur o tych samych nazwach
różniących się zestawem
parametrów formalnych
wywołania.
W takim przypadku trzeba
użyć dyrektywy
overload
w nagłówku każdej przeciążonej
funkcji lub procedury.
Przeciążone funkcje w działają
odpowiednio w zależności
od aktualnych parametrów
Wywołania.
Przykłady funkcji +oper na tablicach
program Podpr3;
{$APPTYPE CONSOLE} {$O-,Q+,R+}
uses SysUtils;
type
TArr=array[1..10]of Integer;
function wypelniacz(x :Integer):TArr;
var
i: Integer;
begin
for i := 1 to 10 do
Result[i] := x;
end;
Var A :TArr;
i:byte;
begin
A := wypelniacz(2);
for i:=1 to 10 do write(A[i], ' ');
readln;
end.
Przykład- funkcja
ZAMIANY liczby
całkowitej na kod 2-10
program CardStr1;
{$APPTYPE CONSOLE} {$O-,Q+,R+}
uses SysUtils;
const MaxPodst = 10;
type TPodst=2..MaxPodst;
function Card2Str(x :Cardinal; p:TPodst):string;
type
TCyfra = 0..MaxPodst-1;
var
cyfra :TCyfra;
begin
Result := '';
repeat
cyfra := x mod p;
x := x div p;
Result := char(cyfra+byte('0')) + Result;
until x = 0;
end;
var
a :Cardinal;
b :TPodst;
begin
write('a=');readln(a);
write('podstawa systemu ');
readln(b);
writeln(Card2Str(a, b));
readln;
end.
Przykład- funkcja ZAMIANY
–efekty uboczne
program CardStr3efUbocz;
{$APPTYPE CONSOLE} {$O-,Q+,R+}
uses SysUtils;
const MaxPodst = 36;
type TPodst=2..MaxPodst;
var
x :Cardinal; p :TPodst;
function Card2Str:string;
type
TCyfra = 0..MaxPodst-1;
function CyfraZnak(c :TCyfra):char;
begin
if c <= 9 then
Result := char( c + byte('0') )
else
Result := char( c-10 +byte('A') );
end;
var
cyfra :TCyfra;
begin
Result := '';
repeat
cyfra := x mod p;
x := x div p;
Result := CyfraZnak(cyfra)
+ Result;
until x = 0;
end;
begin
write('x=');readln(x);
write('podstawa systemu
liczenia:');readln(p);
writeln(Card2Str);
writeln(Card2Str);
readln;
end.
program Sortowanie;
{$APPTYPE CONSOLE} {$O-
,Q+,R+}
uses SysUtils;
const MaxN=5;
var
N,x :Integer;
A :array[1..MaxN] of
Integer;
i :1..MaxN+1;
begin
//Read(N, A[1],..., A[N]);
write('N=');readln(N);
//czytanie rom. tab
for i := 1 to N do
begin
write('A[',i,']=');
readln(A[i]);
end;
if N > 1 then
begin
i := 2;
repeat
while A[i] < A[i-1] do
begin
x := A[i];
A[i] := A[i-1];
A[i-1] := x;
if i > 2 then
i := i-1;
end;
i := i+1;
until i > N;
end;
writeln('posortowane');
for i := 1 to N do
Writeln('A[',i,']=',A[i]);
readln;
end.
Wywołanie funkcji przez inną funkcję
W czasie wykonywania funkcji może nastąpić
wywołanie innej funkcji.
Wykonywanie bieżącej funkcji jest wówczas chwilowo
przerywane, a rozpoczyna się wykonywanie drugiej.
Po zakończeniu wykonania funkcji drugiej sterowanie
wraca do pierwszej funkcji, do miejsca gdzie została
przerwana.
W treści programu w funkcji można
umieścić wywołanie innej funkcji, która
została zdefiniowana wcześniej
Wywołanie funkcji przez inną funkcję
Zagnieżdżanie –
funkcja wywołujący
inną funkcję
function A;
begin
...
end;
Function B;
begin
...
x:=
A;
...
end;
Zagnieżdżanie –
podprogram
wywołujący inny
podprogram
procedure A;
begin
...
end;
procedure B;
begin
...
A;
end;
Zagnieżdżanie – funkcja
wywołujący inną
funkcję
function A;
Function B;
begin
...
end;
begin
...
x:=
B
;
...
end;
Przykład- fukcjA ZAMIANY
liczby całkowitej na Hex
program CardStr2;
{$APPTYPE CONSOLE} {$O-,Q+,R+}
uses SysUtils;
Const MaxPodst = 36;
type
TPodst=2..MaxPodst;
function
Card2Str(x :Cardinal; p:TPodst):string;
type
TCyfra = 0..MaxPodst-1;
function CyfraZnak(c :TCyfra):char;
begin
if c <= 9 then
Result := char( c + byte('0') )
else
Result := char( c-10 +byte('A') );
end;
Var cyfra :TCyfra;
begin
Result := '';
repeat
cyfra := x mod p;
x := x div p;
Result := CyfraZnak(cyfra)
+ Result;
until x = 0;
end;
var a :Cardinal; b :TPodst;
begin
write('a=');readln(a);
write('podstawa systemu:=');
readln(b);
writeln(
Card2Str(a, b)
);
readln;
end.
Zmienne globalne i lokalne
Możemy zdefiniować pewne zmienne, które
będą widoczne we wszystkich funkcjach
danego programu – są to tzw
zmienne
globalne
Wewnątrz funkcji można definiować zmienne,
które są
zmiennymi lokalnymi
tej funkcji
Jeśli w obrębie funkcji definiujemy jakieś zmienne,
to są one zazwyczaj pamiętane na tzw.
stosie
(czyli w obszarze „podręcznym”).
Przykład- funkcja ZAMIANY
–efekty uboczne
program CardStr3efUbocz;
{$APPTYPE CONSOLE} {$O-,Q+,R+}
uses SysUtils;
const MaxPodst = 36;
type TPodst=2..MaxPodst;
var
x :Cardinal; p :TPodst;
function Card2Str:string;
type
TCyfra = 0..MaxPodst-1;
function CyfraZnak(c :TCyfra):char;
begin
if c <= 9 then
Result := char( c + byte('0') )
else
Result := char( c-10 +byte('A') );
end;
var
cyfra :TCyfra;
begin
Result := '';
repeat
cyfra := x mod p;
x := x div p;
Result := CyfraZnak(cyfra)
+ Result;
until x = 0;
end;
begin
write('x=');readln(x);
write('podstawa systemu
liczenia:');readln(p);
writeln(Card2Str);
writeln(Card2Str);
readln;
end.
Podsumowanie
jeśli podprogram ma zwracać więcej niż jedną wartość, bądź
modyfikować wartości parametrów aktualnych użyj procedury;
jeśli ma być zwrócona dokładnie jedna wartość użyj funkcji;
jeśli oba typy podprogramów są dopuszczalne użyj tego, który jest ci
łatwiej zastosować
zmienne mające w podprogramie charakter roboczy należy
deklarować jako zmienne lokalne; bardziej bezpieczne zalecane jest
przekazywanie parametrów przez wartość (chroni przed
niepotrzebnymi zmianami tych parametrów)
jeśli parametr służy do komunikowania otoczeniu efektów wykonania
podprogramu to musi być przekazywany przez zmienną;
jeśli mamy do przekazania duże struktury danych to unikamy ich
przekazywania przez wartość –
pozwoli to na lepsze
gospodarowanie pamięcią (dla parametrów przekazywanych przez
wartość tworzona jest ich kopia na stosie);