You are on page 1of 16

Matematiki fakultet

Programiranje 1 programski jezik C


Beleke sa asova vebi
kolska 2010/2011




Biljana Stojanovi

as 09, 30. 11. 2010.












Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

1
1

1.1 Funkcije

Funkcije razbijaju velike raunske zadatke u manje celine i omoguavaju upotrebu
ve postojeeg koda.
Funkcije skrivaju detalje postupka od delova programa i time ine ceo program
jasnijim i jednostavnijim za menjanje.

Funkcije mogu da vraaju vrednost (rezultat) pozivajuoj funkciji ili ne.

Definicija funkcije obuhvata:
tip povratne vrednosti funkcije ili tip rezultata (ako se ne navede podrazumeva se
int)
ime funkcije
listu formalnih parametara ili argumenata funkcije
telo funkcije

Deklaracija (prototip) funkcije je definicija funkcije bez tela funkcije. Prototip
funkcije zavrava se znakom ;.

Primer prototipa i definicije funkcije:

tip_rezultata ime_funkcije (tip param1, tip param2, ..., tip paramN);

tip_rezultata ime_funkcije (tip param1, tip param2, ..., tip paramN)
{
//telo funkcije
}

Poziv funkcije unutar programa podrazumeva navoenje:
imena funkcije
liste stvarnih argumenata funkcije

Mehanizam za vraanje vrednosti iz pozvane funkcije predstavlja naredba return.
Iza return moe se nalaziti bilo koji izraz.

return izraz;

Tip izraza se pretvara u tip rezultata ako je to neophodno.
Takoe, iza return ne mora uopte da se navede neki izraz u tom sluaju se
nijedna vrednost ne vraa pozivaocu.


1
Zasnovano na primerima kolega Milana Bankovia (www.matf.bg.ac.rs/~milan), Jelene Graovac
(www.matf.bg.ac.rs/~jgraovac) i Stae Vujii (www.matf.bg.ac.rs/~stasa)

Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

2
Funkcija koja ne vraa nikakvu vrednost deklarie se da ima povratni tip void.
Slino, ako funkcija nema argumente, u deklaraciji se umesto liste argumenata
navodi void.
Svi ranije pomenuti osnovni tipovi u C-u mogu biti povratni tipovi funkcije.

Primer 1: Napisati funkciju koja vri sabiranje dva cela broja i program koji testira
rad ove funkcije.

#include <stdio.h>

/* Definicija funkcije */
int zbir(int a, int b)
{
return a+b;
}
int main() //pozivajuca funkcija
{
/* Poziv funkcije zbir */
int rezultat = zbir(3,5);
printf("%d\n", rezultat);

return 0;
}

NAPOMENA: Deklaracija funkcije moe da stoji nezavisno od definicije funkcije, ali
mora da odgovara definiciji.
Ako se funkcija definie posle glavne funkcije main(), na poetku programa (pre
funkcije main) mora da postoji prototip funkcije (deklaracija funkcije).
Dakle, deklaracija funkcije je neophodna u sluaju kada se njena definicija navodi
nakon upotrebe date funkcije u kodu.
Ako prototip ne postoji, bie izvrena implicitna deklaracija funkcije kada se ona
prvi put pozove u nekom izrazu. Za takve funkcije se pretpostavlja da vraaju tip
int i nita se ne pretpostavlja o njihovim argumentima, to moe da dovede do
nepoklapanja.

Primer 2: Funkcija koja sabira dva broja (deklaracija stoji nezavisno od definicije).

#include <stdio.h>

int zbir(int, int); /* Deklaracija (prototip) funkcije */

int main() //pozivajuca funkcija
{
/* Poziv funkcije zbir */
int rezultat = zbir(3,5);
printf("%d\n", rezultat);

return 0;
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

3
}

/* Definicija funkcije */
int zbir(int a, int b)
{
return a+b;
}

Kada se u main() funkciji pojavi izraz:
rezultat = zbir(3,5);
realizuju se sledee akcije:
- Rezervie se memorijski prostor za promenljive deklarisane u funkciji zbir();
- Formalnim parametrima se dodeljuju vrednosti stvarnih parametara: a=3; b=5;
- Izvrava se telo funkcije;
- Rezultat izraunavanja u funkciji se postavlja na mesto obraanja toj funkciji,
odnosno dodeljuje se promenljivoj rezultat, i prelazi se na izvrenje sledee
naredbe u funkciji main().

Primer 3: (Nalaenje maksimuma dva broja). Program pronalazi maksimum dva
broja koji se uitavaju sa ulaza. Maksimum se izraunava u posebnoj funkciji.
Program demonstrira upotrabu najjednostavnijih funkcija.

#include <stdio.h>

/* Funkcija max() prihvata dva broja
i vraca njihov maksimum */
int max(int a, int b)
{
return a > b ? a : b;
}

/* Funkcija main */
int main()
{
int a, b, m;

/* Ucitavamo dva cela broja */
printf("Uneti dva broja: ");
scanf("%d%d", &a, &b);

/* Pozivamo funkciju max(), predajemo joj
vrednosti promenljivih a i b, i njenu
povratnu vrednost smestamo u m */
m = max(a,b);

/* Prikazujemo m */
printf("Maksimum je: %d\n", m);

Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

4
return 0;
}

Primer 4: (Ojlerova funkcija). Program rauna vrednost Ojlerove funkcije pozitivnog
celog broja unetog sa ulaza. Pod Ojlerovom funkcijom (n) podrazumevamo broj
brojeva m, takvih da je 1 m < n i da su m i n uzajamno prosti. Ojlerova funkcija,
kao i NZD(m, n) se raunaju u posebnim funkcijama.

#include <stdio.h>

/* Deklaracije funkcija (prototipovi) */
int nzd(int n, int m);
int euler(int n);

/* main */
int main()
{
int n;

/* Unosimo ceo broj, a zatim izracunavamo
njegovu Ojlerovu funkciju, i ispisujemo
vrednost na izlaz */
printf("Uneti pozitivan ceo broj: ");
scanf("%d", &n);
printf("euler(%d) = %d\n", n, euler(n));

return 0;
}

/* Ojlerova funkcija broja n */
int euler(int n)
{
int br = 0, m;

/* Prolazimo kroz sve prirodne
brojeve m koji su manji od
n, i za svaki koji je uzajamno
prost sa n uvecavamo brojac */
for(m = 1; m < n; m++)
if(nzd(n,m) == 1)
br++;

/* Vracamo broj uzajamno prostih brojeva
sa brojem n */
return br;
}

/* Funkcija racuna nzd dva pozitivna broja
primenom euklidovog algoritma. */
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

5
int nzd(int n, int m)
{
int r;

/* Dokle god je m!=0, svodimo nzd(n,m) na
nzd(m,r), gde je r = n % m. */
while(m)
{
r = n % m;
n = m;
m = r;
}
/* Nakon sto je m postalo 0, jasno je da je
nzd(n,0) = n */
return n;
}

Primer 6: (Stepen broja). Program rauna n-ti stepen unetog realnog broja.
Raunanje ovog stepena se realizuje u posebnoj funkciji. Uitavanje i ispis se
takoe izdvajaju u posebne funkcije.

#include <stdio.h>

/* Funkcija nema argumente, i ne vraca vrednost.
Jedina njena uloga je da ispise pozdravnu
poruku */
void ispisi_poruku()
{
printf("Program racuna n-ti stepen realnog broja!\n");
}

/* Funkcija ucitava sa ulaza realan broj,
i vraca ga kao povratnu vrednost.
Funkcija nema argumente */
double ucitaj_realan_broj()
{
double a;
printf("Uneti realan broj: ");
scanf("%lf", &a);
return a;
}

/* Funkcija ucitava sa ulaza ceo broj,
i vraca ga kao povratnu vrednost.
Funkcija nema argumente */
int ucitaj_ceo_broj()
{
int a;
printf("Uneti ceo broj: ");
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

6
scanf("%d", &a);
return a;
}

/* Funkcija vraca n-ti stepen broja a */
double stepen(double a, int n)
{
double r;
for(r = 1; n ; n--, r *= a);

return r;
}

/* Funkcija prihvata realan broj, i prikazuje
ga na izlazu, sa tri decimale. Funkcija ne
vraca vrednost */
void prikazi_broj(double a)
{
printf("%5.3f\n", a);
}

int main()
{
int n;
double a;

ispisi_poruku(); /* Prikaz pozdravne poruke */
a = ucitaj_realan_broj(); /* Ucitava realan broj */
n = ucitaj_ceo_broj(); /* Ucitava ceo broj */
prikazi_broj(stepen(a, n)); /* Racuna stepen i ispisuje rezultat */

return 0;
}


Primer 6: Verzija funkcije stepen() koja radi i za negativne izloioce.

#include <stdio.h>

double stepen(double a, int n)
{
int negativan = n < 0;
double r;

if(negativan)
n = -n;
for(r = 1; n ; n--, r *= a);

return negativan ? 1.0/r : r;
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

7
}

int main()
{
double s = stepen(2.0, -1);
printf(%f\n, s);
return 0;
}


Primer 7: Napisati funkciju koja izraunava zbir n-tih stepena brojeva od 1 do
zadate granice i program koji ilustruje rad ove funkcije.

#include <stdio.h>

long zbir_stepena(int n, int granica);

int main()
{
printf("Zbir 2. stepena od 1 do 5 jeste %ld\n",
zbir_stepena(2,5));
printf("Zbir 3. stepena od 1 do 5 jeste %ld\n",
zbir_stepena(3,5));
printf("Zbir 4. stepena od 1 do 10 jeste %ld\n",
zbir_stpena(4,10));

return 0;
}

lont zbir_stepena(int n, int granica)
{
int i, j; /* brojaci u petljama */
long zbir = 0;
long stepenovan;

/* Spoljasnji for ciklus obavlja sumiranje */
for(i = 1; i <= granica; zbir += stepenovan, ++i)
/* Unutrasnji for ciklus obavlja stepenovanje */
for(stepenovan = 1, j = 1; j <= n; stepenovan *= i, ++j);
return zbir;
}

Ako izuzmemo korienje operatora zarez, funkcija moe da se napie jednostavnije
na sledei nain:

lont zbir_stepena(int n, int granica)
{
int i, j; /* brojaci u petljama */
long zbir = 0;
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

8
long stepenovan;



/* Spoljasnji for ciklus obavlja sumiranje */
for(i = 1; i <= granica; ++i)
{
stepenovan = 1;
/* Unutrasnji for ciklus obavlja stepenovanje */
for(j = 1; j <= n; ++j)
stepenovan *= i;
}
return zbir;
}

Ako iskoristimo funkciju stepen() iz prethodnog primera, ova funkcija moe jo
jednostavnije da se napie:

lont zbir_stepena(int n, int granica)
{
int i, j; /* brojaci u petljama */
long zbir = 0;

/* Spoljasnji for ciklus obavlja sumiranje */
for(i = 1; i <= granica; ++i)
zbir += stepen(i, n);

return zbir;
}

Primer 8: Napisati program koji prikazuje sve proste brojeve u datom intervalu
kojima je zbir cifara sloen broj. Interval se zadaje uitavanjem gornje i donje
granice (dva prirodna broja). Brojeve prikazati u opadajuem poretku.

#include <stdio.h>
#include <stdlib.h>

int prost(int n); /* Funkcija koja testira da li je broj n
prost */

/* Svi prirodni brojevi (sem 1) imaju najmanje dva delioca: jedinicu i
samog sebe. Brojevi koji nemaju drugih delilaca, sem ova dva, nazivaju
se prostim brojevima. */

int zbir_cifara(int n); /* Funkcija koja racuna i vraca zbir
cifara broja n */

int main()
{
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

9
int donja, gornja; /* granice intervala */
int i; /* brojac u petlji */
int pom; /* posrednik u eventualnoj zameni */

/* Ucitavanje granica intervala */
scanf("%d%d", &donja, &gornja);

if(donja > gornja) /* Obezbedjivanje relacije donja <= gornja */
{
pom = donja;
donja = gornja;
gornja = pom;
}

for(i = gornja; i >= donja; i--)
if(prost(i) && !prost(zbir_cifara(i)) )
printf("%d\n", i);
}

/* Ispituje se da li je broj n prost tako sto se proverava da li ima
delioce medju brojevima od 2 do n/2. Pri implementaciji se koristi
tvrdjenje da je broj prost ako je jednak 2, ili ako je neparan i ako
nema delitelja medju neparnim brojevima od 3 do n/2.
*/
int prost(int n)
{
int prost; /* Indikator slozenosti broja n */
int i; /* Potencijalni delitelj broja n */

if(n == 1) return 0;

/* Parni brojevi razliciti od 2 nisu prosti brojevi */
prost = (n % 2 != 0) || (n == 2);

/* Najmanji potencijalni kandidat za delitelje medju neparnim
brojevima razlicitim od jedan */
i = 3;

while( prost && i <= n/2)
{
prost = n%i != 0;
i = i + 2; /* Proveravamo kandidate za delitelje samo
meu neparnim brojevima */
}
return prost;
}

int zbir_cifara(int n)
{
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

10
int suma = 0;
while( n > 0 )
{
suma += n % 10;
n /= 10;
}
return suma;
}

1.1.2 Prenos parametara po vrednosti

Parametri se funkciji prenose po vrednosti, to znai da funkcija zapravo radi sa
njihovim lokalnim kopijama.
Sve promene koje funkcija naini nad parametrima, zapravo se odnose na lokalne
kopije parametara, a ne na same parametre.
Zakljuak je da se preneti parametri NE MOGU promeniti u telu funkcije.

Primer 9: Demonstracija prenosa parametara po vrednosti preneti parametri se
ne mogu menjati.

#include <stdio.h>

void f(int x)
{
x *= 2;
x++;
}

int main()
{
int x = 3;
f(x);
printf("%d\n", x);

return 0;
}

Promenjena vrednost lokalne kopije promenljive x u okviru funkcije f moe da se
vrati kao rezultat rada funkcije. Promenljiva x i dalje zadrava vrednost koju je
imala pre poziva funkcije f.

#include <stdio.h>

int f(int x)
{
return ++x;
}

Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

11
int main()
{
int x = 3;
printf("%d %d\n", x, f(x));
return 0;
}

Izlaz:
3 4

1.2 Spoljanje (globalne) promenljive

C program sastoji se od skupa spoljanjih objekata, koji mogu biti:
promenljive
funkcije

Spoljanje promenljive su definisane izvan svake funkcije i zato su potencijalno na
raspolaganju raznim funkcijama.

Funkcije su uvek spoljanje, jer C ne dozvoljava definisanje funkcija unutar drugih
funkcija.

Po standardu, spoljanje promenljive i funkcije imaju to svojstvo da sve reference
na njih po istom imenu, predstavljaju reference na istu stvar.

Prenoenje podataka izmeu funkcija:
preko argumenata
preko povratnih vrednosti
preko spoljanjih promenljivih

NAPOMENA: Ukoliko se veliki broj promenljivih mora deliti izmeu funkcija, bolje je
koristiti spoljanje promenljive nego dugake liste argumenata. Meutim, ovo treba
paljivo primenjivati, jer u suprotnom se dobija program sa previe veza izmeu
funkcija.

Poreenje spoljanjih i automatskih promenljivih:

Automatske promenljive su unutranje za funkciju. One nastaju kada otpoinje
izvravanje funkcije i nestaju kada se ono zavrava.
Spoljanje promenljive su permanentne i stoga zadravaju svoje vrednosti izmeu
poziva funkcija. Dakle, ivotni ciklus ovih promenljivih je dui.

Primer 10 (Broja karaktera): Program ita tekst sa ulaza i broji velika i mala slova,
cifre, beline i redove. Program demonstrira korienje globalnih podataka.

#include <stdio.h>
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

12

/* Deklaracija funkcije prebroj */
void prebroj();

/* Globalni brojaci. Podrazumevano su inicijalizovani nulom. */
int br_malih, br_velikih, br_cifara, br_belina, br_redova;

int main()
{
/* Pozivamo funkciju za prebrojavanje */
prebroj();

/* Prikazujemo vrednosti globalnih brojaca, koje je funkcija
prebroj() izmenila */
printf("Broj malih slova: %d\n", br_malih);
printf("Broj velikih slova: %d\n", br_velikih);
printf("Broj cifara: %d\n", br_cifara);
printf("Broj belina: %d\n", br_belina);
printf("Broj redova: %d\n", br_redova);

/* Povratna vrednost funkcije main() */
return 0;
}

/* Definicija funkcije prebroj() */
void prebroj()
{
int c;

while((c = getchar()) != EOF)
{
if(c >= 'a' && c <= 'z')
++br_malih;
else if(c >= 'A' && c <= 'Z')
++br_velikih;
else if(c >= '0' && c <= '9')
br_cifara++;
else if(c == '\n' || c == '\t' || c ==' ')
{
br_belina++;
if(c == '\n')
br_redova++;
}
}
}



Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

13
1.3 Statike promenljive

Deklaracija static, koja se primenjuje na spoljanju promenljivu ili funkciju,
ograniava domet tog objekta na preostali deo izvorne datoteke.

Deklaracija static se moe primeniti i na unutranje promenljive.
Unutranje statike promenljive su lokalne za odreenu funkciju ba kao i
automatske promenljive, ali za razliku od njih, one nastavljaju da postoje i nakon
zavretka funkcije. Dakle, one ne nastaju i ne nestaju sa svakim pozivom funkcije.
Na taj nain obezbeuju privatnu, stalnu memoriju unutar funkcije.

1.4 Inicijalizacija

Spoljanje i statike promenljive se uvek inicijalizuju na nulu ukoliko nisu
eksplicitno inicijalizovane.
Inicijalizator mora biti konstantan izraz.
Inicijalizacija se obavlja samo jednom, obino pre poetka izvravanja programa.

Automatske promenljive imaju nedefinisane (nepredvidive) poetne vrednosti
ukoliko nisu eksplicitno inicijalizovane.
Inicijalizator moe biti svaki izraz u kojem uestvuju prethodno definisane
vrednosti, pa ak i pozivi funkcija.
Inicijalizacija se obavlja svaki put prilikom izvravanja funkcije ili bloka.

Primer 11: Demonstracija ivotnog veka i oblasti vaenja promenljivih.

#include <stdio.h>

/* Globalna promenljiva */
int a = 0;

/* Uvecava se globalna promenljiva */
void uvecaj()
{
a++;
printf("uvecaj::a = %d\n", a);
}

/* Umanjuje se lokalna promenljiva a. Globalna promenljiva sa istim
imenom zadrzava svoju vrednost. */
void umanji()
{
/* Ova promenljiva a je nezavisna u odnosu na globalnu
promenljivu a */
int a = 0;
a--;
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

14
printf("umanji::a = %d\n", a);
}

void nestaticka_prom()
{
/* Nestaticke promenljive ne cuvaju vrednosti kroz pozive
funkcije */
int s = 0;
s++;
printf("nestaticka promenljiva::s = %d\n", s);
}

void staticka_prom()
{
/* Staticke promenljive cuvaju vrednosti kroz pozive funkcije.
Inicijalizacija se odvija samo u okviru prvog poziva. */
static int s = 0;
s++;
printf("staticka promenljiva::s = %d\n", s);
}

int main()
{
/* Promenljive lokalne za funkciju main */
int i;
int x = 3;

printf("main::x = %d\n", x);

for(i=0; i<3; i++)
{
/* Promenljiva u okviru bloka je nezavisna od spoljne
promenljive. Ovde se koristi promenljiva x lokalna za
blok for petlje koja ima vrednost 5, dok originalno x i
dalje ima vrednost 3 */
int x = 5;
printf("for::x = %d\n", x);
}

/* U ovom bloku x ima vrednost 3 */
printf("main::x = %d\n", x);

uvecaj();
umanji();

/* Globalna promenljiva a */
printf("main::a = %d\n", a);

/* Demonstracija statickih promenljivih */
Biljana Stojanovi | Univerzitet u Beogradu, Matematiki fakultet

15
for(i=0; i<3; i++)
nestaticka_prom();

/* Demonstracija statickih promenljivih */
for(i=0; i<3; i++)
staticka_prom();

return 0;
}

You might also like