Funkcije Definisanje funkcija Potprogrami: dekompozicija složenih problema na jednostavnije procesna apstrakcija samo funkcije (nema procedura) funkcija - n-arni operator najvišeg prioriteta vraća rezultat (preko imena) + bočni efekti, oboje opciono Definisanje funkcija [tip] ime(argumenti) telo ime funkcije identifikator tip funkcije mogu svi standardni skalarni tipovi, kao i korisnički definisani tipovi void funkcija ne vraća vrednost podrazumevani tip - int Definisanje funkcija tip funkcije ako * ispred imena vrednost funkcije je pokazivač na objekat navedenog tipa može i generički pokazivač (void *), pokazivač na pokazivač,... vrednost mora da bude samo jedan objekat (zato tip ne može biti niz) ali može pokazivač argumenti funkcije formalni (u definiciji) stvarni (u pozivu) unošenje vrednosti i iznošenje rezultata proizvoljan broj argumenata razdvojenih sa, definišu kao i promenljive, ali tip i kvalifikator za svaki posebno (npr. double x, double y) 1
Definisanje funkcija Definisanje funkcija argumenti funkcije argument može da bude niz zadatog tipa ili pokazivač na dati tip (int *a) za 1-D niz ne mora dužina, samo [] (int a[]) za n-d moraju se navesti dužine za sve dimenzije osim za prvu (int b[][5]) kvalifikatori ispred oznake argumenta tipa pokazivača ili niza const funkcija neće da promeni vrednost objekta na koji pokazuje argument volatile pokazivani objekt može da promeni vrednost mimo kontrole programa nema efekta za druge tipove Definisanje funkcija Prenos argumenata telo funkcije blok: deklaracije + naredbe (oboje opciono) promenljive lokalne za funkciju oblast važenja - od mesta definicije do kraja funkcije inicijalizacija izrazi koji, osim konstanti, mogu da sadrže i formalne argumente formalni argumenti se smatraju lokalnim promenljivima inicijalizuju se vrednostima stvarnih argumenata vrednosti stvarnih argumenata se ne mogu promeniti u funkciji (prenos po vrednosti by value) 2
Prenos argumenata iznošenje rezultata preko argumenata pokazivačkog tipa pokazivač se ne menja menja se vrednost pokazanog objekta (bočni efekat) indirektan pristup Prenos argumenata skalarni - po vrednosti nizova - po referenci (adresi) (ne prenose se vrednosti niza!) kako je indeksiranje praktično indirektno adresiranje nije potrebna posebna notacija za pristup komponentama Definisanje funkcija Definisanje funkcija povratak iz funkcije naredba return argument izraz koji predstavlja vrednost funkcije ako je potrebno, konverzija tipa povratak iz funkcije ako je funkcija tipa void, return ne sme da ima izraz return može da se izostavi, ako je poslednja naredba u funkciji može više naredbi return 3
Definisanje funkcija Pozivanje funkcija mesto definisanja funkcije: ime funkcije (stvarni argumenti) ista ili druga datoteka ispred ili iza poziva ne može u okviru funkcije može i adresni izraz čija je vrednost adresa funkcije (preko pokazivača) operator najvišeg prioriteta (15) Pozivanje funkcija Pozivanje funkcija poziv se vrši stvarni argumenti pri pozivu u okviru izraza ako funkcija ne vraća vrednost ili ona nije potrebna => poziv može i kao naredba izrazi proizvoljne složenosti i tipa čija vrednost inicijalizuje formalne argumente izračunavaju se proizvoljnim redosledom pre pozivanja funkcije 4
Pozivanje funkcija stvarni argumenti pri pozivu treba da se slažu po broju, tipu i poretku sa formalnim po potrebi se konvertuju u tip fomalnih mogu biti i adresni izrazi (npr. ime niza i adresa) Pozivanje funkcija stvarni argumenti pri pozivu ako je stvarni argument niz izraza, mora se staviti u zagrade (zbog zareza) na primer f(a,b,c) i f(a,(b,c)) Primer definisanja Primer pozivanja /* izračunavanje skalarnog proizvoda */ #include <stdio.h> double skal_pro(double a[], double b[], int n) { double zbir = 0; int i; for (i=0; i<n; i++) zbir += a[i] * b[i]; return zbir; 5 /* izračunavanje skalarnog proizvoda */ main () { double x[100], y[100]; int i, k; printf ("Duzina vektora:"); scanf ("%d", &k);
Pozivanje funkcija Primer definisanja /* izračunavanje skalarnog proizvoda */ printf ("Komponente vektora X:"); for (i=0; i<k; i++) scanf ("%lf", x+i); /* izračunavanje polarnih koordinata */ #include <stdio.h> #include <math.h> printf ("Komponente vektora y:"); for (i=0; i<k; i++) scanf ("%lf", y+i); printf ("skalarni proizvod X*Y:%g\n", skal_pro(x,y,k)); void polar (double x, double y, double *pr, double *pfi) { *pr = sqrt(x*x + y*y); *pfi = (x==0 && y==0)? 0 : atan2(y,x);... Primer pozivanja Obrada programskog sistema /* izračunavanje polarnih koordinata */ main () { double x, y, r, fi; while (printf("x, y :"), scanf("%lf%lf",&x,&y)!=eof) { polar(x,y,&r,&fi); printf ("r, fi: %g,%g\n",r,fi); čitav programski sistem se sastoji od proizvoljnog broja funkcija glavni program funkcija main() koju poziva OS 6
Obrada programskog sistema Obrada programskog sistema može u više datoteka, ali jedna funkcija mora u celini unutar datoteke poredak smeštanja funkcije proizvoljan prevođenje svaka datoteka odvojeno i nezavisno svaki objekt mora biti unapred deklarisan po poretku linija izvornog teksta Obrada programskog sistema Obrada programskog sistema prevođenje prototip ako je funkcija kasnije definisana (ili izvan datoteke), pre poziva se mora navesti prototip praktično zaglavlje funkcije (bez bloka) navodi spolja vidljive osobine funkcije (tip kao i argumente), ali ne i sadržaj 7
Obrada programskog sistema Obrada programskog sistema prototip prototip ne rezerviše prostor jednom naredbom može više funkcija sa istim osnovnim tipom argumenti mogu da se navode i bez imena (služe samo da sugerišu namenu) provera broja i tipova argumenata nije obavezna po standardu Obrada programskog sistema Obrada programskog sistema prototip prototip prototip može biti nepotpun (bez argumenata) može i da izostane (predpostavlja se int) ako se piše u deklarativnom delu funkcije, onda vidljiv samo u njoj može izvan tela drugih funkcija (tada vidljiv za sve u nastavku) 8
Lokalne i globalne promenljive Lokalne i globalne promenljive lokalne globalne promenljive definisane na početku tela funkcije važe samo unutar funkcije, nevidljive za druge funkcije mogu ista imena u različitim funkcijama - različite promenljive definišu se izvan funkcija oblast važenja od mesta definicije do kraja datoteke Lokalne i globalne promenljive Lokalne i globalne promenljive globalne zajedničke za sve funkcije samo između mesta definicije i kraja datoteke mogu služiti za prenos podataka između funkcija korišćenje globalne promenljive u funkciji gde nije automatski vidljiva obavezna deklaracija (samo osobine) nema dodele prostora i inicijalizacije koristi se službena reč extern ispred 9
Lokalne i globalne promenljive Lokalne i globalne promenljive korišćenje globalne promenljive u funkciji gde nije automatski vidljiva korišćenje globalne promenljive u funkciji gde nije automatski vidljiva kod nizova dovoljne samo zagrade, ne moraju dimenzije ako je deklaracija u nekoj funkciji, važi samo unutar funkcije ako je izvan funkcije važi do kraja datoteke redundantne deklaracije dozvoljene (na početku datoteke i u funkciji) Lokalne i globalne promenljive Lokalne i globalne promenljive globalni identifikatori spoljašnji (po standardu bar 6 značajnih slova) kad lokalna i globalna imaju isto ime važi lokalna u funkciji prenos podataka preko globalnih promenljivih efikasniji nego preko argumenata manje fleksibilan (svaki poziv obrađuje iste promenljive) 10
Lokalne i globalne promenljive /* primer prenosa podataka preko globalnih promenljivih */ /* jedna datoteka, 1 deo */ #include <stdio.h> #include <math.h> double x, y, r, fi; void polar (void) { extern double x, y, r, fi; /* redudantno */ r = sqrt(x*x+y*y); fi = (x==0 && y==0)? 0 : atan2(y,x);... Lokalne i globalne promenljive /* primer prenosa podataka preko globalnih promenljivih */ /* dve datoteka; prva datoteka */ #include <math.h> extern double x, y, r, fi; void polar (void) { extern double x, y, r, fi; /* redudantno */ r = sqrt(x*x+y*y); fi = (x==0 && y==0)? 0 : atan2(y,x);... Lokalne i globalne promenljive /* primer prenosa podataka preko globalnih promenljivih */ /* jedna datoteka, 2 deo */ main () { extern double x, y, r, fi; /* redudantno */ while (printf("x, y :"), scanf("%1f%1f",&x,&y), x!=1e38) { polar(); printf ("r, fi: %g,%g\n",r,fi); Lokalne i globalne promenljive /* primer prenosa podataka preko globalnih promenljivih */ /* dve datoteka; druga datoteka */ #include <stdio.h> double x, y, r, fi; void polar (void); main () { extern double x,y,r,fi; while (printf("x, y :"),scanf("%1f%1f",&x,&y),x!=1e38) { polar(); printf ("r, fi: %g,%g\n", r, fi); 11
Blokovska struktura programa Blokovska struktura programa svaka sekvenca se smatra blokom može ida definiše promenljive lokalne za blok i nevidljive izvan njega važe od mesta definicije do kraja bloka može i da definiše promenljive ako je ime isto sa globalnom promenljivom ova je nedostupna za blok globalna za sve blokove unutar tog bloka promenljive u obuhvatajućim blokovima globalne za njega Blokovska struktura programa Blokovska struktura programa #include <...> int i, j, k; // int i, j, k; char pp1 (...) { float a, b, i; // int j, k; float a, b, i; if (...) { int j, a, x; // int j, k, a, x; float b, i; for (..;..;..){ double a, j; // int k, x; float b, i; double a, j;... else { char j; // int k; float a, b, i; char j;... int e, h; // int i, j, k, e, h; char pp1;... 12... int e, h; // int i, j, k, e, h; char pp1; double pp2 (char k,...) { // int i, j, e, h; char pp1, k; char a, x, i; // int j, e, h; char pp1, i, k, a, x; { int h; // int j, e, h; char pp1, i, k, a, x;... { long h; // int j, e; char pp1, i, k, a, x; long h;... // int i, j, k, e, h; char pp1; double pp2; main () { float x, y, z, i; // int j, k, e, h; char pp1; double pp2; float x, y, z, i;...
Kategorije promenljivih Kategorije promenljivih prema načinu korišćenja globalne statičke automatske registri određuju se prefiksom u naredbi za definiciju promenljive globalne promenljive definišu se izvan funkcija njihova imena postaju jedinstvena za čitavi programski sistem ako je izvorni program u više datoteka, globalna promenljiva se: definiše samo u jednoj datoteci definiše sa extern u ostalim Kategorije promenljivih Kategorije promenljivih globalne promenljive statičke promenljive: postoje za čitavo vreme izvršavanja mogu se inicijalizovati početnjim vrednostima kao konstantnim izrazima ako se ne inicijalizuju, podrazumeva se 0 definišu se ili deklarišu sa static na početku postoje do kraja programa (vrednostise čuvaju između poziva) 13
Kategorije promenljivih Kategorije promenljivih statičke promenljive: statičke definisane izvan funkcija su lokalne za datoteku (vide se samo unjoj) statičke definisane unutar funkcije su lokalne za funkciju formiraju se na početku izvršavanja inicijalizuju se eksplicitno ili se smatra 0 automatske promenljive definišu se samo unutar funkcija ili blokova default za promenljive koje ne navode prefiks (extern, static ili register) eksplicitno sa auto Kategorije promenljivih Kategorije promenljivih automatske promenljive pri svakom pozivu se ponovo formiraju inicijalizacija izrazima koji mogu da sadrže promenljive, ali sa definisanim vrednostima ako nema eksplicitne početnje vrednsoti, onda slučajno registri automatske promenljive za koje se želi alokacija u registirma ne garantuje se prefiks register nedozvoljena primena adresnog operatora 14
Pretprocesor jezika C Pretprocesor jezika C vrši pripremnu obradu izvornog teksta programa posebne naredbe u posebnim redovima i počinju sa # vrši transformacije izvornog programa umetanje sadržaja tekstualne datoteke na određeno mesto zamena leksičkih simbola novim nizovima simbola uslovno uključivanje ili izostavljanje delova teksta Pretprocesor jezika C Pretprocesor jezika C umetanje sadržaja datoteke naredba #include sa zadatim imenom datoteke ako je ime između "" datoteka se trazi u istom katalogu kao i izvorni program ako se ne nađe ili je između <>, traži se u sistemskim katalozima umetanje sadržaja datoteke koristi se za duže sekvence deklarativnih naredbi npr. deklaracije bibliotečkih funkcija (zaglavlja - prototipovi) iz sistemskog kataloga 15
Pretprocesor jezika C Pretprocesor jezika C zamena leksičkih simbola naredba #define zamenjuje svako pojavljivanje identifikatora zadatim nizom simbola naredba #undef identifikator poništava efekt odgovarajuće #define naredbe za definiciju makroa iza identifikatora u zagradama može da bude niz argumenata odvojenih zarezima kao formalni argumenti koji se javljaju u nizu iza zagrada stvarni argumenti u daljem tekstu - proizvoljni nizovi simbola Pretprocesor jezika C Pretprocesor jezika C #define se može produžiti u naredni red akose nakraj stavi \ #define MAX_DUZ 1000 #define ZAUVEK for(;;) #define MAX(A,B) ((a)>(b)?(a):(b)) preporučuje se stavljanjezagrada oko svakog formiranog argumenta u makrou, jer stvarni argument može da sadrži operatore viših prioriteta npr. zamena pri pojavi: x=max(p+q, r+s); 16
Pretprocesor jezika C Rekurzivne funkcije uslovno prevođenje: #if izraz prevodi do #else ili #endif ako je izraz tačan #ifdef ime prevodi ako je ime prethodno def. sa #define #ifndef ime prevodi ako ime nije prethodno def. sa #define #else početak alternativnog bloka #endif kraj uslovnog bloka Funkcije koje indirektno ili direktno pozivaju same sebe svode se na rešavanje istog problema sa promenljivim parametrima da bi konvergirao, postoje neke specijalne nerekurzivne vrednosti funkcije Rekurzivne funkcije Rekurzivne funkcije pogodno za inherentno rekurzivne algoritme (npr. faktorijel, Fibonaccijevi brojevi,...) manje efikasna od iterativnih (po utrošku vremena ili memorije) otkrivanje grešaka teže nego kod iterativnih Rekurzivno izračunavanje faktorijela int fakt(int n) { return (n>0)? (n*fakt(n-1)):1; N+1 puta se poziva funkcija inicijalizuje formalni argument ispituje vrednost argumenta, oduzima i množi, uključući čuvanje i obnavljanje steka 17
Rekurzivne funkcije Pokazivači na funkcije Iterativno izračunavanje faktorijela int fakt (int n) { int i, f; for (i=f=1; i<=n; f*=i++); return f; mnogo efikasnije (nema poziva) funkcije su objekti na koje se može pokazivati sve uobičajene operacije su dozvoljene nad takvim pokazivačima Pokazivači na funkcije Pokazivači na funkcije standardne naredbe za definiciju promenljivih, npr. double (*pf)(float, int); pokazivač pf na funkciju tipa double sa argumentima tipa float i int double *f(float, int); prototip funkcije čija je vrednost pokazivač na objekte tipa double pri pozivu *f(x, n) prvo se poziva funkcija (zbog višeg prioriteta), a zatim indirektno adresiranje (*pf)(x, n) prvo indirektno adresiranje na pokazivač pf, a zatim poziv funkcije 18
Pokazivači na funkcije Pokazivači na funkcije identifikator funkcije sam za sebe (slično nizu) predstavlja pokazivač na tu funkciju npr. : ako je double fct(float, int); nakon pf = fct, pf pokazuje na funkciju fct pa (*pf)(x,n) poziva funkciju fct() Primer: /* program za tabeliranje realne funkcije realnog arg. */ #include <stdio.h> void tabela (double (*pf)(double), double x1, double x2, double dx) { double x; printf ("\n x f(x) \n"); for (x=x1; x<=x2; x+=dx) printf("%20.10lf%20.10lf\n", x, (*pf)(x));... Pokazivači na funkcije Pokazivači na funkcije /* glavni program za prikaz rada potrpograma */ main() { double x1, x2, dx, oscilac(double); printf("x1, x2, dx:"); scanf("%lf%lf%lf", &x1, &x2, &dx); tabela (oscilac, x1, x2, dx);... /* primer funkcije za tabeliranje */ #include <math.h> double oscilac (double x) { return exp(-0.1*x)*sin(x); Prvi argument potrpograma tabela pokazivač pf na funkciju koja se tabelira njen poziv sa (*pf)(x) 19
Argumenti glavnog programa Argumenti glavnog programa pri startovanju C programa, u istoj komandi OS mogu se predati parametri glavnom programu glavni program se iz OS-a poziva kao funkcija sa dva argumenta void main (const int argc, char * argv[]) argc -broj parametara u komandi uključujući i samu komandu argv -niz pokazivača dužine argc+1 na znakovne nizove (reči iz komande) poslednji pokazivač argv[argc] = NULL Argumenti glavnog programa Argumenti glavnog programa Npr. komanda echo /* program ia ispisivanje poruke na ekranu */ #include <stdio.h> main (int argc, char * argv[]) { int i; for (i=1; i<argc; i++) printf ("%s%c",argv[i], (i<argc-1)?(' '):('\n')); Pisanje funkcija po staroj notaciji unutar zagrada samo imena argumenata tipovi argumenata ispred tela u posebnim naredbama za funkcije bez argumenata se ne piše void prototip samo tip (ne i argumente) i piše se izvan funkcija 20
Funkcije sa promenljivim brojem argumenata Funkcije sa promenljivim brojem argumenata Pozvana funkcija sama mora otkriti broj i tipove prosleđenih argumenata Primer: scanf, printf mogu na osnovu formata prebrojati konverzije koje počinju sa % Dakle, obavezni argument mora sadržati informaciju koliko ima neobaveznih Funkcije sa promenljivim brojem argumenata Postoji alat za bezbedno dohvatanje neobaveznih argumenata Da bi se koristio, mora: #include <stdarg.h> Sadrži makroe: va_list, va_start, va_arg i va_end Funkcije sa promenljivim brojem argumenata Prvo se definiše pokazivač na prvi neobavezni argument: va_list pok_arg; Zatim se postavi početna vrednost pokazivača navođenjem imena pokazivača i imena poslednjeg obaveznog argumenta: va_start (pok_arg, posl_arg); Uzastopni neobavezni argumenti se dohvataju pozivajući: va_arg (pok_arg, tip); gde se za svaki navodi tip argumenta Završetak dohvatanja argumenta se označava naredbom: va_end (pok_arg); 21
Primer: zbir promenljivog broja argumenata Primer: zbir promenljivog broja argumenata #include <stdarg.h> int zbir (int n,...) { int s,i; va_list pa; va_start (pa,n); for (s=i=0; i<n; i++) s+=va_arg(pa, int); va_end(pa); return s; Bibliotečke funkcije #include <stdio.h> void main() { printf ( 1+2= %d\n, zbir(2,1,2)); printf ( 1+2+3= %d\n, zbir(3,1,2,3)); Funkcije za čitanje i pisanje znakova najviši prioritet operatora poredak izračunavanja argumenata proizvoljan standardne biblioteke (za često korišćene obrade) #include <ime_biblioteke> #include <stdio.h> za nizove znakova: printf() scanf() gets(s) puts(s) 22
Funkcije za čitanje i pisanje znakova Funkcije za ispitivanje znakova za pojedinačne znakove: #include <ctype.h> int getchar() vraća kod unesenog znaka ili konstantu EOF (za kraj datoteke ili grešku) int putchar(c) ispisuje znak na ekranu vrednost funkcije je kod ispisanog znaka ili EOF za grešku ispituju vrstu znaka tip argumenta c char vrednost funkcije logička vrednost Funkcije za ispitivanje znakova Funkcije za ispitivanje znakova isalnum (c) slovo ili cifra isalpha (c) slovo iscntrl (c) upravljački znak isdigit (c) decimalna cifra isgraph (c) štampajući znak (osim razmaka) islower (c) malo slovo isprint (c) štampajući znak uključujući razmak ispunct (c) specijalan znak isspace (c) beli znak isupper (c) veliko slovo isxdigit (c) hexa cifra 23
Funkcije za rad sa znakovnim nizovima Funkcije za rad sa znakovni nizovima #include <string.h> umesto operatora za rad sa znakovnim nizovima => standardne funkcije argumenti: t, s znakovni nizovi n - int Funkcije za rad sa znakovni nizovima strcpy (t, s) prepisuje niz s u niz t uključujući i završni znak vrednost funkcije: niz T strncpy (t, s, n) prepisuje najviše n znakova iz s u t ako ih je manje, dopunjava \0 do dužine n vrednost funkcije: niz t Funkcije za rad sa znakovnim nizovima strcat (t, s) dopisuje s na kraj t vrednost funkcije: niz t strncat (t, s, n) dopisuje najviše n znakova is s na kraj t vrednost funkcije: niz t strcmp (t, s) upoređuje nizove t i s (po vrednosti koda znakova) rezultat int: negativno => t ispred s pozitivno => s ispred t nula => t==s strlen (s) vraća dužinu niza (ne ubraja završni znak) rezultat int 24
Matematičke funkcije Matematičke funkcije #include <math.h> vrednosti funkcija double argumenti: x, y double n - int sin (x) cos (x) tan (x) asin (x) x iz [-1, 1] acos (x) x iz [-1, 1] atan (x) x iz [-π/2, π/2] atan2 (x, y) atan (x/y); x iz [-π, π] Matematičke funkcije Matematičke funkcije sinh (x) cosh (x) tanh (x) exp (x) - e x log (x) logaritam (osnova e) log10 (x) logaritam (osnova 10) pow (x, y) -x y sqrt (x) kvadratni koren ceil (x) najmanji ceo broj veći od x floor (x) najveći ceo broj manji od x fabs (x) apsolutna vrednost 25
Matematičke funkcije Uslužne funkcije ldexp (x, n) x*2 n frexp (x, &n) vraća normalizovanu mantisu od x u opsegu [0.5, 1) n vraća binarni eksponet modf (x, &y) vraća razlomljeni deo x (sa predznakom) y je celobrojni deo sa predznakom fmod (x, y) ostatak realnog deljenja x/y sa predznakom x #include <stdlib.h> funkcije različite namene rand () vraća pseudoslučajni int iz opsega [0, RAND_MAX] srand() postavlja početnju vrednost sekvence slučajnih brojeva (def. 1) Uslužne funkcije Uslužne funkcije atof (s) konverzija realnog broja iz znakovnog niza u double atoi (s) konverzija celog broja iz znakovnog niza u int atol (s) konverzija celog broja iz znakovnog niza u long int s znakovni niz preskaču se eventualni beli znaci sa početka niza zaustavlja se na prvom znaku koji nie deo broja abs (n) apsolutna vrednost tip rezultata i argumenta int labs (n) apsolutna vrednost tip rezultata i argumenta long int... 26