Podprogramy

Čo sú podprogramy?
časť hlavného programu, ktorá je nahradená jedným príkazom - volaním podprogramu. Hlavný program sa tým skráti a získa sa na prehľadnosti. Program, ktorý používa podprogramy možno ladiť po častiach, čím sa ľahšie odstraňujú sémantické chyby. Ďalšou výhodou je, že si môžem vytvárať podprogramy pre viacnásobné využitie vo viacerých programoch -databáza podprogramov.
Samozrejme, že "nový" príkaz - volanie nášho podprogramu musíme niekde v programe počítaču "vysvetliť". Obyčajne sa podprogramy vysvetľujú - deklarujú v deklaračnej časti hneď za deklarácie premenných. Štruktúra podprogramu je veľmi podobná hlavnému programu, tiež má
  1. hlavičku
  2. deklaračnú časť
  3. príkazovú časť
Syntax:
Procedure názov (parametre);
deklaračná časť podprogramu
begin
príkazová časť podprogramu
end;
Hlavička
Je na rozdiel od hlavného programu povinná. Skladá sa z kľúčového slova procedure, identifikátora podprogramu, za ktorým môžu byť v okrúhlych zátvorkách zadeklarované parametre.
Parametre
Pokiaľ podprogram má parametre, sú uvedené/zadeklarované v okrúhlej zátvorke a deklarácie sú oddelované bodkočiarkami (podobne ako premenné v deklaračnej časti). Jediný rozdiel medzi parametrom a lok. premennou je ten, že je parametre sú inicializované na hodnotu určenú pri volaní, lokálne premenné majú pri vzniku náhodné hodnoty.
Deklaračná časť
Platia tie isté pravidlá ako pri hlavnom programe. Premenné tu zadeklarované voláme lokálne a platia len vo vnútri podprogramu. V prípade, ak v hlavnom programe je rovnaký objekt s takým názvom už zadeklarovaný, lokálna deklarácia má v podprograme prednosť a takýto objekt z hlavného programu je v podprograme neviditelný - je odtienený. Lokálne premenné sú uložené v zásobníku (teda inde ako globálne premenné) a ich množstvo je ohraničené maximálnou veľkosťou zásobníka 64kB. Lokálne premenné nie sú inicializované ako globálne premenné a ich počiatočná hodnota je náhodná.
V deklaračnej časti môžu byť zadeklarované aj podprogramy viditeľné len z tohoto podprogramu, tiež typy premenných platné len pre tento podprogram.
Teda program môže pracovať s dvoma 60kB poliami - jedno bude zadeklarované v hlavnom programe a druhe v podprograme.
Pozn. : Premenné zadeklarované v hlavnom programe voláme globálne a sú viditelné v celom programe, a teda aj vo všetkých podprogramoch (ak nie sú odtienené).
Príkazová časť
Narozdiel od hlavného programu je ukončená end; a nie end. ako hlavný program.
Volanie:
názov ... pre podprogram bez parametrov
názov( hodnoty parametrov) ... pre podprogram s parametrami
Keď program narazí na takýto príkaz vykoná celú príkazovú časť podprogramu.
Úlohy:
  1. Napíš program, ktorý napíše v jednom riadku n-krát *.
  2. Vytvor podprogram opakuj do ktorého príkazovej časti okopíruj "výkonnú časť" príkazovej časti hlavného programu a tú nahraď volaním podprogramu opakuj
  3. Prerob podprogram na podprogram s dvoma parametrami
  4. Uprav podprogram, aby nemenil hlavnému programu premenné
Riešenia úloh:
  1. Úloha

    Program hviezdicky1;
    Var n,i:integer;
    Begin
      write('Zadaj pocet:'); readln(n);
      clrscr;
      for i:= 1 to n do write('*');
    end.

    Označený riadok zoberieme a vytvoríme pomocou neho príkazovú časť podprogramu opakuj. Namiesto neho v hl. programe napíšeme riadok opakuj;. Tým sme sa dostali ku Úlohe2.
  2. Úloha

    Program hviezdicky2;
    Var n,i:integer;
    Procedure opakuj;
    Begin
      for i:= 1 to n do write('*');
    end.

    Begin
      write('Zadaj pocet:'); readln(n);
      clrscr;
      opakuj;
    end.

    Aké nedostatky má náš nový príkaz opakuj.
    Prvý a najväčší nedostatok je v tom, že vyžaduje aby počet hviezdičiek bol uložený v premennej n. Takto sa "pascalovské" podprogramy (gotoxy, color, ...) nechovajú. Údaje, ktoré chceme podprogramu doniesť bývajú uvedené v zátvorke za názvom podprogramu - napr. setcolor(14).
    Druhý nedostatok je v tom, že je málo univerzálny - vie kresliť len hviezdičky.
    Oboje opravíme pridaním dvoch parametrov, prvý - počet, druhý - aký znak.
  3. Úloha

    Program znaky1;
    Var n,i:integer;
       z:char;
    Procedure opakuj(pocet:integer; znak:char);
    Begin
      for i:= 1 to pocet do write(znak);
    end.

    Begin
      write('Zadaj pocet:'); readln(n);
      write('Zadaj znak:'); readln(z);
      clrscr;
      opakuj(n,z);
    end.

    Vidíme, že s premennými pocet, znak pracujeme ako s ostatnými, len majú v podprograme určenú štartovnú hodnotu - podľa hodnoty parametrov pri volaní. Takto napísaný podprogram už robí, čo od neho chceme, ale pri podrobnejšom skúmaní zistíme, že robí ešte aj niečo navyše a to, že mení hlavnému programu jednu premennú - i. To niekedy môže vadiť a viesť ku ťažko odhaliteľnej chybe, takže našou snahou bude, aby sme zabránili podprogramu nechcene ovplyvňovať beh hlavného programu zmenou premenných resp. obrazovky.Dosiahneme to tak, že v podprograme vytvoríme lokálnu premennú i.
  4. Úloha

    Program znaky2;
    Var n,i:integer; {globalne premenne vsade viditelne}
       z:char; {globalna premenna vsade viditelna}
    Procedure opakuj(pocet:integer; znak:char);
    Var i:integer; {lokalna premenna - plati len v tomto podprograme}
    {premenna i z hlavneho programu je tu nedostupna a teda ju tu nemozno menit}
    Begin
      for i:= 1 to pocet do write(znak);
    end.

    Begin
      write('Zadaj pocet:'); readln(n);
      write('Zadaj znak:'); readln(z);
      clrscr;
      opakuj(n,z);
    end.

    Tým náš podprogram dospel do určitej dokonalosti a môžme ho používať v programoch.
Neriešené úlohy
  1. Úloha - Načítaj a,b prirodzené. Pomocou opakuj vytvor na obrazovke vlavo hore obdĺžnik o a-riadkoch a b-stĺpcoch vyplnený hviezdičkami.
  2. Úloha - Načítaj a,b prirodzené. Pomocou opakuj vytvor hore v strede obrazovky obdĺžnik o a-riadkoch a b-stĺpcoch vyplnený hviezdičkami.
  3. Úloha - Načítaj a prirodzené. Pomocou opakuj vytvor v strede obrazovky rovnoramenný trojuholník o základni a a výške a vyplnený hviezdičkami.
  4. Úloha - Načítaj a prirodzené. Pomocou opakuj vytvor v strede obrazovky presýpacie hodiny o základni a a výške 2a vyplnený hviezdičkami.
Pojmy na opakovanie:
Lokálne premenné
Sú premenné, ktoré sú zadeklarované v podprogramoch, žijú a sú viditeľné len počas vykonávania konkrétneho podprogramu. Pred prvým priradením je v nich náhodná hodnota - globálne číselné sú napr. nulované. Pri vbehnutí do podprogramu, tieto premenné vzniknú po opustení podprogramu zase zaniknú.
Globálne premenné
Sú premenné zadeklarované v hlavnom programe, žijú počas celého behu programu. Sú viditelné zo všetkých podprogramov, okrem prípadov, keď sú odtienené lokálnymi premennými rovnakého mena. Pred prvým priradením nejakej hodnoty majú predpísanú inicializačnú hodnotu
číselné - sú nastavené na nulu
znaky - sú nastavené na znak #0
reťazce - sú nastavené na prázdny reťazec
pointre - sú nastavené na nil
Parametre
Sú vlastne tiež lokálne, len pri vzniku získajú hodnotu podľa skutočných parametrov pri volaní. Parametre v deklarácii podprogramu voláme formálne, parametre pri volaní voláme skutočné.Skutočný parameter môže byť
výraz - pre vstupné parametre
premenná - pre vstupno-výstupné parametre
Parametre poznáme
vstupné - ich zmena nemá vplyv na žiadnu globálnu premennú
vstupno-výstupné - používame na prenos jedného z výsledkov podprogramu do hlavného programu. Poznáme ich podľa toho, že majú pred deklaráciou slovoVar.
Príklady:
Procedure x(a,b:integer); {a,b sú vstupné parametre}
Procedure y(Var a:integer;b:integer); {a je vstupno-výstupný parameter, b je vstupný parameter}
Parameter nemôže byť popisného typu, to znamená v deklarácii parametra nemôžeme používať slová array, record, set of, ani operátor ^. Ako typy premenných sú povolené len identifikátory typu.
Deklarácia podprogramu
V niektorej deklaračnej časti programu alebo podprogramu môžme vytvoriť popis podprogramu, ktorý sa skladá z:
hlavičky
deklaračnej časti
príkazovej časti - na rozdiel od hlavného programu je ukončená end;
Viditelnosť podprogramov
podprogram môže volať a teda vidí:
sám seba
svoje deti - podprogramy v ňom zadeklarované
svojich starších súrodencov - podprogramy, ktoré majú rovnakého rodiča a sú "nad ním" vo výpise.
Volanie podprogramu
Podprogram voláme svojím menom a v zátvorke uvedieme skutočné parametre. Samozrejme volať možno iba tie podprogramy, ktoré sú z daného miesta viditeľné.
Úlohy:

Podprogramy - funkcie

Čo sú funkcie?
Je to podprogram, ktorého výsledkom (resp. hlavným výsledkom) je nejaká hodnota. My sme sa už s funkciami stretli napr. random(100), sin(0,5) a doteraz sme sa nestarali ako pascal vypočíta hodnotu randomu alebo sínisu. Keď chceme vytvárať svoje funkcie musíme určiť postupnosť príkazov, ktoré požadovanú hodnotu vypočítajú.
Deklarácia funcie
Volanie
Volanie podprogramu-procedury sme robili zadaním názvu na samostatnom riadku v príkazovej časti. Funkcia býva často volaná ako súčasť nejakého výrazu.
Napr.
a:= 3*Max(a,b)-2*Max(c,d);
a:= Max(a,Max(b,c));
Úlohy: