You are on page 1of 34

Programske petlje

Često se u procesu programiranja pojavljuje potreba za ponavljanjem dijelova programa.


Na primjer, postoji li potreba za unošenjem niza od 10 brojeva, naredbu za učitavanje treba
pisati deset puta. Ako tada s tim brojevima treba napraviti niz operacija, program postaje
nepregledan i nepotrebno dugačak. Puno je praktičnije naredbu učitavanja i blokove
naredbi koje treba s tim brojevima ponoviti napisati jednom, a pri izvršavanju programa
pozvati željeni broj puta.

Za ponavljanje dijelova programa upotrebljavaju se naredbe ponavljanja ili programske


petlje!

One su sastavni dio svakog programskog jezika, a ovisno o mjestu ispitivanja uvjeta mogu
se podijeliti na:
programske petlje s ispitivanjem uvjeta na početku i
petlje kod kojih se uvjet ponavljanja nalazi na kraju niza naredbi koje se ponavljaju.

Uzmu li se u obzir prethodni kriteriji, u programskom jeziku C razlikuju se:


programske petlje for i while kod kojih se uvjet ponavljanja nalazi na početku niza naredbi i
do-while programska petlja, kod koje se uvjet ponavljanja nalazi na kraju niza naredbi.

Zbog svega navedenog može se uočiti slijedeće:

Niz naredbi unutar programskih petlji for i while ne mora se izvršiti niti jednom, dok će niz
naredbi unutar do-while naredbe sigurno izvršiti barem jednom.
Programska petlja for
Naredba for najčešće se primjenjuje u zadacima u kojima je broj ponavljanja unaprijed
poznat. To je najopćenitija vrsta petlje i najčešće se koristi, a ima slijedeći oblik:

for (inicijalizacija; uvjet; promjena_vrijednosti)


{
blok naredbi;
}

gdje:
inicijalizacija znači postavljanje kontrolne varijable (i/ili dodatnih varijabli) na početnu
vrijednost,
uvjet je uvjet koji kontrolna varijabla mora zadovoljiti da bi se izvršile naredbe u petlji (blok
naredbi), a
promjena_vrijednosti je dio u kojem se definira način promjene stanja kontrolne varijable.

Kontrolna varijabla kontrolira broj prolazaka petljom, a deklarira se kao i sve ostale
varijable koje se koriste u programu. Njezina se vrijednost automatski mijenja svakim
prolaskom kroz petlju kako je to definirano promjenom_vrijednosti. U ostalim programskim
jezicima kontrolna varijabla mora biti rednog tipa (obično cijeli broj) no u C-u ona može biti i
realan broj!

Dijelovi programske petlje for mogu se i izostaviti, ali da bi se zadovoljila sintaksa C-a
obavezno je napisati nul naredbu ;

Tijek izvršavanja for petlje je slijedeći:


Ako je prisutna inicijalizacija, kontrolna varijabla (i/ili dodatne varijable) se postavljaju na
početnu vrijednost (ako je to izraz, izračuna se njegova vrijednost, a nakon toga se ta
vrijednost pridruži kontrolnoj varijabli).
Ako je prisutan uvjet provjerava se njegova istinitost. Izračunata vrijednost je logičkog tipa
(istina ili laž). Ako je rezultat istina, izvodi se blok naredbi.
Ako je prisutna promjena_vrijednosti promjeni se vrijednost kontrolne varijable. Program se
vraća na početak petlje, te se ona ponavlja od točke 2.

1
Ako je vrijednost uvjeta neistina, blok naredbi se preskače i program se nastavlja prvom
naredbom iza bloka.

2
Dijagram tijeka for petlje :

Inicijalizacija / promjena
vrijednosti kontrolne varijable

NE

uvjet

DA

blok naredbi

Primjer 1: Petljom:

for (i=1;i<=10;i++)
printf("\n Danas je ponedjeljak.");

će se na zaslon 10 puta ispisati rečenica «Danas je ponedjeljak.», svaki put u novi red
/*zbog konstante \n ispred početka rečenice*/.

Zašto?
Varijabla i je kontrolna varijabla, čija se vrijednost najprije postavlja na 1. Nakon toga se
provjeri uvjet (i<=10). Obzirom da je zadani uvjet istinit (jer 1 je manji od 10), na zaslon se
ispiše zadana rečenica. Zatim se, zbog promjene vrijednosti kontrolne varijable (i++), ta
vrijednost poveća za 1 (postavi na 2) i izvođenje se vraća na početak. Naredba će se
zadnji put izvršiti kada se vrijednost kontrolne varijable postavi na 10. Nakon što se
vrijednost kontrolne varijable postavi na 11, uvjet neće biti ispunjen i program kreće s
izvršavanjem prve naredbe iza naredbe for.
Vitičaste zagrade za oznaku početka i kraja bloka nisu potrebne, jer se ponavlja samo jedna
naredba. One se koriste samo u slučajevima kada se treba ponavljati više naredbi (blok
naredbi).

Ako program od zahtjeva blok naredbi za ponavljanje, a oznake početka i kraja bloka ({ i })
se izostave program će dati pogrešan rezultat. U tom slučaju, C ponavlja samo prvu
naredbu iza for. Preostale naredbe iz bloka izvršavaju se izvan naredbe ponavljanja!

Primjer 2: Petljom

for(i=100;i<=110;i++)
printf("%d ",i);

će se na zaslon ispisati brojevi 100, 101, 102, 103, 104, 105, 106, 107, 108, 109 i 110, a
petljom

for(i=100;i<=110;i+=2)
printf("%d ",i);

brojevi 100, 102, 104, 106, 108 i 110.

3
Zadatak
U programu koji slijedi napravljene su tri pogreške. Pronađite ih bez korištenja računala!

#include <stdio.h>
int br;
float i,a,s,ars;
void main()
{
printf("\n Koliko imate ucenika? ");
scanf("%d",&br);
for(i=1,i<=br,i++);
{
printf("\n Upisite ocjenu %d. ucenika: ",i);
scanf("%f",&a);
if ((a<1)||(a>5))
i--;
else
s+=a;
}
ars=s/br;
printf("\n Srednja ocjena razreda je %.2f",ars);
}

Rješenje:
unutar for petlje, početna vrijednost i uvjet ponavljanja odvajaju se znakom ;
uvjet ponavljanja i promjena vrijednosti kontrolne varijable odvajaju se znakom ;
iza for naredbe ne smije se pisati ; jer se blok koji slijedi neće ponavljati u petlji

Ugnježđivanje petlje for

Petlje for mogu se i ugnježđivati, što znači pisati jedna unutar druge:

for (inicijalizacija1; uvjet1; promjena_vrijednosti1)


for(inicijalizacija2; uvjet2; promjena_vrijednosti2)
{
blok naredbi;
}

U tom slučaju, kada se jednom promjeni vrijednost kontrolne varijable vanjske petlje,
potpuno se izvrši unutarnja petlja (vrijednosti njezine kontrolne varijable promjene se od
početne do završne). Tek tada se ponovo promjeni vrijednost kontrolne varijable vanjske
petlje. Ako se vanjska petlja izvršava n puta, a unutarnja m, ugniježđene petlje izvršit će se
n*m puta

Primjer: Tijekom izvođenja niza naredbi:

int i,j;
for(i=0;i<=6;i+=5)
for(j=1;i<=7;j+=3)
printf("\ni + j = %d",i, j);

vrijednosti varijabli i i j mijenjaju se na slijedeći način:

Za i = 0 varijabla j poprima vrijednosti: 1, 4 i 7, te se na zaslon ispisuju vrijednosti:


0, 1
0, 4

4
0, 7

Tada unutarnja petlja (po j) staje, jer je uvjet lažan. Povećava se vrijednost kontrolne
varijable i (i= 5), pa se ponovo izvršava unutarnja petlja i poprima vrijednosti: 1, 4 i 7.
Ispis na zaslon:
1, 1
1, 4
1, 7

Slijedeće povećanje kontrolne varijable i je na 10 pa uvjet nije istinit što znači da prestaje
izvršavanje petlji.

Zadatak:
Napraviti program koji će na zaslon ispisati sve Pitagorine brojeve u intervalu od 2 do 50.
Osim tog podatka program treba ispisati i koliko Pitagorinih brojeva ima u danom intervalu.
/* Pitagorini brojevi su uređene trojke brojeva (a, b, c) za koje vrijedi da je a2 + b2 = c2) */

Rješenje:
#include <stdio.h>
#include <math.h>
void main (void)
{
int a,b,c,koliko=0;
for(a=2;a<=50;a++)
for(b=a;b<=50;b++)
for(c=b;c<=50;c++)
if (pow(a,2)+pow(b,2)==pow(c,2))
{
printf("\n %d, %d, %d", a,b,c);
koliko++;
}
printf("\n Ima ih %d", koliko);
}

Zadaci za vježbu:
1. Bez utipkavanja programa odgovorite na pitanje: Kada se slijedeći program izvrši, što će
se ispisati na zaslonu?

#include <stdio.h>
int i;
void main()
{
for(i=20;i<=30;i+=3)
printf("%d ",i);
}

2. Bez utipkavanja programa napišite što će se ispisati na zaslonu monitora nakon


izvršavanja slijedećih programa:

a) }
#include <stdio.h>
void main ()
{
int n=5,i;
long int f=1;
for (i=2;i<=n;i++) f=f*i;
printf(" %d!=%d",n,f);

5
b) int a=2, x=3,y=1,i;
#include <stdio.h> for (i=1;i<=x;i++) y=a*y;
void main () printf(" rezultat je %d",y);
{ }

3. Bez korištenja računala pronađite pogreške u slijedećem programu:

#include <stdio.h>
int i=1,br;
float a,s,ars;
void main()
{
printf("\n Koliko imate ucenika? ");
scanf("%d",&br);
for(i<=br)
{
printf("\n Upisite ocjenu %d. ucenika: ",i);
scanf("%f",&a);
if ((a<1)||(a>5)) i--;
else
{
s+=a;
i++;
}
}
ars=s/br;
printf("\n Srednja ocjena razreda je %.2f",ars);
}

Kada napravite ispravan program odgovorite na pitanje: Kako glasi tekst zadatka kojim bi se
zadao prethodni program?

4. Može li se program napisati i ovako?

#include <stdio.h>
void main()
{
int i=1;
for(;i<=7;i++)
printf("%d \n",i);
}

5. Što će se ispisati na zaslonu nakon izvršavanja slijedećeg bloka naredbi?

int i,j;
for(i=5,j=0;i<=10;i+=2,j++)
{
printf("\ni = %d j = %d",i,j);
}

6. Napravite program koji će na zaslon ispisati prvih 20 prirodnih brojeva, ali u obrnutom
redoslijedu (od 20 do 1)

7. Napraviti program koji će zbrojiti sve cijele brojeve između 500 i 600 koji su djeljivi sa 11.
Uz rezultat zbroja, program treba na zaslon ispisati i koliko ima takvih brojeva.

6
8. Napraviti program koji će tražiti unošenje prirodnog broja n (n<10) Program treba
izračunati i ispisati na zaslon n! ( n! 1  2  3    n )

9. Napraviti program koji će za unesene cijele brojeve a i x izračunati i ispisati ax.


Za one koji žele više…
1. Napraviti program koji će, koristeći for petlju, izračunati i ispisati rezultat zbroja:
s  1  2 2  33    n n .
Test primjeri:

3 5

32 3413

2. Napraviti program koji će tražiti unošenje prirodnog broja n i realnog broja x. Program
treba izračunati i ispisati na zaslon rezultat zbroja
x3 x5 x7 x 2 n 1
S  x    
3! 5! 7! (2n  1)!
Test primjeri:
5 10
1 1.57

0.89 1.16

3. Napravite program koji će od korisnika tražiti unošenje dva cijela broja. Program treba
pomnožiti zadane brojeve koristeći samo operaciju zbrajanja.

Testni primjeri:

3, 2 30, 50

6 600

Programska petlja while


Petlja while je petlja kod koje se zadani uvjet nalazi na početku. Njezin opći oblik je:

while (uvjet izvođenja)


{
blok naredbi;
}

a znači slijedeće:

dok je (uvjet ispunjen)


{
ponavljaj naredbe unutar bloka
}

Uvjet je aritmetički ili logički izraz. Blok naredbi u petlji se ponavlja sve dok je uvjet istinit
ili različit od 0. Kad uvjet postane lažan ili jednak 0 program nastavlja izvođenje prvom
naredbom iza while bloka. Obzirom da se uvjet ponavljanja ispituje na početku petlje, to
znači da blok naredbi unutar petlje ne mora nužno biti izvršen niti jednom.

While naredba obično se koristi kada:


7
se ne zna točan broj ponavljanja naredbi u petlji
ne postoji kontrolna varijabla koja se mijenja ponavljanjem
na izvršavanje petlje utječu neki vanjski parametri (npr. unos s tipkovnice)

Tijek izvršavanja while bloka je slijedeći:


Izračunava se uvjet izvođenja (to je logički izraz i njegov rezultat može biti logička istina ili
logička neistina).
Ako je rezultat istinit izvodi se blok naredbi, a nakon toga se program vraća na while
naredbu i izvodi od točke 1.
Ako je rezultat neistinit, preskače se blok naredbi i program nastavlja s izvođenjem prvom
naredbom iza bloka naredbi.

Dijagram tijeka while petlje:

NE

uvjet

DA

blok naredbi

Kao i kod ostalih složenih naredbi, tako i kod while vrijedi činjenica da oznake početka i
kraja bloka ({, }) nisu neophodne ako se unutar bloka nalazi samo jedna naredba!
Prilikom postavljanja uvjeta potrebno je voditi računa o tome da on mora u jednom
trenutku postati lažan. U protivnom će program ući u beskonačnu petlju!

Primjer: Koristeći while naredbu program na zaslon ispisuje prvih 10 prirodnih brojeva.

#include <stdio.h>
void main()
{
int i=1;
while(i<=10)
{
printf("%d ",i);
i++;
}
}

/*U ovakvim situacijama prikladnija je petlja for.*/

Zadatak: U programu koji slijedi napravljene su 3 pogreške. Pronađite ih bez korištenja


računala!

#include <stdio.h>
float s;
void main()
{
int p=1,i,n;
printf("\n Upisite jedan broj: ");
scanf("%d",&n);

8
while(i=1;i<=n;i+=2)
{
s+=(float)p/i;
p=-p;
}
printf("\n suma je %.3f",s);
}

Rješenje:
Konstrukcija (i=1;i<=n;i+=2) karakteristična je za for petlju, a ne za while.
Početna vrijednost kontrolne varijable postavlja se ispred while naredbe, a
promjena njezine vrijednosti događa se unutar while bloka.

Ispravan program izgleda ovako:

#include <stdio.h>
float s;
void main()
{
int p=1,i=1,n;
printf("\n Upisite jedan broj: ");
scanf("%d",&n);
while(i<=n)
{
s+=(float)p/i;
i+=2;
p=-p;
}
printf("\n suma je %.3f",s);
}

1 1 1 1
S  1    
To je program koji za učitani broj n računa zbroj: 2 3 4 n.

Zadatak: Bez utipkavanja programa odgovorite na pitanje: Kada se slijedeći program izvrši,
što će se ispisati na zaslonu?

#include <stdio.h>
void main()
{
int i=1,s=0;
while(i<=5)
{
s+=i;
i+=2;
}
printf("\n Trazeni zbroj je %d",s);
}

Rješenje: Na zaslonu će se ispisati broj 9.

Zašto?
1. korak:
Vrijednost kontrolne varijable i je 1. Pri prvom ulasku u while petlju, provjerava se uvjet.
Obzirom da je uvjet istinit (vrijedi da je 1<5) izvršava se blok naredbi iza while naredbe.
Vrijednost varijable s uvećava se za 1 (1 je vrijednost varijable i) pa postaje 1. Nakon toga
vrijednost varijable i se uvećava za 2 i postaje 3.
9
2. korak:
Sada se program vraća na provjeravanje uvjeta. 3<5 i uvjet je zadovoljen. Vrijednost
varijable s postaje 4 (prethodna vrijednost varijable s (1) uvećana za vrijednost varijable i
(3)), a vrijednost varijable i ponovo se uvećava za 2 i postaje 5.

3. korak:
Kod ponovne provjere uvjeta, vrijednost kontrolne varijable je 5, pa je uvjet još uvijek istinit
(5=5). Izvršavanjem bloka naredbi iza while, vrijednost varijable s postaje 9 (5+4), a
vrijednost kontrolne varijable je 7 (5+2).

4. korak:
Povratkom na provjeru uvjeta, pokazuje se da uvjet više nije istinit (7>5) i izvršavanje
programa nastavlja se sa slijedećom naredbom iza while bloka. U ovom slučaju to je
naredba za ispis vrijednosti varijable s. Dakle na zaslon će se ispisati 9.

Zadaci za vježbu:
1. Bez utipkavanja programa odgovorite na pitanje: koliko puta će se izvršiti slijedeća
petlja?

int i=100,suma=0;
while(i)
{
suma+=--i;
i++;
}

2. U programima koji slijede napravljena je pogreška unutar while bloka. Pronađite


pogrešku bez korištenja računala!

a) b)
#include <stdio.h> #include <stdio.h>
void main() void main()
{ {
int s=0, n; int s=0, i=1, n, znam;
printf ("\n Upisite broj: "); printf ("\n Upisite broj: ");
scanf("%d",&n); scanf("%d",&n);
while (i=1;i<=n) while (n!=0)
{ {
s+=i; znam=n%10;
i+=3; s+=znam;
} }
printf("Zbroj je %d",s); n/=10;
} printf("Zbroj je %d",s);
}
Nakon ispravljenih pogreški odgovorite na pitanje: Kako glase tekstovi kojima bi se zadali
prethodni programi?

3. Bez utipkavanja programa odgovorite na pitanje: Kada se slijedeći program izvrši, što će
se ispisati na ekranu?

#include <stdio.h>
void main()
{
int i=1,f=1,n=6;
while(i<=n)
{

10
f*=i;i++;
}
printf("\n %d! = %d",n,f);
}

4. Napravite program koji će od korisnika tražiti upisivanje jednog prirodnog broja, Program
treba upisani broj rastaviti na proste faktore.

Test primjer:
12

12=1*2*2*3

Za one koji žele više…

1. Napraviti program koji, koristeći Euklidov algoritam za traženje najveće zajedničke mjere
dva broja, skraćuje uneseni razlomak (Unosi se posebno brojnik, a posebno nazivnik danog
razlomka).

Uputa: Euklidov algoritam radi na slijedeći način:


Veći broj podijeli se s manjim i gleda ostatak dijeljenja.
Ako je ostatak jednak nuli najveća zajednička mjera je manji broj.
Ako je ostatak različit od nule, manji broj postaje veći, ostatak pri dijeljenju postaje manji
broj, i algoritam se vraća na početak.
Postupak se ponavlja sve dok ostatak pri dijeljenju većeg broja s manjim ne postane nula.

Primjer:
veći manji
ostatak
18 12
6

12 6 ostatak pri dijeljenju 12 sa 6 je


0 nula  najveća zajednička mjera
brojeva 18 i 12 je 6

2. Među neparnim brojevima mogu se izdvojiti samo oni kojima je svaka znamenka
neparna. Nazovimo ih "potpuno neparni brojevi". Napravite program koji će za uneseni cijeli
broj ispisati je li ili nije potpuno neparan.

Testni primjeri:

1325 3793
3. Napravite program
koji Nije potpuno Potpuno je omogućuje
unošenje neparan neparan cijelih brojeva sve
dok se ne unese 0. program
treba na zaslon ispisati koliko od unesenih brojeva ima barem jednu parnu znamenku.

Testni primjer:

3, 17, 21, 87, 16, 24, 18, 37, 0

11
5

4. Napravite program koji omogućuje unošenje cijelih brojeva sve dok se ne unese 0.
program treba na zaslon ispisati koliko od unesenih brojeva ima točno jednu neparnu
znamenku.

Testni primjer:

31, 7, 121, 352, 81, 11, 13, 0

Programska petlja do-while


Programska petlja do-while je petlja kod koje se uvjet ponavljanja ispituje na kraju bloka
naredbi. Koristi se u slučajevima kada je blok naredbi unutar petlje potrebno izvršiti barem
jednom, neovisno o istinitosti danog uvjeta.

Njezin opći oblik je:

do

blok naredbi;
 while (uvjet);

a znači slijedeće:

radi
{
ponavljaj naredbe unutar bloka
}sve dok je uvjet ispunjen

12
Dijagram tijeka naredbe do-while:

blok naredbi

NE

uvjet

DA

Primjer: Nakon izvođenja programa:

#include <stdio.h>
void main()
{
int i=1;
do
{
printf("%d ",i);
i++;
}while(i<=10);
}

na zaslon će se ispisati brojevi: 1, 2, 3, 4, 5, 6, 7, 8, 9 i 10 /*odvojeni razmakom, jer u


naredbi za ispis nije drugačije definirano*/.

Stavimo li u prethodnom primjeru početnu vrijednost kontrolne varijable i na 11, program


izgleda ovako:

#include <stdio.h>
void main()
{
int i=11;
do
{
printf("%d ",i);
i++;
}while(i<=10);
}

Nakon njegovog izvođenja, na zaslon će se ispisati samo broj 11.

Zašto?
Početna vrijednost kontrolne varijable je 11 i ona ne zadovoljava dani uvjet, ali uvjet se
provjerava tek na kraju i sve naredbe koje se nalaze ispred provjere uvjeta će se izvršiti. Tek

13
kada se provjeri uvjet, program izlazi van iz petlje. Zbog toga treba biti izuzetno oprezan
prilikom korištenja petlje s provjerom uvjeta na kraju bloka naredbi.

Zadatak 1:
Koje od slijedećih do-while oblika nisu ispravni i zašto?
a) c)
i=1 i=1;
do (i<=10) do
{ {
printf("%d ",i); printf("%d ",i);
i++; } while(i<=10);
}while;
d)
b) i=1;
i=1 do
while {
{ printf("%d ",i);
printf("%d ",i); i+=2;
i++;
}do(i<=10); } while(i<=10);

Rješenje:
Oblik a) nije ispravan jer se uvjet ponavljanja u do-while petlji treba nalaziti na kraju
bloka naredbi koje se ponavljaju.
Oblik b) nije ispravan jer ključna riječ do mora biti na početku, a while na kraju bloka
naredbi
Oblik c) ima ispravnu sintaksu, ali ima logičku pogrešku. Kontrolna varijabla i nigdje ne
mijenja svoju vrijednost, cijelo vrijeme ostaje 1. Program će ući u beskonačnu petlju.
Oblik d) je ispravan i na zaslon će ispisati brojeve: 1, 3, 5, 7 i 9, jer se kontrolna varijabla
i povećava za 2 prilikom svake promjene vrijednosti.

Zadatak 2.
Kolika je vrijednost varijable a nakon izvođenja slijedećih naredbi:

int a=0;
do
a++;
while (a>10);

Zašto?
Rješenje:
Varijabla a=1, jer uvjet nije ispunjen. S obzirom da se uvjet ispituje na kraju, jednom se
izvrši naredba unutar petlje!

Zadatak 3.
Kolika je vrijednost varijabli a i b nakon izvođenja slijedećeg niza naredbi:

int a=10,b;
do
{
b=a/2;
a=pow(a,2);
} while (a<50);

Rješenje:

14
a=100, b=5

Zadaci za vježbu:
1. Što će se ispisati na zaslon monitora nakon izvođenja slijedećeg programa?

#include <stdio.h>
void main()
{
int i=1, s=0;
do
{
s+=i;
i++;
}while (i<=10);
printf("%d ",s);
}

Kako glasi tekst kojim bi se zadao prethodni program?

2. Napraviti program koji će pomoću do-while petlje zbrojiti troznamenkaste brojeve djeljive
sa 19. Osim dobivenog zbroja, program treba na zaslon ispisati i koliko ima takvih brojeva.

Test primjer:

Zbroj je 28832, a ima ih 53

3. Napravite program koji će korisniku omogućiti učitavanje brojeva sve dok se ne unese
-1. Program treba ispisati na zaslon koliko je među unesenim brojevima onih koji su djeljivi s
5.

Testni primjeri:

13,2,1,7,6,28,-1 15,21,5,10,13,-1

0 3

4. Napravite program koji će omogućiti unošenje brojeva sve dok se ne unese broj koji je
djeljiv s 3. Program treba ispisati koliko je ukupno uneseno brojeva (uključujući i posljednji
unesen broj) i njihov zbroj.

Testni primjeri:

2,7,13,17,21 4,22,41,32,16,18

ima ih 5 ima ih 6
zbroj: 60 zbroj: 133

Za one koji žele više…

1. Napraviti program koji će tražiti unošenje prirodnog broja n. Program treba pronaći i
ispisati na zaslon najmanji prost broj koji je veći od n.
/* Prosti brojevi su prirodni brojevi koji su djeljivi samo sa 1 i sa samim sobom */
15
2. Napraviti program koji će od korisnika tražiti unošenje realnog broja x. Program treba na
S  sin( x )  0.0001
zaslon ispisati prirodni broj n za koji vrijedi da je , gdje je
x3 x5 x7 x 2 n 1
S  x    
3! 5! 7! (2n  1)! .

Naredbe break i continue u petljama for, while i do-while


Naredba break je naredba koja unutar switch-case naredbe prekida izvršavanje
određenog bloka naredbi. Isto tako, može se koristi i za prijevremeni prekid petlje! Tada
prekida izvršavanje bloka naredbi unutar petlje i program nastavlja s prvom naredbom izvan
nje.

Primjer: Petlja

for (i=2;i<n/2;i++)
if(n%i) break;
printf("\n Broj %d nije prost",i);

za uneseni n provjerava da li je prost broj. Ukoliko program «naleti» na vrijednost kontrolne


varijable i za koju je vrijednost varijable n djeljiva sa i, izvršavanje petlje se prekida i
program nastavlja s izvršavanjem prve naredbe izvan petlje.

Naredba continue omogućuje preskakanje dijela bloka naredbi unutar petlje. Kada se
nalazi unutar bloka naredbi petlje, naredbe iza nje se preskaču i program se vraća na
uvjetni izraz koji omogućuje nastavak izvršavanja naredbi u petlji.

Primjer: Petljom

for (i=1;i<=50;i++)
{
if(i%3) continue;
printf("\n Broj %d je djeljiv s 3",i);
}

će se na zaslon ispisati svi brojevi iz intervala od 1 do 50 koji su djeljivi s 3. Ukoliko broj nije
djeljiv s 3 (i%3 je različito od 0) naredba koja slijedi se preskače i izvršavanje se nastavlja
od uvjeta ponavljanja! Ukoliko je broj djeljiv s 3 izvršava se naredba printf!
Ponovimo
Naredbe ponavljanja koriste se kada se isti dijelovi programa trebaju više puta ponoviti.
Programski jezik C razlikuje tri naredbe za ponavljanje. To su:
for petlja, kod koje se uvjet ponavljanja provjerava na početku i sadrži kontrolnu varijablu
while petlja, kod koje ponavljanje ovisi o uvjetu koji se nalazi na početku bloka naredbi koje
se ponavljaju i
do-while petlja, kod koje ponavljanje također ovisi o uvjetu, ali se uvjet nalazi na kraju bloka
naredbi koje se ponavljaju.
Ovisno o problemu koji se rješava, programer sam odlučuje koja naredba ponavljanja je
najbolji izbor.
Opći oblici spomenutih naredbi su:
for (inicijalizacija; uvjet; promjena_vrijednosti)
{
blok naredbi;
}

while (uvjet izvođenja)


{
blok naredbi;

16
}

do

blok naredbi;
 while (uvjet);
za prijevremeni prekid izvršavanja naredbi u petlji koristi se naredba break
za preskakanje dijela naredbi u petlji koristi se naredba continue
Funkcije
Već je rečeno da se svi programi u C-u sastoje od jedne ili više funkcija i da je jedina
obavezna funkcija u programu funkcija main() (koja označava početak izvršavanja glavnog
dijela programa). Tijekom procesa programiranja često se neki dijelovi programa trebaju
više puta izvoditi, ali sa različitim vrijednostima varijabli.

Na primjer: Neka su zadane tri točke u pravokutnom koordinatnom sustavu. Potrebno je


izračunati opseg i površinu trokuta koji nastaje spajanjem tih točaka.
Da bi se zadatak riješio, najprije treba
izračunati udaljenosti među točkama
C(x , y )
3 3

a tek onda primjenom Heronove


formule izračunati površinu danog
B(x2,y2) trokuta

A(x1, y1)

Rješenje zadatka izgledalo bi ovako:

#include <stdio.h>
#include <math.h>
void main(void)
{
float x1,x2,x3,y1,y2,y3,d1,d2,d3,o,s,p;
printf("Uneste koordinate tocke A ");
scanf("%f,%f",&x1,&y1);
printf("\nUnesite koordinate tocke B ");
scanf("%f,%f",&x2,&y2);
printf("\nUnesite koordinate tocke C ");
scanf("%f,%f",&x3,&y3);

/*racunanje udaljenosti medju tockama*/


d1=sqrt(pow(x2-x1,2)+pow(y2-y1,2));
d2=sqrt(pow(x3-x2,2)+pow(y3-y2,2));
d3=sqrt(pow(x1-x3,2)+pow(y1-y3,2));

/*primjena Heronove formule*/


o=d1+d2+d3;
s=o/2;
p=sqrt(s*(s-d1)*(s-d2)*(s-d3));

17
printf("\nDuljine stranica trokuta su %.2f, %.2f, %.2f",d1,d2,d3);
printf("\nOpseg je %.2f\nPovrsina je %.2f",o,p);
}

Lako se može uočiti da se za računanje udaljenosti među točkama zapravo koristi ista
formula, ali sa različitim vrijednostima. Takve dijelove programa praktično je izdvojiti u
zasebne cjeline, korisnički definirane funkcije i pozivati ih po potrebi.
Rješavamo li problem na takav način, možemo reći da se bavimo strukturnim
programiranjem.

Pojam strukturnog programiranja uveden je u trenutku kada se pojavila potreba za


standardizacijom pisanja programa. Programi su, zbog nepostojanja općih pravila za
njihovo pisanje, postajali sve veći i nepregledniji. Promjene programa ili ispravljanja grešaka
ponekad su bile gotovo nemoguće.

Glavna karakteristika strukturno napisanog programa je zadržavanje linearne strukture


glavnog programa, jer se mogu izdvojiti problemski zadaci koji se tada izvršavaju u
zasebnim dijelovima programskog koda.

U prethodnom primjeru možemo izdvojiti slijedeće problemske zadatke:

zadatak

unošenje koordinata računanje udaljenosti računanje površine


točaka između dvije točke trokuta

Pod funkcijama se podrazumijeva cjelovita skupina naredbi koja izvršavanjem ispunjava


određene zahtjeve.

To znači da je funkcija u C-u isto što i funkcija, potprogram i procedura u ostalim višim
programskim jezicima. One omogućavaju razlaganje problema na jednostavnije i manje
cjeline, čime doprinose boljoj preglednost izvornog koda i jednostavnijem pronalaženju i
otklanjanju pogrešaka. Također, korištenjem funkcija dolazi do značajnih ušteda
memorijskog prostora.
Funkcije se ne moraju koristi samo da bi se izbjeglo višestruko pisanje određenih dijelova
programa, već su praktične i ako će se izvršiti samo jednom. U tom slučaju olakšavaju
razumijevanje programa, odnosno algoritma.

Jednom napisanu funkciju moguće je koristiti u više različitih programa.

Da bi se napisala funkcija potrebno je znati kako ju ispravno definirati i pozvati.


Definiranje funkcije
Definicija funkcije je izvorni kod kojim je određen način rada pojedine funkcije. Svaku
funkciju treba definirati na točno propisan način. Postoje dva načina definiranja funkcije.

Prvi način je noviji i preporuča se ANSI C standardom:

tip_funkcije ime_funkcije(najava liste_argumenata)


{
najava lokalnih varijabli;
naredbe;
return izlazna_vrijednost;
}
18
gdje:
tip_funkcije određuje tip vrijednosti koju pozvana funkcija vraća u nadređenu funkciju, a
može biti bilo koji od osnovnih tipova podataka (int, char, float, double, void)
ime_funkcije je identifikator preko kojeg se funkcija poziva, dok je
lista_argumenata lista formalnih parametara sa pripadajućim tipovima preko kojih se niz
podataka iz nadređene funkcije prenose u pozvanu funkciju.

Slijedeća funkcija ima takvu definiciju:

int pomnozi(int x, int y)


{
int rez; /*najava lokalne varijable*/
rez=x*y; /*naredbe u funkciji*/
return rez; /*izlazna vrijednost*/
}

Drugi način razlikuje se od prvog po tome što se argumenti funkcije najavljuju izvan
zagrade.

tip_funkcije ime_funkcije(lista_argumenata)
najava liste_argumenata;
{
najava lokalnih varijabli;
naredbe;
return izlazna_vrijednost;
}

Prethodni primjer zapisan na ovakav način je:

int pomnozi(x,y)
int x,y; /*najava liste argumenata*/
{
int rez; /*najava lokalne varijable*/
rez=x*y; /*naredbe u funkciji*/
return rez; /*izlazna vrijednost*/
}

Funkciju je dovoljno definirati samo jednom. Nakon toga moguće ju je pozvati iz bilo
kojeg dijela programa. Funkcije u C-u mogu vratiti u glavni program jednu ili niti jednu
vrijednost (što je određeno tipom funkcije). Za to se koristi naredba return koja prenosi
izlaznu vrijednost u nadređeni program. Funkcija se prestaje izvršavati nailaskom na prvu
return naredbu.

Funkciji koja ne vraća nikakvu vrijednost dodjeljuje se tip podataka void. Takve funkcije
služe za obavljanje niza radnji, recimo za ispis, i ne sadrže return naredbu.

Na primjer, funkcija proba ne prenosi nikakvu vrijednost u glavni program već samo
ispisuje navedeni tekst.

void proba()
{
printf("Ovo je funkcija");
}

19
Ako u glavni program treba vratiti niz vrijednosti onda se to radi preko argumenta funkcije
koji su najavljeni kao globalne varijable. Slijedeća funkcija će u glavni program vratiti dvije
vrijednosti.

#include <stdio.h>
int a,b; /*najava globalnih varijabli*/

/*funkcija zamjene*/
void zamjena ()
{
int t; /*lokalna varijabla*/
t=a; /*zamjena koristenjem globalnih varijabli*/
a=b;
b=t;
}
void main()
{
printf("Unesite dva cijela broja ");
scanf("%d,%d",&a,&b);
printf("\nUpisali ste a=%d i b=%d",a,b);
zamjena(); /*poziv funkcije sa globalnim varijablama*/
printf("\nNakon funkcije a=%d, b=%d",a,b);
}

Ukoliko funkcija vraća cjelobrojnu vrijednost tip podataka se može izostaviti.

Na primjer, slijedeće funkcije su iste:

int proba1(int x)
{
return(x*x);
}

proba1(int x)
{
return(x*x);
}
Formalni parametri funkcije
Po samoj definiciji funkcija, njihova je namjena različita. Neke ne zahtijevaju ulazne
podatke, pa lista_argumenata može ostati i prazna (kao kod ranije navedenih funkcija proba
i zamjena). Ako ulazni podaci postoje, za svaki od njih se navodi tip podatka i identifikator.
Međusobno se odvajaju zarezom (kao kod funkcije proba1).
U funkciji proba1 identifikator x je formalni parametar koji služi za rezerviranje memorijskog
prostora. Tek pozivom funkcije na mjesto formalnog parametra učitava se u memoriju
stvarna vrijednost navedena u pozivu.

Kao što je navedeno na početku, argument funkcije se, osim unutar zagrada, može
deklarirati i ovako:

int proba1(x)
int x;
{
return(x*x);
}

iako je češće u upotrebi deklaracija kod koje se i tip i ime svakog formalnog parametra
navode unutar zagrade.

20
Poziv funkcije
Funkcija se izvršava onog trena kad je pozvana iz glavnog programa ili neke druge
funkcije.

Za poziv funkcije dovoljno je navesti njeno ime i listu stvarnih argumenata onim
redoslijedom kako su navedeni u najavi funkcije:
ime_funkcije (stvarna lista_argumenata);

Lista argumenata može biti i prazna. Ako je lista prazna onda funkcija koristi globalne
varijable (kao u primjeru funkcije zamjena) . No obavezno je pisati zagrade (), jer one
označavaju da se kontrola tijeka programa prenosi iz nadređene u pozvanu funkciju.
Funkcije se mogu pozivati u izrazima, petljama, ili kao argumenti u pozivima drugih
funkcija.
Deklaracija funkcije
Svaka funkcija se prije poziva treba najaviti.

Najava omogućava pravilnu pretvorbu različitih tipova podataka, te provjeru tipova podataka
u listi argumenata i podataka iz glavnog programa koji se prenose u funkciju.

Ako se funkcija piše na kraju glavnog programa, najavljuje se navođenjem tipa, imena i
tipa podataka ulaznih argumenata (prototip funkcije), kao što je to učinjeno u slijedećem
primjeru funkcije za računanje udaljenosti između dvije točke u pravokutnom koordinatnom
sustavu:

#include <stdio.h>
#include <math.h>
/*najava funkcije za racunanje udaljenosti*/
float udaljenost(float,float,float,float) ; /*prototip funkcije*/

/*pocetak glavnog programa*/


void main()
{
float x1,x2,y1,y2,d1;
printf("Upisite koordinate tocke T1 ");
scanf("%f,%f",&x1,&y1);
printf("\nUpisite koordinate tocke T2 ");
scanf("%f,%f",&x2,&y2);

/*racunanje udaljenosti medju tockama T1 i T2 pozivom funkcije*/


d1=udaljenost(x1,y1,x2,y2);
printf("\nUdaljenost medju zadanim tockama je %.2f\n",d1);
}

/*kraj glavnog dijela programa*/

/*tijelo funkcije za racunanje udaljenosti*/


float udaljenost(float a,float b,float c,float d)
{
float dulj;
dulj=sqrt(pow(c-a,2)+pow(d-b,2));
return dulj;
}

Test primjer:

21
0,0
3,0

Udaljenost medju zadanim tockama je 3.00

Međutim, u C-u je uobičajeno pisati funkciju na početku, nakon svih predprocesorskih


naredbi i najava globalnih varijabli, ali prije funkcije main(). Tada ju ne treba posebno
najavljivati, jer je sama funkcija ujedno i najava.

Primjer:

#include <stdio.h>
#include <math.h>
/*funkcija za racunanje udaljenosti*/
float udaljenost(float a,float b,float c,float d)
{
float dulj;
dulj=sqrt(pow(c-a,2)+pow(d-b,2));
return dulj;
}

/*pocetak glavnog programa*/


void main()
{
float x1,x2,y1,y2,d1;
printf("Upisite koordinate tocke T1 ");
scanf("%f,%f",&x1,&y1);
printf("\nUpisite koordinate tocke T2 ");
scanf("%f,%f",&x2,&y2);

/*racunanje udaljenosti medju tockama T1 i T2 pozivom funkcije*/


d1=udaljenost(x1,y1,x2,y2);
printf("\nUdaljenost medju zadanim tockama je %.2f\n",d1);
}

Osim navedenih načina, definicija funkcije može biti i u odvojenoj datoteci ili unutar neke
druge funkcije. No takve se najave rjeđe koriste. U tim slučajevima obavezno je najaviti
funkciju.

Funkcija se može pojaviti kao argument druge funkcije i broj ugniježđenih funkcija nije
ograničen.

22
Primjer: Nakon izvođenja slijedećeg programa:

#include <stdio.h>
void funkcija_3()
{
printf("\nFunkcija_3"); ZAPAMTITE:
} FUNKCIJA NE MOŽE BITI
POZVANA AKO PRIJE POZIVA
void funkcija_2() NIJE NAJAVLJENA!
{
printf("\nFunkcija_2"); Stoga Funkcija_3 mora biti
funkcija_3(); najavljena prije nego je pozvana.
printf("\nOpet funkcija_2"); Obzirom da se poziva u funkciji_2
} mora biti najavljena prije nje. Isto
tako funkcija_2 je najavljena prije
void funkcija_1() funkcije_1 jer se u njoj poziva!
{
printf("\nFunkcija_1");
funkcija_2();
printf("\nOpet funkcija_1");
}

void main()
{
printf("Glavni program");
funkcija_1();
printf("\nOpet glavni program");
}

na zaslon će se ispisati redom:

Glavni program
Funkcija_1
Funkcija_2
Funkcija_3
Opet funkcija_2
Opet funkcija_1
Opet glavni program

Pokušajmo sada, koristeći prethodnu funkciju za računanje udaljenosti između dvije


točke, riješiti zadatak sa početka.

Zadatak:
Napraviti program koji će, koristeći funkciju za udaljenost dvije točke, izračunati i ispisati
opseg i površinu trokuta zadanog koordinatama svojih točaka u pravokutnom koordinatnom
sustavu.

Rješenje:

#include <stdio.h>
#include <math.h>
float o;
float udaljenost(float a,float b,float c,float d)
{
float dulj;
dulj=sqrt(pow(c-a,2)+pow(d-b,2));
return dulj;

23
}
float opseg (float d1, float d2, float d3)
{
o=d1+d2+d3;
return o;
}
float povrsina (float d1, float d2, float d3)
{
float s,p;
s=o/2;
p=sqrt(s*(s-d1)*(s-d2)*(s-d3));
return p;
}
void main()
{
float x1,x2,x3,y1,y2,y3,d1,d2,d3,p;
printf("Upisite koordinate tocke A ");
scanf("%f,%f",&x1,&y1);
printf("\nUpisite koordinate tocke B ");
scanf("%f,%f",&x2,&y2);
printf("\nUpisite koordinate tocke C ");
scanf("%f,%f",&x3,&y3);

/*racunanje duljina stranica pozivom funkcije*/


d1=udaljenost(x1,y1,x2,y2);
d2=udaljenost(x2,y2,x3,y3);
d3=udaljenost(x1,y1,x3,y3);
o=opseg(d1,d2,d3);
p=povrsina(d1,d2,d3);
printf("\nDuljine stranica trokuta su %.2f, %.2f, %.2f",d1,d2,d3);
printf("\nOpseg je %.2f\nPovrsina je %.2f",o,p);
}

Test primjer:
0,0
3,0
0,4
Stranice trokuta su 3.00, 5.00, 4.00
Opseg je 12.00
Povrsina je 6.00

Top-down metoda
Za raščlambu problema na manje zadatke, kao šo smo to radili u prethodnim primjerima
postoji i naziv: top-down metoda rješavanja zadatka. Top-down je općenit postupak koji se
ne koristi samo u programiranju. Njime se dani problem raščlanjuje na manje zadatke –
module. Pojedini moduli tada se rješavaju ili, ako je potrebno, ponovo dijele na nove
module. To je metoda koju smo i do sada koristili u svim dosadašnjim zadacima, sa
iznimkom zadataka rješavanih goto naredbom

Primjer:
Rotiramo li pravokutni trokut oko njegovih kateta i hipotenuze, dobit ćemo 4 stošca (po
jedan rotacijom oko kateta i dva spojena rotacijom oko hipotenuze). Treba pronaći stožac
sa najmanjim volumenom!

24
R 2v
V 
3

c
b

vc

problem

učitati duljine Izračunati obujme stožaca Pronalaženje najmanjeg


stranica obujma

provjeriti je li trokut Izračunati duljinu Izračunati visine stožaca


pravokutan visine na hipotenuzu dobivenih rotacijom oko
hipotenuze

funkcija main() je oblika:


{
učitavanje duljina stranica
provjera je li trokut pravokutan
obujam stožaca
pronalaženje najmanjeg obujma
ispis rezultata
}

Top-down metoda je potpuno u skladu sa principima strukturalnog programiranja.

#include<stdio.h>
#include<math.h>
#define pi 3.14
/*funkcija koja provjerava je li ucitani trokut pravokutan*/
int provjera(float x, float y, float z)
{
int p=0;
if (pow(x,2)+pow(y,2)==pow(z,2)) p=1;
return p;
}
/*funkcija koja racuna obujam stozca*/
float obujam(float r, float v)
{
float o;
25
o=(pow(r,2)*pi*v)/3;
return o;
}
float pitagora(float z, float y)
{
float x;
x=sqrt(pow(z,2)-pow(y,2));
return x;
}
/*manji od dva broja*/
float manji (float x, float y)
{
float z;
if (x<y)z=x;
else z=y;
return z;
}
void main()
{
float a,b,c,p,o1,o2,o3,o4,vc,min;
int k=0;
do
{
printf("Upisite duljine kateta pravokutnog trokuta: ");
scanf("%f, %f", &a, &b);
printf("Upisite duljinu hipotenuze: ");
scanf("%f", &c);
k=provjera(a,b,c);
}while (k==0);
p=a*b/2;
vc=(2*p)/c;
o1=obujam(a,b);
o2=obujam(b,a);
o3=obujam(vc,pitagora(a,vc));
o4=obujam(vc,pitagora(b,vc));
min=o1;
min=manji(min,o2);
min=manji(min,o3);
min=manji(min,o4);
printf("\nNajmanji obujam je %.3f", min);
}
Prijenos podataka
Podaci iz nadređenih funkcija prenose se na dva načina:
pomoću vrijednosti (call by value) ili
pomoću adrese (call by reference)

Osnovna karakteristika prijenosa podatka pomoću vrijednosti je da promjena vrijednosti


argumenata unutar pozvane funkcije ne utječe na promjenu vrijednosti prenesenih varijabli
u nadređenoj funkciji. Dakako da tip argumenata pozvane funkcije mora odgovarati
podacima koji se šalju iz nadređene funkcije.

Primjer: Nakon izvođenja slijedećeg programa

#include <stdio.h>
int funkcija(x)
{
x*=2;

26
printf("\nx u funkciji je %d",x);
}

void main(void)
{
int x=5;
funkcija(x);
printf("\nVrijednost varijable x=%d",x);
}

na zaslon će se ispisati:
x u funkciji je 10
Vrijednost varijable x=5

Zašto?
Obzirom da je početna vrijednost varijable x=5, ta vrijednost prenosi se u funkciju. U
funkciji se ulazna varijabla množi sa 2 i dobivena vrijednost se opet sprema u varijablu x.
Ispisuje se vrijednost varijable x u funkciji. No, promjena vrijednosti varijable unutar funkcije
ne prenosi se u glavnu funkciju tako da je u glavnom programu x=5.

Prijenos podataka pomoću adrese karakterističan je po tome što promjena vrijednosti


argumenta pozvane funkcije utječe na promjenu vrijednosti prenesenih varijabli nadređene
funkcije. Ovim načinom se u pozvanu funkciju prenose adrese varijabli nadređene funkcije.

Za prijenos podataka preko adrese koriste se pokazivači i o tome će biti više riječi u
poglavlju o pokazivačima

Svi podaci, njihove vrijednosti ili adrese, prenose se preko STOGA (eng. stack). Stog je
dinamički dio memorije koji se upotrebljava za pohranjivanje podataka koji se privremeno
koriste u određenim djelovnima programa. Broj podataka na stogu je promjenljiv. Međutim,
količina memorije za stog je ograničena. Stog se puni i prazni prema principu «zadnji unutra
– prvi van» (eng. LIFO – last in – first out)

Zadaci za vježbu:
1. Ako je definirana funkcija na slijedeći način:

broj()
{
return(7.56);
return (2);
return(10);
}

koju će vrijednost vratiti u glavni program? Zašto?

2. Kolike će biti vrijednost varijabli x i y nakon izvođenja slijedećeg programa?

#include <stdio.h>
proba(x)
int x;
{
x=2*x;
return x;
}

void main()
{

27
int x=10,y;
y=2*proba(x);
printf("\nx=%d\ny=%d",x,y);
}

3. Napraviti program koji omogućuje unošenje duljina stranica pravokutnika pa pomoću


funkcija za računanje površine i opsega računa i ispisuje površinu i opseg.

Test primjer:
3,0

Duljina stranice mora biti veca od 0

5,7

Povrsina je 35.00
Opseg je 24.00

4. Napraviti program koji će omogućiti unošenje duljine stranice kocke. Program treba,
koristeći funkcije, ovisno o želji korisnika izračunati i ispisati oplošje, volumen ili duljinu
prostorne dijagonale zadane kocke.

Test primjeri:
5
1

Oplosje je 150.00

5
2

Volumen je 125.00
5
3

Duljina pr. dijagonale je 8.66

Za one koji žele više…

1. Napraviti program koji će omogućiti unošenje brojnika i nazivnika jednog razlomka.


Program treba, koristeći funkciju za skraćivanje razlomka, potpuno skratiti učitani razlomak.

2. Napraviti program koji će, koristeći funkciju, za zadani prirodan broj provjeriti je li prost.

Test primjeri:
256

Broj 256 NIJE prost broj

17

28
Broj 17 JE prost broj

3. Napraviti program koji će za uneseni prirodan broj ispisati sve njegove djelitelje.

Test primjer:
256

2 4 8 16 32 64 128

17

Broj nema djelitelja

Rekurzivna funkcija
Rekurzivna funkcija je funkcija koja poziva samu sebe. U pravilu, rekurzivna rješenja su
kraća, ali je za njihovo izvođenje potrebno više vremena i memorije.
Svaka rekurzija mora imati uvjet zaustavljanja koji će omogućiti izlazak iz rekurzije. U
protivnom rekurzivna funkcija će se izvoditi beskonačno. Također svaki poziv rekurzije mora
se približavati uvjetu zaustavljanja.

Svi podaci, njihove vrijednosti ili adrese, prenose se preko STOGA (eng. stack). Stog je
dinamički dio memorije koji se upotrebljava za pohranjivanje podataka koji se privremeno
koriste u određenim dijelovima programa. Broj podataka na stogu je promjenljiv. Međutim,
količina memorije za stog je ograničena. Stog se puni i prazni prema principu «zadnji unutra
– prvi van» (eng. LIFO – last in – first out). Za bolje razumijevanje stoga često se koristi
analogija s hrpom tanjura (npr. u restoranima): posljednji tanjur stavljen na hrpu se uzima
prvi.
Na stogu se koriste dvije operacije: push i pop. Operacija push šalje podatak na stog dok
operacija pop skida podatak sa stoga.
Za pohranjivanje rezultata i povratak iz rekurzije upotrebljava se STOG.

Primjer: Izračunavanje vrijednosti funkcije n! pomoću rekurzije.


/*Ovaj problem već smo rješavali iterativno*/
Po definiciji je:
0! 1
1!  1
2 !  1 2  2  2 !  1!  2
3 !  1 2  3  6  3 !  2!  3
4 !  1 2  3  4  24  4 !  3! 4
5 !  1  2  3  4  5  120 .  5 !  4! 5
Itd

n !  1 2  3  4  5     n  1  n  ?  n !   n  1 !  n

Dakle n! se može izračunati ako je poznat (n-1)!, a (n-1)! može se izračunati ako je
poznat (n-2)!, itd.

Iz prethodnog razmatranja možemo zaključiti slijedeće: ako računamo umnožak prvih n


prirodnih brojeva

29
uvjet zaustavljanja je 1!=1,
a opći oblik će biti n!  n  ( n  1)! .

Rekurzivna funkcija bi glasila:

long int faktorijel(int n)


{
if (n==1) /*moze biti i n==0*/
return 1;
else
return faktorijel(n-1)*n;
}

Što se zapravo događa?


STOG /*na početku je prazan*/
Neka je n = 4. Pri prvom pozivu 1. korak
rekurzivne funkcije na stog se spremi 4
vrijednost n = 4.
2. korak
Obzirom da 4 nije jednako 1 ponovo se 3
poziva rekurzivna funkcija, ali sada je 4
n = n - 1 = 3 pa se na stog sprema
vrijednost 3.
3. korak
Obzirom da opet nije ispunjen uvjet 2
zaustavljanja funkcija se ponovo poziva 3
ali za n = 2. Ta vrijednost se sprema na 4
stog. 4. korak
1
Funkcija se poziva ponovo s vrijednosti 2
n = 1. Sada je uvjet zaustavljanja
3
zadovoljen.
4

30
Kad rekurzivna funkcija dostigne uvjet zaustavljanja, stog se prazni po principu «prvi
unutra – zadnji van». Znači, prvo se izračunava vrijednost funkcije za n = 1.

faktorijel (1) =1 (uvjet zaustavljanja) 1. korak


1
2
3
4
Uzima se slijedeća vrijednost sa stoga 2. korak
(n=2) i izračunava 2
faktorijel 2  2  faktorijel1  2  1  2 3
4
Sada je n=3 i 3. korak
faktorijel 3   3  faktorijel 2  3  2  6 3
4
i konačno 4. korak
faktorijel 4   4  faktorijel 3   4  6  24
4

Primjer: Za nenegativan cijeli broj e slijedeće rekurzivna funkcija računa potenciju be, /*b0 =
1*/

long int potencija(int b,int e)


{
if (e==0)
return 1;
else
return b*potencija(b,e-1);
}

Zadatak: Napraviti program kojim se, za uneseni prirodan broj n računa zbroj:
x x 2 x3 x 4 xn
s    
1! 2! 3! 4! n!
/*iskoristite prethodnu rekurzivnu funkciju za računanje faktorijela!*/

Rješenje:

#include <stdio.h>
/*rekurzivna funkcija za racunanje potencije+/
long int potencija(int b,int e)
{
if (e==0)
return 1;
else
return b*potencija(b,e-1);
}
/*rekurzivna funkcija za racunanje faktorijela*/
long int faktorijel(int n)
{
if (n==1)
return 1;
else
return faktorijel(n-1)*n;
}
void main(void)

31
{
int x,i,y;
float s;
printf("Upisite prirodan broj x i n ");
scanf("%d,%d",&x,&y);
if (y<=0)
printf("Broj mora biti prirodan");
else
{
for (i=1;i<=y;i++)
s+=(float)potencija(x,i)/faktorijel(i);
printf("Zbroj je %.2f ",s);
}
}

Zadaci za vježbu:
1. Što će se ispisati na zaslonu monitora nakon izvođenja slijedećeg programa ako se
prilikom unosa podataka upišu vrijednosti:
a) broj=15, baza=2
b) broj=15, baza=8?

#include <stdio.h>
int pretvori (int n, int b)
{
if (n>=b) pretvori(n/b, b);
printf("%d ",n%b);
}
void main (void)
{
int broj, baza;
printf("\n Upisite jedan prirodni broj => ");
scanf("%d",&broj);
printf("\n Upisite bazu => ");
scanf("%d",&baza);
if (baza>=10)
printf("\nBaza mora biti <10");
else
pretvori(broj,baza);
}

2. Napravite rekurzivnu funkciju koja će za uneseni n izračunati prvih n članova


Fibonaccievog niza.
Uputa: Fibonacciev niz definiran je sa:
f 1  1
f  2  1
f  3   f 1  f  2
...
f  n  f  n  2  f  n  1

Test primjer:

f(1)=1
f(2)=1
f(3)=2
32
f(4)=3
f(5)=5
f(6)=8
f(7)=13

3. Napravite rekurzivnu funkciju koja zbraja znamenke unesenog prirodnog broja n.


Za one koji žele više…

4. Napravite rekurzivnu funkciju za računanje binomnih koeficijenata.


 m  m! (m  n)!
B    
n  n!
2. Napišite program kojim ćete ispisati sve poteze potrebne za prebacivanje Hanojskih
diskova.
Uputa: Hanojski tornjevi su stari indijski problem. Prema legendi indijski bog Brahma je
prilikom stvaranja svijeta postavio tri dijamantna štapa i na prvog stavio 64 zlatna diska
različitih promjera (od najvećeg prema najmanjem koji je na vrhu). Svećenici hrama imaju
obavezu bez prestanka prebacivati diskove sa prvog štapa na treći upotrebljavajući srednji
štap kao pomoćni. U jednom koraku se može premjestiti samo jedan disk. Uvijek se mora
stavljati manji disk na veći. Obrnuto nije dozvoljeno. Kada svi diskovi budu prebačeni s
prvog na treći doći će do smaka svijeta.
Na primjer, uzmimo da je broj diskova n=3.

Potezi su slijedeći:
zeleni disk sa prvog na treći štapić,
smeđi disk sa prvog na drugi štapić,
zeleni disk sa trećeg na drugi štapić,
plavi disk sa prvog na treći štapić,
zeleni disk sa drugog na prvi štapić,
smeđi disk sa drugog na treći štapić, i konačno
zeleni disk sa prvog na treći štapić.
Dakle za n = 3 najmanji broj poteza je 7. Za n diskova najmanji broj poteza je 2n-1. Problem
se svodi na to da na pomoćni štap stavimo n -1 disk i nakon toga n disk prebacimo na treći
štap. Dalje n -1 disk sa pomoćnog štapa analogno prenosimo na treći štap.

3. Napišite program kojim će te uporabom rekurzivne funkcije podijeliti dva učitana prirodna
broja na zadani broj decimala.

Ponovimo
Funkcije su cjelovite skupine naredbi koje izvršavanjem ispunjavaju određene zahtjeve
Omogućavaju razlaganje problema na jednostavnije manje cjeline, čime doprinose boljoj
preglednost izvornog koda i jednostavnijem pronalaženju i otklanjanju pogrešaka
Funkcija se definira na slijedeći način:
tip_funkcije ime_funkcije(najava liste_argumenata)
{

33
najava lokalnih varijabli;
naredbe;
return izlazna_vrijednost;
}
funkcija u nadređeni program vraća jednu ili niti jednu vrijednost ovisno o tipu funkcije
Za prijenos vrijednosti u nadređeni program koristi se naredba return
Funkcija se poziva na slijedeći način:
ime_funkcije(stvarna lista_argumenata);
Funkcije se mogu pozivati u izrazima, petljama, ili kao argumenti u pozivima drugih funkcija
Svaka korištena funkcija se mora najaviti prije poziva
Podaci iz nadređenih funkcija prenose se na dva načina:
pomoću vrijednosti (call by value)
pomoću adrese (call by reference)
STOG je dinamički dio memorije koji se upotrebljava za pohranjivanje podataka koji se
privremeno koriste u određenim djelovnima programa
Stog se puni i prazni prema principu «zadnji unutra – prvi van» (eng. LIFO – last in – first
out)
Rekurzivna funkcija je funkcija koja poziva samu sebe
Svaka rekurzija mora imati uvjet zaustavljanja koji će joj omogućiti izlaz
Svaki poziv rekurzije mora se približavati uvjetu zaustavljanja

34

You might also like