$$ \newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} \newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} \newcommand{\mod}{\,\mathrm{mod}\,} \renewcommand{\div}{\,\mathrm{div}\,} \newcommand{\metar}{\,\mathrm{m}} \newcommand{\cm}{\,\mathrm{cm}} \newcommand{\dm}{\,\mathrm{dm}} \newcommand{\litar}{\,\mathrm{l}} \newcommand{\km}{\,\mathrm{km}} \newcommand{\s}{\,\mathrm{s}} \newcommand{\h}{\,\mathrm{h}} \newcommand{\minut}{\,\mathrm{min}} \newcommand{\kmh}{\,\mathrm{\frac{km}{h}}} \newcommand{\ms}{\,\mathrm{\frac{m}{s}}} \newcommand{\mmin}{\,\mathrm{\frac{m}{min}}} \newcommand{\smin}{\,\mathrm{\frac{s}{min}}} $$

Funkcije

  • Dozvoljeno polaganje
  • Lekcije
  • Nema
  • Teo
  • 7/25/2015

Do sada smo koristili "gotove" funkcije iz standardnih biblioteka. Sve ove funkcije smo pozivali iz glavne funkcije našeg programa - main() funkcije, koja predstavlja specijalnu funkciju jer izvršavanje programa počinje od nje i sve programe bez obzira na njihovu dužinu smo pisali u toj jednoj (main) funkciji.

Hajde da ponovo pogledamo primer iz lekcije "Unos podataka":

using namespace std;

#include <iostream>

 

void main()

{

int zbir = 0;

float prosek;

const int brPredmeta = 11;

int ocena;

 

cout << "Sta imas iz srpskog?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz matematike?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz fizickog?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz engleskog?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz fizike?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz hemije?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz ruskog?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz muzickog?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz likovnog?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz kung-fu-a?\n";

cin >> ocena;

zbir += ocena;

 

cout << "Sta imas iz kibernetike?\n";

cin >> ocena;

zbir += ocena;

 

prosek = (float) zbir / brPredmeta;

 

cout << "Tvoj prosek je:"

 << prosek;

}

 

Kao što vidimo dobili smo prilično dugačak program u kome ima dosta ponavljanja sličnih ili istih operacija i blokova naredbi. Kako možemo da poboljšamo ovaj program i napišemo ga na kraći i jednostavniji način? Tu nam pomažu funkcije i na primeru ispod je pokazano kako se piše jedna jednostavna funkcija. Ova funkcija nas podseća na main funkciju iz naših prethodnih programa.

using namespace std;

#include <iostream>

#include <string>

 

int StaImasIz(std::string imePredmeta)

{

int ocena;

cout << "Sta imas iz " << imePredmeta << "?\n";

 

cin >> ocena;

 

return ocena;

}

 

void main()

{

int zbir = 0;

float prosek;

const int brPredmeta = 11;

 

zbir += StaImasIz("srpskog");

zbir += StaImasIz("matematike");

zbir += StaImasIz("fizickog");

zbir += StaImasIz("engleskog");

zbir += StaImasIz("fizike");

zbir += StaImasIz("hemije");

zbir += StaImasIz("ruskog");

zbir += StaImasIz("muzickog");

zbir += StaImasIz("likovnog");

zbir += StaImasIz("kung-fu-a");

zbir += StaImasIz("kibernetike");

 

prosek = (float) zbir / brPredmeta;

 

cout << "Tvoj prosek je:"

 << prosek;

}

 

Kao što vidite dobili smo značajno kraći i pregledniji program u kome smo deo programa stavili u odvojenu funkciju StaImasIz(). Inače telo funkcije moze biti veoma složeno za razliku od ovog primera. Posle kreiranja funkcije možemo je iz ostalog dela programa pozivati po imenu a funkcije mogu da pozivaju i jedne druge, čak funkcija može da poziva samu sebe (to se koristi u rekurzivnim algoritmima). Za sad nemojte pozivati funkciju iz same sebe ;)

Većina komandi programskog jezika C++ predstavljaju funkcije. Na primer “sqrt” je funkcija koja izračunava kvadratni koren prosleđenog joj broja. Ove funkcije su definisane u fajlovima C++ biblioteke koji su uključeni u C++ prevodilac (eng. compiler). Kada koristimo C++ funkciju, kompajler dodaje njeno telo vašem programu i kreira krajnji izvršni program (EXE). 

Da sumiramo sve razloge za upotrebu funkcija:

• Kada imamo više ponavljanja istih blokova naredbi (operacija) u različitim delovima programa (time skraćujemo tekst programa)

• Upotrebom funkcija, program se deli na odvojene blokove. Svaki blok radi određeni posao. Ovako olakšavamo čitljivost/razumevanje programa. Osmišljavanje, razumevanje i održavanje manjih blokova koda je lakše.

• Kada se deo programa moze izvršiti sa različitim parametrima. Ovi parametri se prosleđuju funkciji kao argumenti funkcije.

Definisanje funkcije

Funkcija se definše na sledeći način:

tip_rezultata ime_funkcije(opis argumenata funkcije)

{

/*telo funkcije*/

}

ili prikazano na sledećem dijagramu:


 

tip_rezultata je neki od već poznatih tipova podataka i on označava kakav je rezultat koji funkcija vraća. Često se kaže i "tip funkcije", a tada se misli upravo na tip njenog rezultata.

ime_funkcije je identifikator funkcije

Opis argumenata funkcije je lista argumenata funkcije koja sadrži tipove argumenata i identifikatore argumenata. Npr. funkcija Izracunaj(int a, char ch, float x) u listi su upisana tri argumenta i to: a, ch i x čiji su tipovi podataka navedeni ispred.

Telo funkcije je niz naredbi koje počinju sa deklaracijama promenljivih kao u programu tj. funkciji main(). U telu funkcije naredba za vraćanje rezultata koji funkcija daje je: return rezultat;

Svaka funkcija se sastoji od skupa naredbi koje određuju šta i kako funkcija radi. Taj skup naredbi čini telo funkcije. Telo funkcije započinje nakon otvorene vitičaste zagrade ({), a završava zatvorenom vitičastom zagradom (}).

Poziv funkcije

Funkcija se izvršava tako što se „poziva“ u (glavnom) programu ili drugoj funkciji. Funkcija se poziva navođenjem njenog naziva i argumenata zapisanih u redosledu koji je zadan deklaracijom, kao u primeru StaImasIz("kung-fu-a") gde učenika pitamo koju ocenu ima iz Kung-Fu-a.

Povratna vrednost funkcije

U programskom jeziku C++ očekujemo da funkcija vrati neku vrednost. Ova povratna vrednost ima svoj tip kao i ostale vrednosti u C++, pa može biti tipa integer, float, char ili bilo šta drugo. Vrednost funkcije vraćamo sa komandom return.

float Kvadriraj(float x)

{

    float rezultat;

    rezultat = x * x;

    return rezultat;

}

Funkcija iz gornjeg primera vraća vrednost promenljive “rezultat” kao povratnu vrednost funkcije. Takođe, možemo koristiti i izraz u return komandi. Na primer možemo zameniti poslednje dve linije funkcije sa ‘return (x * x);’ Ako zaboravite povratnu vrednost u nekoj funkciji dobićete poruku upozorenja (eng. warning)  od C++  kompajlera da funkcija mora da vrati vrednost. Upozorenja kompajlera ne zaustavljaju izvršavanje programa ali greške zaustavljaju. Ipak, dobra je praksa obraćati pažnju i na ova upozorenja i popraviti kod tako da se prevodi bez upozorenja.

Funkcije koje ne vraćaju vrednost

Prema pravilima pisanja programa na jezicima C i C++, svaka funkcija ima tip. Ako nam nije potrebno da funkcija na mesto poziva vrati vrednost, deklarišemo (objavljujemo) da je tip funkcije, to jest njene povratne vrednosti, tip void (srpski: nevažeći, prazan):

 

void test ()

{

/* kod funkcije ali bez povratne vrednosti */

}

Tip void se ne može koristiti nizašta, njegovom upotrebom u deklaraciji samo saopštavamo da vrednost nećemo koristiti. Zato se pozivi funkcija tipa void pišu u programu kao naredbe, a ne kao izrazi.

Funkcija tipa void može (i ne mora) da sadrži naredbu return, a ako je sadrži, onda bez ikakvog izraza.

Evo kako to izgleda na primeru:

void ispisUpozorenja()

{

cout << "Upozorenje!";

}

Poziv ove funkcije sa nekog drugog mesta u programu bi izgledao ovako:

ispisUpozorenja();

 

Deklaracija funkcije

Svaka funkcija se pre upotrebe u programu najavljuje (deklariše), kao što se deklarišu promenljive. Ako pri čitanju programa u trenutku kad naiđemo na upotrebu nekog imena, do tada nije već najavljeno to ime i način njegove upotrebe, naš program ne može da se pripremi za izvršenje jer mu to ime nije poznato i u tom trenutku mu nije jasno šta treba da se radi. U najavi je dovoljno navesti samo tipove podataka koje funkcija koristi kao argumente ili vraća kao rezultat.

Ajde sad da pogledamo koji je redosled deklaracija funkcije ispravan kroz primere:

 

  • Ovo je ispravno

 

int StaImasIz(string imePredmeta)

{

}

 

void main()

{

zbir += StaImasIz("mađioničarskih trikova");

}

 

  • I ovo je ispravno

 

int StaImasIz(string imePredmeta);

 

void main()

{

zbir += StaImasIz("mađioničarskih trikova");

}

 

int StaImasIz(string imePredmeta)

{

zbir += StaImasIz("mađioničarskih trikova");

}

 

ali ovo nije ispravno

 

void main()

{

zbir += StaImasIz("mađioničarskih trikova");

}

 

int StaImasIz(string imePredmeta)

{

}

 

Jer kad naiđemo na StaImasIz, ne znamo da li je to ime funkcije ili nešto drugo.

 

Argumenti funkcije

Funkcije mogu da prihvataju ulazne parametre u formi promenljivih  i izraza i ove ulazne promenljive se mogu koristiti u telu funkcije.

Do sad su parametri služili da prenesu vrednost sa mesta poziva u funkciju i to su ulazni parametri, a moguće je preneti i vrednost iz funkcije (tako da parametri budu izlazni), ali o tome u sledećoj lekciji.