12. Funkce II
  1. Pokuste se vytvořit aplikaci GUI, ve které do editačního ovladače budete zadávat přirozené číslo a po stisku tlačítka bude vypsána informace, zda zadané číslo je nebo není prvočíslo.
  2. Následující konzolová aplikace obsahuje rekurzivní funkci (funkce, která je volána ze sebe sama) provádějící výpočet n-té mocniny reálného čísla.

  3. long double mocnina(int exponent, long double zaklad);
    int main(int argc, char **argv)
    {
      int n;
      long double x;
      cout << "Zadej exponent a základ mocniny: ";
      cin >> n >> x;
      cout << x << " na " << n << " = " << mocnina(n, x);
      getch();
      return 0;
    }
    long double mocnina(int exponent, long double zaklad)
    {
      return (exponent < 1) ? 1 : zaklad * mocnina(exponent-1, zaklad);
    }
    Vytvořte program provádějící obdobně výpočet faktoriálu. U obou programů určete jak bude probíhat výpočet pomocí rekurzivní funkce.
  4. Vytvořte konzolovou aplikaci pracující obdobně jako příkaz type operačního systému DOS. Při vytváření programu se můžete inspirovat vzorovým příkladem k funkci fopen. Jméno vypisovaného souboru zadávejte jako parametr z příkazové řádky (pokud je zadán jiný počet parametrů než jeden, vypište signalizaci chyby). Určený soubor otevřete (funkce fopen) v textovém režimu, čtete jej po znacích (funkcí fgetc) až do konce souboru (zjistíme jej funkcí feof) a vypisujte jednotlivé znaky na obrazovku (funkcí putchar nebo datovým proudem cout). Na závěr je potřeba soubor uzavřít funkcí fclose.
  5. Upravte předchozí program tak, aby při delším souboru byl výpis na obrazovku prováděn po částech. Vypište vždy několik řádků např. 22 a čekejte na stisk libovolné klávesy.
  6. Vytvořte konzolovou aplikaci, kopírující obsah jednoho textového souboru do druhého. V novém souboru vynechte všechny znaky mezer. Jména obou souborů zadávejte jako parametry. Na závěr vypište celkový počet překopírovaných znaků.
  7. Termín rozsah určuje viditelnost proměnných v různých částech našeho programu. Mnoho proměnných má lokální rozsah. Tzn. proměnná je viditelná pouze v bloku kódu, ve kterém je deklarována. Podívejte se na následující program.

  8. #pragma hdrstop
    #include <iostream.h>
    #include <conio.h>
    //---------------------------------------------------------------------------
    #pragma argsused
    int x = 20;
    void citacCyklu(int);
    int main(int argc, char **argv)
    {
      int x = 40;
      int i = 0;
      cout << "V hlavním programu x = " << x << endl;
      bool hotovo = false;
      while (!hotovo) {
        int x;
        cout << "Zadej číslo (-1 je konec): ";
        cin >> x;
        if (x != -1) {
          cout << "V cyklu x = " << x << endl;
          citacCyklu(++i);
        }
        else hotovo = true;
      }
      cout << "Globální x = " << ::x << endl;
      getch();
    }
    void citacCyklu(int x)
    {
      cout << "Cyklus byl proveden " << x << " krát." << endl;
    }
    První věcí, které si povšimneme je to, že proměnná x je zde deklarována 4x. Nejprve je deklarována před funkcí main, dále na začátku funkce main, na začátku cyklu while a nakonec jako parametr funkce citacCyklu. Pokud deklarujeme proměnnou více než jednou, pak překladač generuje chybu "Multiple declaration for 'x'" (vícenásobná deklarace x). Tento program je ale přeložen bez chyby. Je to tím, že každá proměnná je v jiném rozsahu.
    Deklarace x uvnitř cyklu while je lokální v bloku kódu tohoto cyklu. Neexistuje mimo tento blok. Tato proměnná má lokální platnost. Podobně deklarace parametru funkce je lokální ve funkci citacCyklu a neexistuje mimo tuto funkci. V tomto případě se jedná o část seznamu parametrů, ale je to také deklarace proměnné.
    Dále se podíváme na proměnné x a i deklarované na začátku funkce main. Tyto proměnné jsou lokální v bloku, ve kterém jsou deklarovány. Jinými slovy, proměnné x a i jsou v rozsahu funkce main a v rozsahu cyklu while. U proměnné i je to jasné. Jak je to ale s x? Uvnitř cyklu while jsou dvě proměnné x a obě jsou v rozsahu. Která z nich bude používána? Odpověď je jasná. Bude to x deklarované v cyklu, protože má nejbezprostřednější rozsah.
    Nakonec se budeme zabývat deklarací x, která je umístěna před funkcí main. Protože je deklarována mimo funkci, je to globální proměnná a má globální rozsah. Globální proměnná x je dostupná kdekoliv v programu: uvnitř funkce main, uvnitř bloku while i uvnitř funkce citacCyklu.
    Jak je uvedeno výše, lokální proměnné mají přednost před globálními proměnnými. Jak ale lze přistoupit ke globální proměnné uvnitř funkce main? Použijeme operátor rozsahu ::. V našem programu se vyskytuje řádek:
    cout << "Globální x = " << ::x << endl;
    Operátor rozsahu :: říká překladači: "Použij globální proměnnou x a ne lokální proměnou x".
    Podívejte se ještě na následující příklad:
    for (int i = 0; i < 10; i++) {
      if (pole[i] == 40) break;
    }
    index = i;        // chyba
    Tento kód generuje chybu, protože proměnná i je viditelná pouze v bloku cyklu for. Proměnnou i v tomto případě je  nutno deklarovat před cyklem. Následující řešení je již správné:
    int i;
    for (i = 0; i < 10; i++) {
      if (pole[i] == 40) break;
    }
    index = i;
  9. Reálné aplikace se obvykle skládají z několika souborů zdrojového kódu. Globální proměnné deklarované v jednom zdrojovém souboru jsou globální v tomto souboru, ale nejsou viditelné z ostatních zdrojových souborů. Namísto pojmu globální proměnná by bylo lépe používat termín proměnná s rozsahem souboru. Jsou ale případy, kdy potřebujeme některé proměnné vidět i z ostatních zdrojových souborů programu. Vytvoření těchto "skutečných globálních proměnných" je dvoukrokový proces. Nejprve deklarujeme proměnnou v jednom zdrojovém souboru jako proměnnou s rozsahem souboru. Potom v ostatních zdrojových souborech, ve kterých budeme potřebovat přistupovat k této proměnné, deklarujeme tuto proměnnou znova, ale tuto deklaraci musí předcházet klíčové slovo extern. Např.

  10. extern int x;
    Klíčové slovo extern říká překladači: "Tento zdrojový soubor bude používat proměnnou, jejíž deklarace bude nalezena v jiném zdrojovém souboru". Jak poznáme později (v souvislosti s objektově orientovaným programováním) je vhodné používání globálních proměnných omezit na minimum.

Hlavní pravidla pro funkce:


 
12. Funkce II