Download presentation
Presentation is loading. Please wait.
Published byEduard Brož Modified over 6 years ago
1
Prednáška 8 podprogramy typy podprogramov lokálne a globálne objekty
procedúry funkcie parametre volané hodnotou a adresou
2
Motivačný príklad Nakreslite vláčik s 10 vozňami a lokomotívou.
3
Diskusia rozdeľme úlohy na nakreslenie vozňov a nakreslenie lokomotívy
vozeň pozostáva z obdĺžnika a dvojice kružníc, napr.: Image1.Canvas.Rectangle(100,100,140,120); Image1.Canvas.Ellipse(105,115,115,125); Image1.Canvas.Ellipse(125,115,135,125); realizovať výpočty a triafať sa do súradníc je časovo i psychicky náročné existuje jednoduché riešenie, prostredníctvom ktorého vykreslíme naraz celý vozeň
4
Podprogramy ucelené a relatívne samostatné časti programu (nakreslenie vozňa) obvykle zodpovedajú algoritmu riešiacemu čiastkovú úlohu (nakreslenie vozňa) umožňujú vytváranie hierarchie programu, zvyšujú prehľadnosť a v niektorých prípadoch sú nevyhnutnými súčasťami aplikácie stretli sme sa s nimi už pri vytváraní prvého programu každá udalosť komponentu je obsluhovaná prostredníctvom samostatného podprogramu (procedúry)
5
Môj prvý podprogram ako zabezpečiť, aby sa vozeň vykreslil na zadanej súradnici? musí ju poznať časť programu, ktorá bude vykreslenie realizovať musí túto pozíciu od hlavného programu získať
6
Môj prvý podprogram II. zápis by mohol vyzerať nasledovne:
Image1.Canvas.Rectangle(x,y,x+40,y+20); Image1.Canvas.Ellipse(x+5,y+15,x+15,y+25); Image1.Canvas.Ellipse(x+25,y+15,x+35,y+25); odkiaľ vezmem x a y? priradím pred každým zavolaním/zadaním uvedeného kódu vytvorím z vozňa podprogram a súradnice budem posielať ako parametre
7
Procedúra existujú dva typy podprogramov (neskôr), my využijeme procedúru: procedure Vozen(x,y:integer); begin Image1.Canvas.Rectangle(x,y,x+40,y+20); Image1.Canvas.Ellipse(x+5,y+15,x+15,y+25); Image1.Canvas.Ellipse(x+25,y+15,x+35,y+25); end;
8
Umiestnenie procedúry
pri vytváraní vlastného podprogramu ho budeme spočiatku viazať na form (unit), v ktorom ho vytvárame - zjednoduší sa prístup ku komponentom (pokiaľ sa na ne budeme v rámci podprogramu odvolávať) - zlepší sa prehľadnosť kódu: v implementačnej časti: budeme pred názov vkladať jeho vlastníka (napr. TForm1), do interface: budeme vkladať ako súčasť triedy TForm1, už bez vlastníka. volanie cez názov procedúry s parametrami v zátvorkách
9
Skupina vozňov prostredníctvom cyklu a zmenou parametrov vykreslíme požadovaný počet vozňov nasledovne: procedure TForm1.Button2Click(Sender:TObject); var i:integer; begin for i:=1 to 10 do Vozen(i*50,100); end;
10
Lokomotíva využijeme hotový podprogram vozňa, pridáme len komín a kabínu pre rušňovodiča procedure TForm1.Lokomotiva(x,y:integer); begin Vozen(x,y); Image1.Canvas.Rectangle(x+10,y,x+15,y-10); Image1.Canvas.Rectangle(x+25,y,x+40,y-10); end;
11
Záver podprogram možno volať aj z iného podprogramu
12
Možnosti použitia podprogramov
systémom generované podprogramy pri zložitejších aplikáciách je vhodné vytvárať i podprogramy vlastné možnosti použitia: v programe sa vyskytuje úplne rovnaká postupnosť príkazov viackrát na rôznych miestach je bez diskusie, že opakovanie tých istých postupností príkazov vedie jednak k nehospodárnemu využívaniu prostriedkov: (zbytočne sa zväčšuje veľkosť výsledného súboru a to ako exe, tak i zdojového kódu) a predstavuje nočnú moru pre tých, ktorí majú zdrojový kód neskôr ladiť – každú úpravu treba realizovať na všetkých miestach
13
Použitie podprogramov II.
v programe sa viackrát vyskytuje podobná postupnosť príkazov odlišujúca sa iba parametrami otváranie dvoch rôznych súborov a ich prečítanie do rôznych Listboxov, hľadanie NSD v rámci aplikácie na viacerých miestach a pod. množstvo grafických príkladov
14
Použitie podprogramov III.
potrebujeme zvýšiť prehľadnosť programu a priblížiť jeho zápis “ľudskému” riešeniu veľmi častý dôvod, pri ktorom programátor postupuje pri vytváraní programu tak, že najprv určí postupnosť vykonania jednotlivých podprogramov slovne, a až potom ich „kóduje“ napr.: VycistiMriezku; NacitajHodnotyZoSuboru; NajdiNajmensiPrvok; Vypis; výhodou takéhoto postupu je, že okrem zrozumiteľného zápisu algoritmu si ujasní vlastné myšlienkové pochody ešte predtým ako začne písať samotný kód
15
Použitie podprogramov IV.
riešenie je formulované rekurzívne: celkové riešenie získame tak, že pojem je opísaný pomocou “samého seba” napr. n!=n*(n-1)! an=an-1+d a pod.
16
Zhrnutie Čo je podprogram?
relatívne samostatný algoritmus, ktorý je možné vykonávať samostatne alebo v závislosti na iných prvkoch programu často ide o postup, ktorý je v rámci programu používaný viac ráz na rôznych miestach
17
Štruktúra podprogramu
každý podprogram si vyžaduje: určenie jednoznačného názvu definovanie typov/deklaráciu premenných zápis príkazov do tela vo všeobecnosti má tvar hlavička podprogramu deklaračná časť; begin algoritmus podprogramu end
18
Typy podprogramov procedúry a funkcie procedúra funkcia
postupnosť príkazov – čiastkový program, ktorá má na starosti vykonanie postupnosti príkazov pojem je všeobecnejší ako pojem funkcie dokáže pracovať bez návratu hodnoty, alebo vrátiť akýkoľvek počet výsledkov napr. VymazHodnoty, VratMinimumAMaximumZPola funkcia špecifický prípad procedúry používa sa vtedy, ak potrebujeme zostaviť čiastkový algoritmus, ktorého volaním sa získava funkčná hodnota napr. VratPI, ZistiMaxZDvochCisel a pod.
19
Procedúry I. automaticky generované
udalostné procedúry pre definované udalosti komponentov zoznam udalostí na záložke Events Object Inspectora dvojklik vytvorí obslužnú procedúru v prípade existencie iných udalostných procedúr možno vybrať zo zoznamu podmienkou sú rovnaké parametre
20
Procedúry II. podprogramy vytvárame (zatiaľ) ako súčasť formulára
vytvárané (zapisované) manuálne treba si uvedomiť nasledovné fakty: procedúry patriace formuláru sú umiestnené v samostatnom súbore – unite. Každý unit pozostáva z dvoch základných častí: interface (rozhranie) zoznam použitých unitov (iných), zoznam typov a v rámci definovaného typu pre formulár (TFormx) i zoznam podprogramov, ktoré sú preň vytvorené, sekciu končí deklaračná časť. implementation (implementačná časť) zdrojový kód podprogramov definovaných v časti interface. podprogramy vytvárame (zatiaľ) ako súčasť formulára názov (hlavičku vkladáme do tela Formx) a pred názov podprogramu v implementačnej časti uvádzame „Formx.“.
21
Interface a implementation
22
Príklad Napíšte procedúru, ktorá sa vykoná kliknutím na tlačidlo Štart a vykreslí do Image1 hviezdičky. Vkladajte ich tak, že do prvého riadku vložíte jednu, do druhého dve, atď. až do riadku, ktorého poradové číslo je zadané v Edite.
23
Riešenie 1. procedúra hviezdičky sa z udalostnej proce- dúry pre tlačidlo len zavolá a tým poprie akýkoľvek zmysel používania procedúr: rovnaký efekt by sme dosiahli jej priamym zápisom do udalostnej procedúry navyše by sme ušetrili riadok kódu a definíciu procedúry
24
Riešenie 1. kód na vypísanie hviezdičiek: procedure TForm1.Hviezdicky;
var n,i,j:integer; riadok:string; begin n:=StrToInt(Edit1.Text); for i:=1 to n do begin riadok:=''; for j:=1 to i do begin riadok:=riadok+'*'; end; Image1.Canvas.TextOut(10,i*10,riadok);
25
Riešenie 2. ak by sme chceli napísať napr. procedúru na iný spôsob vloženia hviezdičiek, napr. od n po 1, ***** **** *** ** * museli by sme zasa vytvárať takú istú procedúru a neušetril by sa ani riadok kódu skúsme teda najprv počet hviezdičiek načítať v udalostnej procedúre tlačidla a len príkazy venované vkladaniu do obrázka realizovať v samostatnej procedúre
26
Riešenie 2. kód zápis na obrázku vedie ku kolapsu
premenná n nie je totiž mimo procedúry, v ktorej je definovaná, známa ide o tzv. lokálnu premennú, s nasle- dovnými vlastnosťami: vzniká pri zavolaní procedúry a pri jej ukončení pamäť uvoľňuje je použiteľná a viditeľná len v tele procedúry, ktorej patrí
27
Riešenie 2. oprava na to, aby sme mohli premennú použiť vo viac ako v jednej procedúre, ju potrebujeme definovať ako: globálnu v rámci formulára premennú deklarujeme v rámci časti private alebo public v tele formulára v sekcii Type stane sa súčasťou formulára 1 rovnako ako procedúra, ktorú sme vytvárali pokiaľ ju budeme potrebovať volať z iného fomulára, budeme k nej pristupovať ako Form1.n
28
Riešenie 2. oprava globálnu v rámci aplikácie
premennú deklarujeme v sekcii var v ľubovoľnom formulári bude nezávislou na formulároch a prístupnou len na základe svojho mena z ľubovoľného miesta aplikácie
29
Riešenie 2. zase problém v oboch prípadoch však máme problém, spočívajúci v tom, že po spustení aplikácie nás obrázok jednoducho ignoruje dôvodom je, že počet prvkov v udalostnej procedúre tlačidla načítavame do lokálnej premennej n deklarovanej len v rámci udalostnej procedúry v jej deklaračnej časti táto lokálna premenná prekryje globálnu premennú rovnakého mena a v rámci jej lokality sa globálna premenná ignoruje => zostáva jej preddefinovaní hodnota – pravdepodobne 0
30
Riešenie 2. riešenie problému
vymazať deklaráciu lokálnej premennej a je to Toto riešenie je veľmi neefektívne, neelegantné a nesprávne Pokiaľ možno, globálnym premenným sa treba vyhýbať
31
Úloha 2 Pridajte do programu 5 tlačidiel, ktoré budú vkladať do obrázku 3,6,9,12 a 15 radov hviezdičiek podľa už uvedených pravidiel. mohli by sme v každej udalostnej procedúre tlačidiel vkladať do premennej n príslušnú hodnotu, no krajším riešením bude použitie parametra, ktorý procedúre Hviezdicky priamo do tela oznámi, koľko hviezdičiek požadujeme. aby sme nemuseli obrázok stále vymazávať pošleme do podrpogramu aj x-ovú pozíciu, na ktorej chceme postupnosť vykresliť
32
Úloha 2 kód procedure TForm1.Hviezdicky(x,n:integer); var i,j:integer; riadok:string; begin for i:=1 to n do begin riadok:=''; for j:=1 to i do begin riadok:=riadok+'*'; end; Image1.Canvas.TextOut(x,i*10,riadok); analógia s pôvodnou procedúrou, pribudli len parametre v zátvorke
33
Úloha 2 diskusia parameter je potrebné uvádzať (aj) v definičnej časti formulára (Type) v samotnom kóde procedúry je jeho použitie dobrovoľné no odporúčané (aby sme vedeli, ktorá premenná reprezentuje parameter a ktorá je napr. globálna) premenná s názvom parametra je po jeho vstupe do procedúry akoby nahradená „prinesenou“ hodnotou do premennej s názvom parametra možno priraďovať hodnotu, no dôrazne to neodporúčame – rozpor s logikou parameter rovnako ako lokálne premenné prekrýva premenné globálne globálne n môžeme tým pádom vymazať
34
Úloha 2 volanie procedúry
parameter je celočíselný, do procedúry preto z jednotlivých tlačidiel budeme posielať požiadavku nasledovným spôsobom: Hviezdicky(10,3); Hviezdicky(100,6); .... aby nám fungovala aj predchádzajúca činnosť, môžeme upraviť procedúru na vkladanie počtu hviezdičiek podľa hodnoty v edite: procedure TForm1.Button1Click(Sender: TObject); begin Hviezdicky(200,StrToInt(Edit1.Text)); end;
35
Úloha 3 Napíšte program, ktorý do obrázka bude vkladať pre počet zadaný v edite hviezdičky tak, že začne počtom zadaným v edite, potom ho o jedna zmenší, atď až po 1. pre hodnotu 5: ***** **** *** ** *
36
Úloha 3 - kód procedure TForm1.Hviezdicky(x,n:integer); var i,j:integer; riadok:string; begin for i:=n downto 1 do begin riadok:=''; for j:=1 to i do begin riadok:=riadok+'*'; end; Image1.Canvas.TextOut(x,i*10,riadok); downto riadi beh cyklu opačným smerom – od väčšej hodnoty k menšej
37
Úloha 3 - kód na sprehľadnenie úlohy existujúci kód mierne upravíme:
procedure TForm1.Hviezdicky(x,n:integer); var i,j:integer; riadok:string; begin for i:=n downto 1 do begin NaplnRiadok(i); Image1.Canvas.TextOut(x,i*10,riadok); end; NaplnRiadok zabezpečí naplnenie premennej riadok počtom i hviezdičiek
38
Procedúra v procedúre v danej situácii je najrýchlejším riešením doplnenie procedúry do tela už existujúcej procedúry s tým, že má prístup ku všetkým premenným, ktoré sú deklarované v nadradenom podprograme: procedure TForm1.Hviezdicky(n:integer); var i,j:integer; riadok:string; procedure NaplnRiadok(pocet:integer); begin riadok:=‘’; for j:=1 to pocet do riadok:=riadok+’*’; end; //**************************************** for i:=n downto 1 do begin NaplnRiadok(i); Image1.Canvas.TextOut(x,i*10,riadok);
39
Procedúry na rovnakej úrovni
predchádzajúci zápis však protirečí požiadavke hromadného využívania procedúr – ak by sme chceli naplnenie riadku využiť z iného miesta ako z procedúry Hviezdicky, nemáme k nej prístup – preto ju „osamostatníme“: procedure TForm1.NaplnRiadok(pocet:integer); begin riadok:=‘’; for j:=1 to pocet do riadok:=riadok+’*’; end; pri tomto zápise je však na premennú riadok položená požiadavka na prístupnosť z oboch procedúr => globálnosť a tým pádom neohrabanosť a znižovanie prehľadnosti
40
podobne, ako sme zaviedli parameter pri posielaní hodnoty do procedúry, zavedieme parameter i na získanie hodnoty premennej, ktorá bola v tele procedúry zmenená premenná, ktorej hodnotu chceme z volanej procedúry získať, však potrebuje určité previazanie na premennú z volajúcej procedúry toto previazanie zabezpečuje systém tak, že sa postará aby premenná z volanej i premenná z volajúcej procedúry ukazovali na to isté pamäťové miesto ak sa potom v rámci volanej procedúry zmení hodnota príslušnej premennej, je po jej ukončení to isté (a zmenené) pamäťové miesto k dispozícii aj premennej z volajúcej procedúre parametre, ktoré do procedúry s týmto úmyslom posielame sa označujú ako parametre volané adresou a v hlavičke procedúry nesú pred názvom var spárenie premenných vo volanej a volajúcej procedúre je dané ich poradím v hlavičke i volaní procedúry
41
Volanie adresou procedure TForm1.NaplnRiadok(poc:integer;var riadok:string); var j:integer; begin riadok:=‘’; for j:=1 to poc do riadok:=riadok+’*’; end; //******************************************* procedure TForm1.Hviezdicky(x,n:integer); var i:integer; riadok:string; for i:=n downto 1 do begin NaplnRiadok(i,riadok); Image1.Canvas.TextOut(x,i*10,riadok); len zhodou okolností vystupuje premenná riadok v oboch procedúrach, nie je nutné aby niesli rovnaký názov
42
Diskusia názov premennej, do ktorej požadujeme vrátenie hodnoty, nemusí byť totožný s názvom premennej používanej v procedúre vďaka odkazu na rovnakú adresu v pamäti druhým parametrom našej procedúry však MUSÍ byť premenná hodnota totiž nemá adresu ešte efektívnejší zápis nám v tomto prípade poskytnú funkcie
43
Funkcie špeciálny typ podprogramov
ako výsledok svojej činnosti vracajú hodnotu zápis: function Nazov(prip.parametre):typ navratovej hodnoty var deklaracia potrebnych premennych begin telo funkcie end ostatné možnosti a požiadavky sú rovnaké ako v prípade procedúr vrátane posielania parametrov a volaní adresou
44
Riešenie úlohy prostredníctvom funkcie
od funkcie NaplnRiadok budeme chcieť, aby nám vrátila string, ktorý potom vložíme do obrázku zbavíme sa tým potreby použitia premennej, ktorá by nám vracala hodnotu function TForm1.NaplnRiadok(poc:integer):string; var j:integer; riadok:string; begin riadok:=‘’; for j:=1 to poc do riadok:=riadok+’*’; // do nazvu funkcie priradime premennu, ktorej hodnotu // chceme pouzit ako navratovu NaplnRiadok:=riadok; end; návratovú hodnotu získavame jednoduchým priradením hodnoty názvu funkcie
45
Riešenie úlohy prostredníctvom funkcie II.
napĺňanie hviezdičiek potom môže vyzerať napr.: procedure TForm1.Hviezdicky(x,n:integer); var i:integer; riadok:string; begin for i:=n downto 1 do begin riadok:=NaplnRiadok(i); Image1.Canvas.TextOut(x,i*10,riadok); end;
46
Riešenie úlohy prostredníctvom funkcie III.
alebo ešte lepšie: procedure TForm1.Hviezdicky(n:integer); var i:integer; begin for i:=n downto 1 do begin Image1.Canvas.TextOut(x,i*10,NaplnRiadok(i)); end; vo funkcii sme síce nejaký ten riadok pridali, ale pri jej viacnásobnom použití očividne ušetríme
47
ak návratové hodnoty nepožadujeme, postačí nám procedúra
Čo je lepšie? v prípade požiadavky jedinej návratovej hodnoty je prehľadnejší zápis funkcie pokiaľ potrebujeme vrátiť viac hodnôt, riešením je použitie parametrov volaných adresou a je v podstate jedno, či ako súčasť procedúry alebo funkcie ak návratové hodnoty nepožadujeme, postačí nám procedúra
48
Príklad 1 Napíšte funkciu, ktorá z dvoch zadaných čísel vráti minimum.
function TForm1.min(a,b:integer):integer; begin if a>b then min:=b else min:=a; end; volanie: procedure TForm1.Button1Click(Sender: TObject); var a,b:integer; a:=StrToInt(Edit1.Text); b:=StrToInt(Edit2.Text); Label1.Caption:=IntToStr(Min(a,b));
49
Príklad 1 a dokonca je možné aj nasledovné volanie:
procedure TForm1.Button1Click(Sender: TObject); var a,b:integer; begin a:=StrToInt(Edit1.Text); b:=StrToInt(Edit2.Text); c:=StrToInt(Edit3.Text); d:=StrToInt(Edit4.Text); Label1.Caption:=IntToStr(Min(Min(Min(a,b),c),d)); end;
50
Príklad 1 Pre zadané pole nájdite minimum.
opäť môžeme riešiť prostredníctvom funkcie vstupom môže byť pole uvedené ako parameter pokiaľ ho používame ako argument, je vhodná jeho definícia v Type Type TPole=array[1..20] of integer; .... function TForm1.MinimumPola(pole:TPole;pocet:integer):integer; var i,min:integer; begin min:=pole[1]; for i:=2 to pocet do if min>pole[i] then min:=pole[i]; MinimumPola:=min; end;
51
Príklad 2 Pre zadané pole zistite jeho minimum a maximum.
požadujeme návrat dvoch hodnôt, funkcia už nepostačí, resp. bol by to nejaký ten hybrid použijeme procedúru s dvoma „var“ parametrami
52
Príklad 2 - riešenie a diskusia
procedure TForm1.MinMaxPola(pole:TPole;n:integer;var min, max :integer):integer; var i:integer; begin min:=pole[1]; max:=pole[1]; for i:=2 to n do begin if min>pole[i] then min:=pole[i]; if max<pole[i] then max:=pole[i]; end; návratové hodnoty používame priamo v tele procedúry ako obyčajné premenné fakt, že po jej ukončení budú obsahovať premenné, ktoré boli pri volaní procedúry použité na 3. a 4. pozícii ich hodnoty, je zabezpečený prostredníctvom var v hlavičke
53
Mechanizmus volania podprogramu
keď sa objaví v programe volanie podprogramu: zapamätá sa návratová adresa (kam sa bude treba vrátiť) vytvoria sa lokálne premenné procedúry (s nedefinovanou hodnotou) a formálne parametre s hodnotami nastavenými podľa vstupov prenesie sa riadenie programu do tela podprogramu vykonajú sa všetky príkazy podprogramu zrušia sa lokálne premenné riadenie sa vráti za miesto v programe, odkiaľ bol podprogram volaný kvôli potrebe vykonania všetkých týchto operácií môže byť rýchlosť programu s podprogramami o čosi nižšia ako bez ich použitia, pri súčasných procesoroch však ide o mizivé a prakticky nezmerateľné zdržanie.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.