12. Podprogramy

Pavel Satrapa nazval příslušnou kapitolu ve své knize "Raději organizovat než pracovat". Vzhledem k tomu, že je vedoucím katedry informačních technologií na Technické universitě v Liberci, zřejmě ví co říká...

Pascal disponuje dvěma typy podprogramů. Jsou to procedury a funkce.


Zajímavou nabídku podprogramů najdeš např. na adrese:


12.1 Procedury

Procedura je část programu, která vykonává specifickou akci, často v závislosti na množině parametrů.

12.1.1 Syntaxe

procedure identifikátor;

NEBO

procedure identifikátor ( parametry );

12.1.2 Popis

Záhlaví procedury určuje identifikátor procedury a seznam formálních parametrů (jestliže nějaké jsou).
Procedura je aktivována příkazem volání procedury.
Za záhlavím procedury následuje blok procedury, který obsahuje:

- deklarační část lokálních objektů (konstanty, proměnné, procedury aj.)
- příkazy mezi vyhrazenými slovy a , které určují vykonávanou posloupnost příkazů při volání procedury

12.1.3 Příklad

{ Deklarace procedury }
procedure WrStr(X, Y: integer; S: string);
var
   SaveX, SaveY: Integer;
begin
   SaveX := WhereX;
   SaveY := WhereY;
   GotoXY(X, Y);
   Write(S);
   GotoXY(SaveX, SaveY);
end;


12.2 Funkce

function (vyhrazené slovo)

Funkce je blok programu, který vrací hodnotu.

12.2.1 Syntaxe

function identifikátor : typ;

NEBO

function identifikátor (parametry) : typ;

12.2.2 Popis

Záhlaví funkce určuje identifikátor funkce, formální parametry (jestliže jsou) a typ výsledku funkce.
Platný typ výsledku je ordinální, reálný, řetězec a ukazatel.
Volání funkce se objeví jako operand ve výrazu.
Za záhlavím funkce následuje blok, který obsahuje:

- deklarační část lokálních objektů (konstanty, proměnné, procedury aj.)
- příkazovou část, která určuje vykonávané příkazy při volání funkce

Příkazová část by měla obsahovat nejméně jeden příkaz, který přiřadí hodnotu do identifikátoru funkce; většinou je výsledek funkce poslední přiřazená hodnota.

12.2.3 Příklad

funkce MinimumAB vrací menší z čísel uložených v proměnných A a B:

function MinimumAB : Integer;

begin

   if A < = B then MinimumAB := B

      else MinimumAB := B;

end;

12.2.4 Cvičení:

(* Deklarace funkce *)
function UpCaseStr(S: string): string;

var

   I: Integer;

begin

   for I := 1 to Length(S) do

       if (S[I] >= 'a') and (S[I] <= 'z') then

          Dec(S[I], 32);

          UpCaseStr := S;

end;


12.3 Příklad použití procedur

Program pro uspořádávání žáků (bez použití podprogramů viz. dříve).

Všimni si:

program ProspechTridy;

{Program pro seřazení třídy podle prospěchu}

const MaxZaku = 30;

type Zak = record

           Jmeno : string;

           Prumer : Real;

       end;

var Trida : array [1..MaxZaku] of Zak;

      PocetZaku : Integer;

procedure Inicializace;

         {počáteční inicializace proměnných}

begin

   PocetZaku := 0;

   Writeln ( 'Seřazení žáků podle průměru.' );

end;

procedure NactiTridu;

       {načte informace o všech žácích ve třídě}

      procedure PridejZaka;

      {přidá nového žáka a načte informace o něm}

      begin

         PocetZaku := PocetZaku + 1;

         with Trida[PocetZaku] do

              begin

                  Write ( 'Jméno:' );

                  Readln ( Jmeno );

                  if Jmeno <> '' then

                      begin

                         Write ( 'Průměr:' );

                         Readln ( Prumer );

                     end;

              end;

        end;

begin {NactiTridu}

        Writeln ( 'Prázdné jméno ukončí vstup.' );

        repeat

             PridejZaka;

             if PocetZaku = MaxZaku then

                   Writeln ( 'Naplněna kapacita. Ukončuji vstup.' );

        until (Trida[PocetZaku].Jmeno = '') or                                              (PocetZaku = MaxZaku);

        if Trida[PocetZaku].Jmeno = '' then

                PocetZaku := PocetZaku - 1;

end; {NactiTridu}

procedure SeradTridu;

             {uspořádá žáky podle položky Prumer}

var Prvni, Nejlepsi, I : Integer;

      PomZ : Zak;

begin

      for Prvni := 1 to PocetZaku-1 do

             begin

                Nejlepsi := Prvni;

                for I := Prvni+1 to PocetZaku do

                         if Trida[I].Prumer < Trida[Nejlepsi].Prumer then

                                  Nejlepsi := I;

                PomZ := Trida[Prvni];

                Trida[Prvni] := Trida[Nejlepsi];

                Trida[Nejlepsi] := PomZ;

            end;

end;

procedure TiskniTridu;

             {vypíše informace o žácích ve třídě}

var I : Integer;

begin

       for I := 1 to PocetZaku do

              with Trida[I] do

              Writeln ( Jmeno, ' (', Prumer:4:2, ')' );

end;

begin

    Inicializace;

    NactiTridu;

    SeradTridu;

    TiskniTridu;

end.


12.4 Volání procedury

procedure Vymen ( var I, J : Integer)

var Pom : Integer;

begin

  Pom := I;

  I := J;

  J: = Pom;

end;

 

Tuto proceduru voláme Vymen (A,B);

Proměnná Pom deklarovaná přímo v těle procedury se označuje jako lokální proměnná a má lokální platnost (= jen pro proceduru). Lokální proměnná je opakem globální proměnné (= platí pro celý program).

 


12.5 Příklad: rekurzivní funkce

 

Výpočet faktoriálu čísla N, program fakt1.pas.

Algoritmus vychází ze vzorce n! = n  x (n - 1)!   {x znamená krát}

 

function Faktorial1 ( N : Integer ) : Integer;

begin

   if N = 0 then Faktorial1 := 1

      else

        if N > 0 then

           Faktorial1 := N * Faktorial1(N-1)

        else

           begin

              Writeln ( 'Faktoriál čísla < 0 ???' );

              Faktorial1 := 0;

           end;

end;

 

Pozornost si zaslouží řádek

           Faktorial1 := N * Faktorial1(N-1)

Funkce Faktorial1 volá sama sebe - je rekurzní...

Zásady pro rekurzivní podprogramy:

  1. Musí být definován konec - situace, kdy je problém natolik zjednodušen, že lze stanovit řešení. Zde je to rovnost 0! = 1.

  2. V každém kroku rekurze musí dojít ke zjednodušení problému. Zde je to zvolení vždy o jedničku menšího čísla pro výpočet faktoriálu.

  3. Nejprve se musí prověřit, zda nenastala koncová situace. Když ne, provede se rekurzivní krok. Proto je rovnost 0! = 1 první. Při opačném pořadí by se vždy uplatnil rekurzivní krok a výpočet by proletěl okolo nuly k mínus nekonečnu.

 

Druhá možnost řešení výpočtu faktoriálu (program fakt2.pas):

function Faktorial2 ( N : Integer ) : Integer;

var Fakt, I : Integer;

begin

  if N < 0 then

     begin

       Writeln ( 'Faktoriál čísla < 0 ???' );

       Faktorial2 := 0;

     end

  else

     begin

       Fakt := 1;

       for I := 2 to N do Fakt := Fakt * I;

          Faktorial2 := Fakt;

     end;

end;

Tento algoritmus vychází ze vztahu n! = n x (n - 1) x (n - 2) x .... x 2 x 1. Toto řešení je iterativní (cyklem).


 

12.6 Cvičení

Fibonacciho posloupnost je definována:

F(0) = 1

F(1) = 1

F(n) = F(n-1) + F(n-2) pro n > 1

Naprogramuj funkci Fibonacci1 a Fibonacci2 počítající n-tý prvek této posloupnosti rekurzivně i iterativně. Srovnej dobu výpočtu.

...řešení


<-předchozí

další->

 

© 2001 Milan Volejník, http://hledej.to.zde.cz

aktualizace: 17.09.2002 17:25:35

Powered by Notepad editor.
Copyright © 2001 by !!!Protiproud!!! All rights reserved.
Revised: 17 IX 2002 17:49:11 +0200 .