Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.

13. diel - Funkcie v jazyku C ++

V predchádzajúcom kvíze, Kvíz - textové reťazce v C++, sme si overili nadobudnuté skúsenosti z predchádzajúcich lekcií.

V minulej lekcii, Kvíz - textové reťazce v C++ , sme si predstavili matematickú knižnicu cmath. Dnešné tutoriál o programovacom jazyku C ++ je venovaný veľmi dôležitej téme, ktorým je využívanie funkcií. My sme už zoznámenie s tým, že kód programu píšeme do funkcie main(). To pre naše učebné programy, ktoré vedeli vykonávať len jednu jednoduchú vec, zatiaľ stačilo. Predstavte si však, že píšete program, ktorý je dlhý niekoľko sto tisíc riadkov. Určite uznáte, že v takej rezance kóde v jednom súbore a v jednej funkcii by sa orientovalo veľmi zle. Navyše, ak by sme chceli vykonať nejakú rovnakú postupnosť príkazov na viacerých miestach, museli by sme ju buď stále opisovať alebo v kóde skákať z miesta na miesto. Obe dve možnosti sú opäť veľmi neprehľadné.

Funkcionálne dekompozícia

O rozdelení aplikácie do funkcií sa niekedy hovorí ako o tzv. Funkcionálne dekompozícii. Neľakajte sa termíne, jednoducho si rozmyslíme, čo má naša aplikácia vedieť, a pre rôzne užívateľské funkcie zvyčajne vytvoríme jednotlivé funkcie v zdrojovom kóde. V praxi sa nám bude často stávať, že si budeme tvoriť okrem týchto funkcií ešte nejaké pomocné, napr. Môžeme mať funkciu pre výpis menu aplikácie alebo rozdelíme nejaký zložitý výpočet do viacerých menších funkcií kvôli prehľadnosti.

Funkciám sa niekedy hovorí podprogramy alebo subrutiny. Ak funkcia nevracia žiadnu hodnotu (viď ďalej), môže sa ju v niektorých jazykoch hovoriť procedúra. U väčších aplikácií, ktoré majú mnoho funkcií, sa funkcia združujú do tzv. Modulov. Tie vy dobre poznáte napr. V podobe #include <iostream>, ktorým načítame knižnicu (modul) pre prácu so štandardným vstupom a výstupom (teda pre nás s konzolou). Podobne sú matematické funkcie sústredené v systémovom module cmath. Tieto moduly alebo ak knižnice sa tiež naučíme vytvárať.

Tvorba funkcií

Funkcia je logický blok kódu, ktorý raz napíšeme a potom ho môžeme ľubovoľne volať bez toho, aby sme ho písali znovu a opakovali sa. Funkciu deklarujeme v globálnom priestore, niekde nad funkciou main(). Bude vyzerať podobne. Pridajme do nášho zdrojového kódu funkciu, ktorá do konzoly vypíše " Ahoj, vrelo ťa tu vítam! ". Pre názornosť si prvýkrát uveďme kompletný zdrojový kód programu:

#include <iostream>
using namespace std;

void pozdrav()
{
    cout << "Ahoj, vrele te tú vitam!" << endl;
}

int main()
{
    return 0;
}

Kľúčové slovo void v definícii funkcie označuje, že funkcia nevracia žiadnu hodnotu. Funkciu teraz musíme zavolať, aby sa spustila. Musíme to samozrejme urobiť až po tom, čo ju deklarujeme, inak by ju kompilátor nepoznal (preto sme ju písali nad funkciu main()). Do main() napíšeme tento riadok:

Klikni pre editáciu
  • pozdrav(); // zavolanie funkcie
    
    • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

    Do konzoly by sa v tejto chvíli malo vypísať Ahoj, vrele te tú vitam.

    Funkcie s parametrami

    Funkcia môže mať tiež ľubovoľný počet vstupných parametrov (niekedy sa im hovorí argumenty), ktoré píšeme do zátvorky v jej definícii. Parametre ovplyvňujeme správanie funkcie. Majte situácii, keď chceme pozdraviť nášho používateľa podľa mena. Rozšírime teda existujúce funkciu o parameter jmeno a ten potom pridáme s konkrétnou hodnotou do volanie funkcie:

    void pozdrav(string jmeno)
    {
        cout << "Ahoj, vrele te tú vitam " << jmeno << endl;
    }

    Funkciu v main() následne zavoláme takto:

    Klikni pre editáciu
    • pozdrav("Karle"); // zavolanie funkcie
      
      • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

      Keby sme teraz chceli pozdraviť niekoľko ľudí, nemusíme otrocky písať znovu a znovu cout << "Ahoj, vrele..., stačí nám len viackrát zavolať našej funkcii:

      Klikni pre editáciu
      • pozdrav("Karle");
        pozdrav("Davide");
        pozdrav("Marenko");
        
        • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

        výsledok:

        Konzolová aplikácia
        Ahoj, vrele te tú vitam Karle
        Ahoj, vrele te tú vitam Davide
        Ahoj, vrele te tú vitam Marenko

        Návratová hodnota funkcie

        Funkcia môže ďalej vracať nejakú hodnotu. Opusťme náš príklad s pozdravom a vytvorme tentoraz funkciu, ktorá nám spočíta obsah obdĺžnika. Tento obsah však nebudeme chcieť len vypísať, ale budeme ho chcieť použiť v ďalších výpočtoch. Preto výsledok funkcie nevypíše, ale vrátime ako návratovú hodnotu. Funkcia môže vracať práve jednu hodnotu pomocou príkazu return. Return okrem navrátenie hodnoty funkciu tiež okamžite ukončí, ďalšie prípadné príkazy po ňom sa už nevykonajú. Dátový typ návratovej hodnoty musíme uviesť pred definíciu funkcie. Pridajte si do programu nasledujúcej funkcii:

        int obsah_obdelniku(int sirka, int vyska)
        {
            int vysledek = sirka * vyska;
            return vysledek;
        }

        V praxi by naše funkcie samozrejme počítala niečo zložitejšieho, aby sa nám ju vyplatilo vôbec programovať. V príklade ale obdĺžnik poslúži dobre. Funkcia pomenovávame malými písmenami, celými slovami a miesto medzier používame podčiarknutia. Hoci C ++ samotné je plné skrátené, vy sa im vyhnite. Je totiž oveľa čitateľnejšie funkcie datum_narozeni() ako datnar(), u ktorej nemusia byť na prvý pohľad zrejmé čo že to vôbec robí.

        Ak by sme teraz chceli vypísať obsah nejakého obdĺžnika, jednoducho vložíme volanie funkcie do volania cout. Ako prvý sa spočíta obsah obdĺžnika, funkcia túto hodnotu vráti a hodnota príde ako vstupný parameter objektu cout, ktorý ju vypíše. Ako šírku a výšku zadajte napr. 10 a 20 cm:

        Klikni pre editáciu
        • cout << "Obsah obdĺžnikov je: " << obsah_obdelniku(10, 20) << " cm^2" << endl;
          
          • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

          Konzolová aplikácia
          Obsah obdĺžnikov je 200 cm^2

          Pokiaľ vám to príde zmätené, vždy môžete použiť ešte pomocnú premennú:

          Klikni pre editáciu
          • int obsah = obsah_obdelniku(10, 20);
            cout << "Obsah obdĺžnikov je: " << obsah << " cm^2" << endl;
            
            • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

            Návratovú hodnotu funkcie sme však nepoužili kvôli tomu, aby sme ju len vypisovali. Využime teraz toho, že je výpis na nás, a výpisy súčet obsahov dvoch obdĺžnikov:

            Klikni pre editáciu
            • int celkovy_obsah = obsah_obdelniku(10, 20) + obsah_obdelniku(20, 40);
              cout << "Sucet obsahu obdĺžnika je: " << celkovy_obsah << " cm^2" << endl;
              
              • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

              výsledok:

              Konzolová aplikácia
              Sucet obsahu obdĺžnikov je: 1000 cm^2

              Spomeňme si na minulé príklady, ktoré sme počas nášho seriálu vytvorili. Môžete si ich skúsiť prepísať tak, aby ste volali funkciu. V rámci návrhu by všetok kód mal byť rozdelený do funkcií (a ideálne do modulov, viď. Ďalší lekcie) a to najmä kvôli prehľadnosti. My sme to zo začiatku kvôli jednoduchosť zanedbali, teraz to prosím berte na vedomie :)

              Výhoda funkciou je teda v prehľadnosti a úspornosti (môžeme napísať nejakú vec raz a volať ju treba stokrát na rôznych miestach programu). Keď sa rozhodneme funkciu zmeniť, vykonáme zmenu len na jednom mieste a táto zmena sa prejaví všade, čo značne znižuje riziko chýb. V príklade, kde zdravíme Karla, Davida a Marienku, nám stačí zmeniť text pozdravu vo funkcii a zmení sa vo všetkých troch volaniach. Nemať kód vo funkcii, museli by sme prepisovať 3 vety a v nejakej by sme mohli urobiť chybu.

              Rekurzia

              Na koniec si urobme ešte odbočku k pokročilejšiemu téme, ktorým je rekurzia. Rekurzívne funkcie je taká funkcia, ktorá v tele volá sama seba. Takáto funkcia potrebuje nejakú informáciu, podľa ktorej spozná, kedy má skončiť (tzv. Ukončenie rekurzia), inak by zavolala seba, tá zas seba a tak až do pádu programu na nedostatok pamäti. Rekurzia sa často používa v algoritmizácia.

              Vo funkcionálnych jazykoch sa rekurzia používa namiesto cyklov. Zoberme si napríklad cyklus for, ktorý je súčtom čísla od 1 do 10. Rovnaký výsledok môžeme docieliť aj rekurzia, funkcie sa buď zavolá znovu s číslom o 1 vyšším alebo sa ukončí.

              int cyklus(int aktualni_index, int konecny_index, int suma)
              {
                  if (aktualni_index == konecny_index)
                      return suma;
                  return cyklus(aktualni_index + 1, konecny_index, suma + aktualni_index);
              }

              Funkciu by sme zavolali takto:

              Klikni pre editáciu
              • cout << cyklus(0,10,0) << endl; // začiatok rekurzia
                
                • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

                To isté môžeme zapísať pomocou cyklu for:

                Klikni pre editáciu
                • // ekvivalentné zápis s for
                  int suma = 0;
                  for (int a = 0; a < 10; a++)
                      suma += a;
                  cout << suma;
                  
                  • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

                  Ako môžete vidieť, čítanie rekurzia nie je tak jednoduché, ako je tomu u cykle for. Aby toho nebolo málo, použitie rekurzia sebou nesie dodatočnú záťaž, pretože sa musí opakovane odovzdávať parametre (viac v článku o kompiláciu). Všeobecne možno veľkú časť programov, ktoré používajú rekurziu, prepísať do podoby bez rekurzia. Pre príklad si napíšeme program, ktorý počíta faktoriál. Predvedieme si verziu s rekurzia a verziu bez rekurzia.

                  int faktorial(int x)
                  {
                          if (x == 1)
                                  return 1;
                          return x * faktorial(x - 1);
                  }

                  A funkciu by sme zavolali takto:

                  Klikni pre editáciu
                  • cout << faktorial(10) << endl;
                    
                    • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

                    A alternatíva pomocou cyklu:

                    Klikni pre editáciu
                    • int vysledek = 1;
                      int x = 10;
                      for (int i = 2; i <= x; i++)
                              vysledek *= i;
                      cout << vysledek << endl;
                      
                      • Skontroluj, či výstupy programu zodpovedajú predlohe. S inými textami testy neprejdú.

                      S rekurzia sa môžete často stretnúť v už existujúcich programoch alebo na pohovoroch do práce. Avšak odporúčam rekurziu z dôvodov výkonnostných skôr nepoužívať. Rekurzia dokáže veľmi rýchlo zaplniť zásobník a ukončiť celý program. Naviac je zložitá na chápania, ak vás zmiatla, ešte sa s ňou stretnete minimálne u algoritmov, kde bude dostatok priestoru pre ďalšie pochopenie.

                      V budúcej lekcii, Riešené úlohy k 13. lekcii C ++ , už trochu nazrieme do OOP. Pozrieme sa na štruktúry, ktoré sú takým medzikrokom medzi procedurálnym programovaním a OOP.

                      V nasledujúcom cvičení, Riešené úlohy k 13. lekcii C ++, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


                       

                      Ako sa ti páči článok?
                      Pred uložením hodnotenia, popíš prosím autorovi, čo je zleZnakov 0 z 50-500
                      Predchádzajúci článok
                      Kvíz - textové reťazce v C++
                      Všetky články v sekcii
                      Základné konštrukcie jazyka C ++
                      Preskočiť článok
                      (neodporúčame)
                      Riešené úlohy k 13. lekcii C ++
                      Článok pre vás napísal Patrik Valkovič
                      Avatar
                      Užívateľské hodnotenie:
                      Ešte nikto nehodnotil, buď prvý!
                      Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
                      Aktivity