PP W9, Podstawy programowania


9. PODPROGRAMY - FUNKCJE I PROCEDURY

9.1. Konieczność stosowania podprogramów

Podprogram to niewielki program, który zostaje uruchomiony (wywołany) w jakimś miejscu programu głównego po to, aby wykonać określone zadanie cząstkowe.

Po jego wywołaniu podprogram pobiera z programu głównego dane wejściowe, a po wykonaniu swojego zadania przekazuje do programu głównego dane wyjściowe (wyniki).

W Turbo Pascalu mamy dwa rodzaje podprogramów: funkcje i  procedury

Są co najmniej cztery powody, dla których stosowanie podprogramów jest niezbędne:

9.2. Procedury i funkcje standardowe

Turbo Pascal oferuje programistom obszerny zbiór gotowych procedur i funkcji standardowych, które mogą być wywoływane za pomocą odpowiednich instrukcji, zwanych instrukcjami wywołania, które dominują w tekście programu. Jedynie nieliczne instrukcje podstawowe: while, repeat, for, break, continue, if, case, nie są instrukcjami wywołania podprogramów.

Procedury i funkcje znajdują się w tak zwanych modułach o nazwach System, Crt, Dos, Windos, Graph, Overlay, Strings. Chcąc użyć procedury lub funkcji, zawartej w danym module, trzeba na początku programu zadeklarować użycie tego modułu, na przykład:

uses Crt,Dos;

Nie deklaruje się jednak podstawowego modułu System, którego zasoby są dołączane do programu domyślnie.

9.3. Wywołania funkcji

Funkcję wywołujemy, podając jej nazwę i po niej, w nawiasach zwykłych, argumenty, oddzielone przecinkami. Wywołania funkcji mogą być umieszczane:

Przykład

Obliczenie odległości między dwoma punktami na płaszczyźnie XY

program Ex9_1;

uses Crt;

var D,X1,Y1,X2,Y2:Real;

begin

Clrscr;

Write('Podaj X1,Y1: ');

Readln(X1,Y1);

Write('Podaj X2,Y2: ');

Readln(X2,Y2);

D:=Sqrt(Sqr(X1-X2)+Sqr(Y1-Y2));

Write('Wynik:',D:0:6);

{Można także jak poniżej: }

{Write('Wynik:',Sqrt(Sqr(X1-X2)+Sqr(Y1-Y2)));}

Readln;

end.

Często popełniany błąd to wywołaniu funkcji w następujący sposób:

Sin(X);

Przy takim wywołaniu funkcja, po dokonaniu obliczeń i przyjęciu odpowiedniej wartości, nie dałaby żadnych rezultatów, bo jej wartość nie zostaje nigdzie przekazana.

9.4. Wywołania procedur

Dotychczas poznaliśmy już kilka instrukcji wywołania procedur standardowych: Readln, Write, Writeln, Inc z modułu System oraz procedury Clrscr, Gotoxy z modułu Crt.

Ogólną postać instrukcji wywołania procedury:

nazwa_procedury(arg1,arg2, . . . argN);

Argumenty arg mogą mieć postać stałych, zmiennych lub wyrażeń. Przykłady:

Write('X1=',X1,'X2=',X2);

Readln(X,Y); {Tutaj wyłącznie nazwy zmiennych!}

Gotoxy(Wherex+1,Wherey+2);

Writeln(Sin(X));

Inc(J,2); {J musi być nazwą zmiennej!}

Mamy dwa rodzaje argumentów:

  1. Przekazywane przez wartość. Procedura traktuje takie argumenty jako dane wejściowe, kopiuje je do swojego obszaru pamięci i z tej kopii korzysta, wykonując obliczenia. Procedura w toku obliczeń może zmienić wartość kopii, ale sam argument użyty w wywołaniu nie ulega zmianie. Parametry tej grupy mogą w instrukcji wywołania mieć postać stałej jawnej, stałej definiowanej, zmiennej, lub wyrażenia, przy zachowaniu wymaganej kolejności oraz typów kolejnych argumentów.

Przykład: Gotoxy(5,Wherey);

  1. Przekazywane przez zmienną. Procedura operuje bezpośrednio na zmiennej, użytej w instrukcji wywołania, więc w toku obliczeń może zmieniać jej wartość. Dlatego ten rodzaj argumentów służy do przekazywania danych wyjściowych, czyli rezultatów działania procedury. Parametry tej grupy w instrukcji wywołania mogą mieć wyłącznie postać nazw zmiennych.

Przykład:

Readln(X,Y,Z);

Inc(X,3);

{Argument wyjściowy X musi być nazwą zmiennej!}

9.5. Definiowanie funkcji własnych

Oczywiście, funkcje standardowe oferowane w Turbo Pascalu nie spełniają wszystkich możliwych potrzeb programisty. Dlatego przewidziano możliwość definiowania w programie własnych funkcji. Definicje funkcji własnych umieszcza się przed programem głównym. Każda z nich rozpoczyna się odrębnym słowem kluczowym function. Ogólna postać definicji funkcji jest następująca:

function 

nazwa_funkcji(arg1:typ1;arg2:typ2; . . .):typ_wyniku;

var

{deklaracje zmiennych lokalnych}

begin

instrukcja_1;

instrukcja_2;

{ - - - }

instrukcja_N;

{przekazanie wyniku:}

nazwa_funkcji:= wynik_obliczeń;

end;

Uwaga: Argumenty funkcji, podobnie jak zmienne lokalne, są tworzone w momencie wywołania funkcji w obszarze pamięci zwanym stosem.

Zmienne lokalne i argumenty istnieją tylko w czasie działania funkcji i są usuwane po zakończeniu jej pracy.

Wewnątrz bloku funkcji należy wprowadzić specjalną instrukcję przypisania, która do nazwy funkcji przypisuje obliczony wynik. Jeżeli pominiemy wspomnianą instrukcję, to obliczony wynik zostanie utracony, a funkcja po jej wywołaniu przekaże jakąś przypadkową wartość.

Przykład

Program z funkcją własną, która oblicza wartość silni swojego argumentu.

program Ex9_2;

uses Crt;

var Arg:Byte;

S:Longint;

{definicja funkcji)

function Silnia(Arg:Byte):Longint;

var I:Byte;

S:Longint;

begin

if Arg>12 then S:=0

else begin

S:=1;

for I:=1 to Arg do S:=S*I;

end;

Silnia:=S; {instrukcja przekazania wyniku}

end;

{program główny}

begin

Clrscr;

Write('Podaj argument silni <13: ');

Readln(Arg);

S:=Silnia(Arg); {wywołanie funkcji}

if S=0 then Write('Argument za duzy!')

else Write('Silnia liczby ',Arg,' wynosi ',S);

Readln;

end.

Przykład

Program z funkcją własną, która oblicza średnią arytmetyczną swoich trzech argumentów.

Przed przystąpieniem do zadania dobrze jest wyobrazić sobie funkcję jako „czarną skrzynkę”, z trzema wejściami (argumentami wejściowymi), oraz wyjściem danych; w tym przypadku rolę wyjścia pełni instrukcja, która nazwie funkcji przypisuje uzyskany wynik.

X:Real ——►

Y:Real ——►

Z:Real ——►

function

Srednia

Srednia:=wynik

program Ex9_3;

uses Crt;

var

A,B,C,S:Real; {zmienne programu głównego}

{definicja funkcji}

function Srednia(X,Y,Z:Integer):Real;

var Wynik:Real;

begin

Wynik:=(X+Y+Z)/3;

Srednia:=Wynik; {przekazanie wyniku}

end;

{program główny}

begin

Clrscr;

Write('Podaj trzy liczby: ');

Readln(A,B,C);

S:=Srednia(A,B,C);{wywołanie funkcji}

Write('Wynik: ',S);

Readln;

end.

9.6. Definiowanie procedur własnych

Poniżej pokazano ogólną postać definicji procedury.

procedure nazwa(a1:typ1...; var wy1:typ1; . . .);

var {deklaracje zmiennych lokalnych}

begin

instrukcja1;

instrukcja2;

{ - - - }

instrukcjaN;

end;

Procedura może zawsze zastąpić funkcję, a funkcja - procedurę.

Przykład

Program z procedurą równoważną funkcji Srednia.

Wyobrazimy sobie tę procedurę jako „czarną skrzynkę”, pokazując wejścia i wyjścia danych. Są trzy wejścia (argumenty wejściowe) A, B, C, i jedno wyjście (argument wyjściowy var S dla przekazania wyniku.

A: Real ——►

B: Real ——►

C: Real ——►

procedure

Srednia

——► var S: Real

program Ex9_4;

uses Crt;

{zmienne programu głównego}

var A,B,C,S:Real;

{definicja procedury}

procedure Srednia(X,Y,Z:Real; var Sr:Real);

begin

Sr:=(X+Y+Z)/3;

end;

{program główny}

begin

Clrscr;

Write('Podaj trzy liczby: ');

Readln(A,B,C);

Srednia(A,B,C,S);{wywołanie procedury}

Write('Wynik: ',S);

Readln;

end.

Porównując postać funkcji Srednia z postacią procedury o tej samej nazwie, i sposoby wywołania obu tych podprogramów, zauważamy, że:

9.7. Przekazywanie danych pomiędzy programem głównym

a podprogramami

a/ Organizacja zasobów pamięci operacyjnej Turbo Pascala

STERTA

ZMIENNE DYNAMICZNE

rozmiar <= 655 kilobajtów

STOS

ZMIENNE LOKALNE, ARGUMENTY PODPROGRAMÓW

Rozmiar domyślny: 16 kilobajtów

OBSZAR ZMIENNYCH GLOBALNYCH

ZMIENNE GLOBALNE PROGRAMU

Rozmiar: 64 kilobajty

OBSZAR KODU WYNIKOWEGO

DEKLAROWANE MODUŁY+MODUŁ SYSTEM

+ SKOMPILOWANY PROGRAM .EXE

Rozmiar: co najwyżej 64 K dla każdego z modułów i dla programu

b/ Mechanizm przekazywania danych wejściowych z programu głównego do podprogramu

Rozważmy prostą procedurę, która znajduje sumę swoich argumentów oraz instrukcję wywołania tej procedury w programie głównym:

procedure Suma(X,Y:Real;

var S:Real);

begin

S:=X+Y;

end;

{program główny}

var A,B,Wynik:Real;

begin

{------}

Suma(A,B,Wynik);

{------}

end.

Argumenty wejściowe instrukcji wywołania w programie głównym są samoczynnie kopiowane do argumentów wejściowych procedury lub funkcji:

X:=A;

Y:=B;

Dlatego procedura doda te wartości, jakie mają aktualnie zmienne A, B w instrukcji wywołania.

c/ Mechanizm przekazywania danej wyjściowej z procedury do programu głównego

Słowo var użyte w definicji procedury przed argumentem S powoduje, że

wszelkie wartości nadawane argumentowi S będą jednocześnie nadawane zmiennej Wynik, użytej w instrukcji wywołania.

Mamy tutaj do czynienia z jedną zmienną (jednym obszarem pamięci) o dwóch równoważnych nazwach!

Przykład

Program znajdujący rozwiązania równania kwadratowego, który zawiera trzy procedury własne.

Ap:Real ——►

Bp:Real ——►

Cp:Real ——►

procedure

Rowkwad

——► var X1p: Real

——► var X2p: Real

——► var Kp: Byte

program Ex9_5;

{Znajduje rozwiązania równania kwadratowego.}

uses Crt;

procedure Dane(var A,B,C:Real);

begin

Write('Podaj A,B,C: ');

Readln(A,B,C);

end;

procedure Rowkwad(Ap,Bp,Cp:Real;

var X1p,X2p:Real;

var Kp:Byte);

var Delta:Real;

begin

Delta:=Bp*Bp-4*Ap*Cp;

if Delta<0 then Kp:=1

else begin

Kp:=0;

X1p:=(-Bp+Sqrt(Delta))/(2*Ap);

X2p:=(-Bp-Sqrt(Delta))/(2*Ap);

end;

end;

procedure Wyniki(X1,X2:Real; K:Byte);

begin

if K=0 then begin

Writeln('X1=',X1);

Writeln('X2=',X2);

end else Writeln('Brak pierwiastkow.');

end;

{program główny}

var A,B,C,X1,X2:Real;

K:Byte;

begin

Clrscr;

Dane(A,B,C);

Rowkwad(A,B,C,X1,X2,K);

Wyniki(X1,X2,K);

Readln;

end.

9.9. Funkcja jako podprogram uniwersalny

Funkcja, podobnie jak procedura, może zwracać wyniki obliczeń, posługując się argumentami wyjściowymi (poprzedzonymi słowem var) Na przykład funkcja własna o nagłówku:

function Rowkwad(A,B,C:Real;var X1,X2:Real):Byte;

wywołana, jak poniżej:

K:=Rowkwad(A,B,C,X1,X2);

zwróci trzy wartości - dwie wartości typu Real przez argumenty X1, X2 oraz jedną wartość typu Byte, przypisaną do zmiennej K.

Przykład

Program z poprzedniego przykładu, w którym procedury zastąpiono funkcjami

program Ex9_6;

{Znajduje rozwiązania równania kwadratowego.}

uses Crt;

function Dane(var A,B,C:Real):Byte;

begin

Write('Podaj A,B,C: ');

Readln(A,B,C);

Dane:=0;

end;

function Rowkwad(Ap,Bp,Cp:Real; var X1p,X2p:Real):Byte;

var Delta:Real;

begin

Delta:=Bp*Bp-4*Ap*Cp;

if Delta<0 then Rowkwad:=1

else begin

Rowkwad:=0;

X1p:=(-Bp+Sqrt(Delta))/(2*Ap);

X2p:=(-Bp-Sqrt(Delta))/(2*Ap);

end;

end;

function Wyniki(X1,X2:Real;K:Byte):Byte;

begin

if K=0 then begin

Writeln('X1=',X1);

Writeln('X2=',X2);

end else Writeln('Brak pierwiastkow.');

Wyniki:=0;

end;

var A,B,C,X1,X2:Real;

K:Byte;

begin

Clrscr;

Dane(A,B,C);

K:=Rowkwad(A,B,C,X1,X2);

Wyniki(X1,X2,K);

Readln;

end.

9.10. Unikanie błędów przy definiowaniu i wywoływaniu

podprogramów

60



Wyszukiwarka

Podobne podstrony:
PP temat6, Podstawy programowania
PP 11, Podstawy programowania
PP W7, Podstawy programowania
PP W6, Podstawy programowania
PP temat3, Podstawy programowania
PP W1, Podstawy programowania
PP W4, Podstawy programowania
PP 10, Podstawy programowania
PP W5, Podstawy programowania
PP W8, Podstawy programowania
PP temat2, Podstawy programowania
PP temat4, Podstawy programowania
PP temat5, Podstawy programowania
PP W2, Podstawy programowania
PP W10, Podstawy programowania
PP temat6, Podstawy programowania
zasady zaliczeń PP IG, Politechnika Białostocka, ZiIP (PB), Semestr 1, Podstawy programowania, Progr
pp projekty2004, wisisz, wydzial informatyki, studia zaoczne inzynierskie, podstawy programowania

więcej podobnych podstron