uvod u programiranje predavanja 6 i 7

Post on 04-Jan-2016

29 Views

Category:

Documents

8 Downloads

Preview:

Click to see full reader

DESCRIPTION

uvod u programiranje

TRANSCRIPT

Увод у програмски језик Увод у програмски језик CC

Функције

Електротехнички факултет у Источном Сарајеву

2

СадржајСадржај

1. Функције

2. Област важења и циклус трајања променљиве

3.3. Рекурзивне функцијеРекурзивне функције

4.4. Претпроцесорске наредбеПретпроцесорске наредбе

3

ФункцијеФункције

• Велики програм се дели на мање делове или модуле које је много лакше дефинисати и контролисати.

• Ти делови се називају потпрограми

• У програмском језику C сви потпрограми се називају функције.

4

Зашто функцијеЗашто функције

• Писање мањих целина које се лакше контролишу

• Примена функције као градивног елемента програма, - могућност да се једном написана функција користи у више различитих програма

• Понављање извршавања истог кôда у програму

5

Функције Функције

Потпрограми

Приликом развоја алгоритма могу се уочити логичке целине, односно поступци обраде које се често пута понављају, најчешће над различитим скупом података. Такве целине треба издвојити у посебне програмске целине - потпрограме.

Коришћењем потпрограма:повећава се прегледност, читљивост програма,смањује се величина програма,постиже се универзалност кода,омогућава се лакше отклањање грешака.

У програмским језицима обично се имплементирају:процедурални потпрограми (procedure)функцијски потпрограми (function)

Програмски језик C има имплементиране само функцијске потпрограме.

6

ФункцијеФункције

Функција се обично дефинише као потпрограм који на основу одређеног броја аргумената даје један резултат.

Податак који функција враћа главном програму или другој функцији назива се вредност функције.

Под типом функције подрсазумева се тип податка који враћа функција.

Процедурални потпрограми (у другим програмским језицима) могу да враћају више података (ниједан податак). Због тога, функције у C-у имају имплементирану могућност да осим резултата – вредност функције, врате више података кроз размену аргумената. Ефекет када функција крооз аргументе враћа резултате назива се бочни ефекат.

Функција може у потпуности да се понаша као процедура, односно може да даје само бочне ефекте.

7

Врсте функцијаВрсте функција

• C програм je најчешће комбинација два типа функција: – функција које пише сам програмер

(корисничке функције) и

– функција које постоје у стандардним библиотекама (библиотечке функције) као што су: printf, scanf, sin, malloc, free, и друге.

8

Особине ФункцијеОсобине Функције

• Функције у математици

• Тип функције (тип повратне вредности)

• Аргументи функције

• Тип аргумената функције

( ) 2 5f x x

9

Библиотечке функцијеБиблиотечке функције• Готове функције које постоје у оквиру програмског

језика

#include <math.h>#include <stdio.h>main(){ double y;

/* poziv bibliotečke funkcije*/ y = floor(2.8); printf( “Ceo deo od 2.8 je %f\n", y ); y = floor( -2.8 ); printf( “Ceo deo od -2.8 je %f\n",y );}

Ceo deo od 2.8 je 2.000000

Ceo deo od -2.8 je -3.000000

10

Корисничке функцијеКорисничке функције

• Функције које дефинише програмер

• Mогу се поделити у две категорије:– Функције које имају тип податка, тј.

функције које враћају неку вредност

– Функције које не враћају вредност и оне се називају воид (void) функције.

11

Функције које враћају вредностФункције које враћају вредност

• Својства функције :1. Име функције

2. Број аргумената функције

3. Тип податка сваког аргумента (формалног)

4. Тип повратне вредности, односно тип функције

5. Шта ради та функција, односно њен кôд.

12

Функције Функције

Дефиниција функције

Општи облик дефиниције функције:

tip ime (arg1, arg2, ... , argN)

definicija_formalnih_argumenata;

{

definicija_lokalnih_promjenljivih;

programski_iskazi;

return (izraz); }

Тип функције

Ако се не наведе подразумева се int

Ако функција не враћа податак, тип је void

Листа формалних аргумената Параметри кроз које функција

прима податке (вредности или адресе)

Дефиниција типова аргумената

Име функције Идентификатор у складу са синтаксом језика

Дефиниција локалних променљивих

Променљиве које се користе у функцији,

Нису видљиве изван функције

Излаз из функције и враћа вредност датог типа

У телу функције може бити више return исказа

Ако функција не враћа ништа, return може да се изостави.

13

Функције Функције

Дефиниција функције

Алтернативни облик дефиниције функције:

tip ime ( tip1 arg1, tip2 arg2, ... , tipN argN )

{ definicija_lokalnih_promjenljivih; programski_iskazi; return (izraz); }

Дефиниција типова аргумената садржана је у листи аргумената

Позивање функције

Општи облик позива функције:

ime ( sarg1, sarg2, ... , sargN )

Листа стварних аргумената Параметри који се шаљу у функцију

(вредности или адресе)Зову се стварни зато што су то

стварни, реални подаци

14

Функције које враћају вредностФункције које враћају вредност

• Заглавље и тело функције

int abs(int x) /* Zaglavlje*/

{

if(x < 0)

x = -x;

return x;

}

• Променљиве које су декларисане у заглављу функције се називају формални аргументи функције

15

Формални и стварни аргументиФормални и стварни аргументи

main(){ double u = 2.5; double v = 3.0; double x,y,z; x=stepen(u,v); /* Linija 1 */ y=stepen(2.0, 3.2); /* Linija 2 */ z=stepen(v,7); /* Linija 3 */ ...}

double stepen(double osnova, double eksponent){ ...}

Формални аргументи

стварни аргументи

16

Дефинисање функцијаДефинисање функција

• Општа синтакса за дефинисање функције је:tip_funkcije ime_funkcije(lista form argumenata)

{

naredbe

}

• Тело функције– Група наредби, део између витичастих заграда

– наредбе могу бити наредбе за дефинисање променљивих (декларативне наредбе) или извршне наредбе

17

Тип функцијеТип функције

• Представља тип вредности коју враћа функција.

• Назива се и тип повратне вредности (return type) функције.

• Уколико се изостави подразумева се тип int.

• За функције које не враћају вредност резервисан је тип void.

18

Тип функцијеТип функције

int ime_funkcije(lista form. argumenata)

double ime_funkcije(lista form. argumenata)

void ime_funkcije(lista form. argumenata)

19

Име функције Име функције

• Додељује се према правилима за доделу имена идентификатора.

• испред имена функције је могуће ставити *, што значи да је повратна вредност функције показивач на податке чији је тип наведен као tip_funkcije

double *treci_stepen(lista form. argumenata)

void *moja_funkcija(lista formalnih argumenata)

20

Листа формалних аргуменатаЛиста формалних аргумената

• Унутар малих заграда наводи се листа аргумената.• Потребно је навести тип податка и његово име.

• Уколико постоји више аргумената они се међусобно

раздвајају зарезом.

tip_funkcije ime_funkcije(tip_prom1 ime_prom1, tip_prom2 ime_prom2,... ,tip_promN ime_promN)

float funPrimer(int a, double b)

21

Листа формалних аргуменатаЛиста формалних аргумената

• Аргумената не мора бити али и у том случају се морају навести мале заграде.

tip_funkcije ime_funkcije()

• У случају да је листа формалних параметара празна, онда приликом позива те функције не треба наводити листу стварних аргумената.

ime_funkcije(); /* poziv*/

22

Наредба Наредба returnreturn

• Након што се унутар тела функције израчуна вредност коју функција треба да врати, та вредност се враћа помоћу наредбе return.

• Општи облик синтаксе за враћање вредности је return izraz;

• izraz може да буде променљива, константа или неки израз чијим израчунавањем се добија жељена вредност.

23

Наредба Наредба returnreturn

• Након извршења наредбе return функција се тренутно напушта, а контролу преузима део програма одакле је функција позвана.

• Наредба којом је позвана функција се „замењује” са вредношћу коју враћа функција, тј. са вредношћу поред наредбе return.

24

Наредба Наредба returnreturnfloat manji(float x,float y){ float pom; if(x<=y) pom=x; else pom=y; return pom;}

1

float manji(float x, float y){ if(x<=y)

return x; 2 else return y; }

float manji(float x, float y){

if(x<=y) 3 return x; return y; }

26

Прототип функцијеПрототип функције

• Идентификатор (име функције или променљиве) мора се декларисати пре прве употребе, (пре функције main)

• У пракси се обично прво пише функција main пре свих осталих корисничких функција.

• Овај проблем је могуће решити увођењем прототипа функције пре дефинисања било које функције (укључујући и функцију main)

27

Прототип функцијеПрототип функције

• Прототип функције представља заглавље функције (без навођења тела функције). Прототип функције је обавезно завршити са знаком тачка-зарез (;)

tip_funkcije ime_funkcije(lista formalnih arg.);

• Прототип за функцију manji је:

float manji(float x, float y);

• Није неопходно да се наведе име променљиве у листи аргумената, мора се навести тип аргумента.

float manji(float , float );

28

Прототип функцијеПрототип функције

Декларације функције (прототип)

Прототип или декларација функције представља њен ”опис за спољашњи свет”

Из прототипа се види како се комуницира са датом функцијом, јер садржи:

тип функције,име функције,типове (а може и имена) аргумената.

Општи облик прототипа је:

tip ime ( tip1, tip2, ... , tipN );

Пример:int zbir( int a, int b )

{ return (a+b); }

int zbir( int, int );

void poruka ()

{ printf(”Zdravo!”); }

void poruka ();

29

функцијефункције

Структура C програма

Уобичајена је следеће структура:

pretprocesorske direktive

prototip funkcija

main

definicija funkcija

Алтернативно је могуће и:

pretprocesorske direktive definicija funkcija main

Погодно када имамо мали број функција

Ако функција позива неку другу функцију, функција која се позива мора претходно бити дефинисана

Пример:

#include <stdio.h>

void poruka ();

main() { poruka(); }

void poruka () { printf(”Zdravo!”); }

30

vvoidoid функције функције

• Функције које не враћају вредност

• tip_funkcije који представља тип повратне вредности као и наредба return немају посебног значаја.

• У void функцијама се може користити наредба return али без израза поред ње, користи се за напуштање

функције пре њеног краја.

• void функције могу али не морају имати аргументе

31

Прослеђивање вредности аргуменатаПрослеђивање вредности аргумената

• Приликом позива функције у малим заградама се наводи листа аргумената. По начину преношења вредности, уопштено гледано, постоји две врсте аргумената :

1. Аргументи који се прослеђују преко вредности (value arguments)

2. Аргументи који се преносе помоћу адресе (reference arguments)

32

Пример 1:Пример 1:

Учитати дужине страница правоугаоника, а затим израчунати и исписати обим и површину. Обим треба да се рачунау функцији obim, а површина у функцији povrs.

#include <stdio.h>

float obim(float, float);

float povrs(float s1, float s2);

main(){ float a,b, o,p; printf(”Stranica a: ”); scanf(”%d”, &a); printf(”Stranica b: ”); scanf(”%d”, &b); o = obim(a,b); p = povrs(a,b); printf(”Obim : %7.3f\n”, o); printf(”Povrsina : %7.3f\n”, p);}

float obim (float x, float y) { return ( 2*x + 2*y ); }

float povrs (float c, float d) { return ( c*d ); }

Prototip funkcije obim

Navedeni samo tipovi argumenata

Prototip funkcije povrs

Navedeni tipovi i imena argumenata

Poziv funkcije obimPoziv funkcije povrs

Šalju se stvarni podaci a i b

Definicija funkcije obim

Funkcija prihvata proslijeđene vrijednosti (a i b) kroz formalne argumente x i y

Funkcija izračunava obim 2*x+2*y i to vraća u glavni program

33

Пример 2:Пример 2:

Функција која не враћа вредност:

#include <stdio.h>

void kvadrat ( int );

main(){ int i,n;

do { printf(”n = ”); scanf(”%d”, &n); } while (n<1);

for (i=1; i<=n; i++) kvadrat(i);}

void kvadrat (int k) { int kv; kv = k * k; printf(”%5d %5d\n”, k, kv); }

Функција kvadrat не враћа вредност (void)

Оваква функција понаша се као процедурални потпрограм

n = 4....1 ....1....2 ....4....3 ....9....4 ...16

34

Пример 3:Пример 3:Програм који исписује првих n простих бројева. Провера да ли је број прост врши се у функцији prost.

#include <stdio.h>#include <math.h>int prost (int);main(){ int i=1, broj=1, n; do { printf(”n = ”); scanf(”%d”, &n); } while (n<1); printf(”To su brojevi:\n”);

while (i<=n)

{

if ( prost(broj) )

{ printf(” %d”, broj); i++; }

broj++;

}

}

int prost (int b){ int d=3, pom; pom = (b%2) || (b==2); while (pom && d<=sqrt(b)) { pom = b%2; d += 2; } return(pom);

}

n = 6To su brojevi: 1 2 3 5 7 11

35

Пренос параметра у функцију преко ВРЕДНОСТИУ претходним примери кориштен је пренос параметра по ВРЕДНОСТИ:

1. приликом позива функције шаље се вредност • као стварни аргумент може да се наведе: име променљиве, нека константа или израз• израчунава се вредност израза и та вредност се шаље у функцију

2. функција прихвата послате вредности у формалне аргументе• формални и стварни аргументи морају да се слажу у:

броју, редоследу i типу• формални аргументи (променљиве) аутоматски настају приликом

уласка у функцију и преузимају прослеђене вредности

3. по изласку из функције формални аргументи аутоматски нестају

• аутоматски настају и нестају па се називају аутоматске променљиве

У функцији се формира слика стварних аргумената и користе се те слика, а не стравне променљиве из главног програма,

зато након изласка из функције променљиве у главном програму остају непромењене!!!

36

Пример 4:Пример 4:

Илустрација преноса параметара путем вредности.

#include <stdio.h>

void f (int);

main(){ int i=10; printf(”main: %d\n”,i);

f(i); printf(”main: %d\n”,i);

}

void f (int k){ printf(”f: %d\n”,k); k=20; printf(”f: %d\n”,k);

}

main: 10

MEMOРИJA

i10

k1020

f: 10f: 20main: 10

39

ПримерПример

• Након линије 3 извршена је иницијализација

Linija 4: Unutar funk. main num1=10, num2=15, ch=A

main

10

15

A

.

.

.

.

.

.

.

.

.

1200

add

1430

1620

ime

num1

num2

ch

main( ){ int num1, num2, char ch;

num1=10; /*L1*/

num2=15; /*L2*/

ch='A'; /*L3*/

40

main( ){ int num1, num2; char ch; num1=10; /* L1*/ num2=15; /* L2*/ ch='A'; /* L3*/ printf("Linija 4: ....); funJedan(num1, &num2, ch); /* L5*/

41

ПримерПример funJedan(num1, &num2, ch); /* L5 poziv*/

void funJedan(int a, int *b, char v)

{

int jedan;

...

10

1430

A

.

.

.

.

.

.

.

.

. ??

funJedan

.

.

10

15

A

.

.

.

.

.

.

.

.

.

1200

add

1430

1620

ime

num1

num2

ch

ime

a

b

v

jedan

main

42

void funJedan(int a, int *b, char v){ int jedan; jedan=a; /* L 9 */ a++; /* L10 */ *b=(*b)*2; /* L11 */ v='B'; /* L12 */ printf("Linija 13: Unutar funJedan a=%d, *b=%d, v=%c\n",a,*b,v);

}

43

ПримерПример

• У линији 9, након наредбе jedan=a;

a

b

v

jedan

num11200

num2

ch

funJedan main

10

15

A

.

.

.

.

.

.

.

.

.

10

1430

A

.

.

.

.

.

.

.

.

. 10

1200

14300

1620

44

void funJedan(int a, int *b, char v){ int jedan; jedan=a; /* L 9 */ a++; /* L10 */ *b=(*b)*2; /* L11 */ v='B'; /* L12 */ printf("Linija 13: Unutar funJedan a=%d, *b=%d, v=%c\n",a,*b,v);

}

45

ПримерПример

• Након линије 10 (а++):

10

15

A

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

11

1430

A

.

.

.

.

.

.

.

.

.

ime: а

ime: b

ime: v

ime: jedan 10

funJedan

46

void funJedan(int a, int *b, char v){ int jedan; jedan=a; /* L 9 */ a++; /* L10 */ *b=(*b)*2; /* L11 */ v='B'; /* L12 */ printf("Linija 13: Unutar funJedan a=%d, *b=%d, v=%c\n",a,*b,v);

}

47

ПримерПример

• Након наредбе *b=(*b)*2; у линији 11

10

30

A

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

11

1430

A

.

.

.

.

.

.

.

.

.

ime: а

ime: b

ime: v

ime: jedan 10

funJedan

48

void funJedan(int a, int *b, char v){ int jedan; jedan=a; /* L 9 */ a++; /* L10 */ *b=(*b)*2; /* L11 */ v='B'; /* L12 */ printf("Linija 13: Unutar funJedan a=%d, *b=%d, v=%c\n",a,*b,v);

}

49

ПримерПример

• Након наредбе v='B' у линији 12

10

30

A

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

11

1430

B

.

.

.

.

.

.

.

.

.

ime: а

ime: b

ime: v

ime: jedan 10

funJedan

50

void funJedan(int a, int *b, char v){ int jedan; jedan=a; /* L 9 */ a++; /* L10 */ *b=(*b)*2; /* L11 */ v='B'; /* L12 */ printf("Linija 13: Unutar funJedan a=%d, *b=%d, v=%c\n",a,*b,v);

}

а=11, *b=30, v=B

51

ПримерПример

• након извршавања наредбе у линији 13 напушта се функција funJedan и програм наставља да се извршава у линији L6 функције main

10

30

A

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

52

main( ){ int num1, num2; char ch; num1=10; /* L 1 */ num2=15; /* L 2 */ ch='A'; C /* L 3 */ printf("Linija 4: ....); funJedan(num1, &num2, ch); /* L 5 */ printf("Linija 6: Unutar...); funDva(&num2, 25, &ch); /* L 7*/ printf("Linija 8: ...);}

53

ПримерПримерfunDva(&num2, 25, &ch) /* L7 poziv */

void funDva(int *x, int y, char *w);

{

...

10

30

A

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

1430

25

1620

.

.

.

.

.

.

.

.

.

ime: x

ime: y

ime: w

funDva

54

void funDva(int *x, int y, char *w){ (*x)++; /* L14*/ y=y*2; /* L15*/ *w='G'; /* L16*/ printf("Linija 17: Unutar funDva *x=%d, y=%d, *w=%c\n",*x,y,*w);

}

55

ПримерПример

• Након извршавања наредбе у линији 14, (*x)++

10

31

A

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

1430

25

1620

.

.

.

.

.

.

.

.

.

ime: x

ime: y

ime: w

funDva

56

void funDva(int *x, int y, char *w){ (*x)++; /* L14*/ y=y*2; /* L15*/ *w='G'; /* L16*/ printf("Linija 17: Unutar funDva *x=%d, y=%d, *w=%c\n",*x,y,*w);

}

57

ПримерПример

• Наредба у линији 15 (y=y*2) даје следеће

10

31

A

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

1430

50

1620

.

.

.

.

.

.

.

.

.

ime: x

ime: y

ime: w

funDva

58

void funDva(int *x, int y, char *w){ (*x)++; /* L14*/ y=y*2; /* L15*/ *w='G'; /* L16*/ printf("Linija 17: Unutar funDva *x=%d, y=%d, *w=%c\n",*x,y,*w);

}

59

ПримерПример

• Након линије 16 (*w='G')

10

31

G

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

1430

50

1620

.

.

.

.

.

.

.

.

.

ime: x

ime: y

ime: w

funDva

60

void funDva(int *x, int y, char *w){ (*x)++; /* L14*/ y=y*2; /* L15*/ *w='G'; /* L16*/ printf("Linija 17: Unutar funDva *x=%d, y=%d, *w=%c\n",*x,y,*w);

}

*x=31, y=50, *w=G

61

ПримерПример

• Након завршетка наредбе у линији 17 напушта се функциа funDva и враћа се у линију 8 функције main.

10

31

G

.

.

.

.

.

.

.

.

.

main

ime: num2

ime: ch

ime: num1

adresa:14300

adresa:1200

adresa:16200

62

main( ){ int num1, num2; char ch; num1=10; /* L 1 */ num2=15; /* L 2 */ ch='A'; C /* L 3 */ printf("Linija 4: ....); funJedan(num1, &num2, ch); /* L 5 */ printf("Linija 6: Unutar...); funDva(&num2, 25, &ch); /* L 7*/ printf("Linija 8: ...); /* L 8*/}

63

ПримерПример

• Након линије 8 се прекида извршавање програма и ослобађа меморијски простор

nim1=10, num2=31, ch=G

64

Домени и меморијске класеДомени и меморијске класе

Домен идентификатора

Домен (област дефинисаности, област важења ) идентификатора (променљиве) је подручје програма у којем је тај идентификатор доступан по имену (видљив)

Основно правило:Идентификатор је доступан у блоку у којем

је дефинисан, као и у свим угњежденим блоковима, осим аку у њима није маскоран другим идентификатором са истим именом!

Пример:

#include <stdio.h>main(){ int x=1; printf(”Pre bloka: %d\n”,x); { int x=0; printf(”U bloku: %d\n”,x); } printf(”Posle bloka: %d\n”,x);}

Pre bloka: 1U bloku: 0Posle bloka: 1

У угњежденом блоку је

дефинисана променљива са истим именом,

чиме је маскирана променљива x iz funkcije main()

65

Домени и меморијске класеДомени и меморијске класеМеморијске класе променљивих

У програмском језику C разликујемо 4 меморијске класе променљивих:

• глобалне

дефинишу се изван свих функција

• статичке

дефинишу се помоћу кључне речи static static tip ime=vrednost

• аутоматске

дефинишу се помоћу кључне речи auto auto tip ime=vrednost

подразумева се да је променљива аутоматска, ако се другачије не наведе

• регистрске

дефинишу се помоћу кључне речи register register tip ime=vrednost

66

Домени и меморијске класеДомени и меморијске класе

Аутоматске променљиве

Аутоматске променљиве дефинишу се на почетку тела функције (главног програма или потпрограма). Често се користи термин локална променљива.

Почетна вредност им се не подразумева!!! (То значи није нула!!!)

Могу да се користе само у функцији у којој су дефинисане. То значи да исто име можемо да користимо независно у више различитих функција. Чак те променљиве могу да буду и различитих типова.

Аутоматски настају прилико уласка у функцију, и аутоматски нестају након изласка из функције.

Подразумева се да је променљива аутоматска ако се другачије не наведе.

Не мора се експлицитно наводити да се ради о аутоматској променљивој, али може помоћу речи auto

auto tip ime=vrednost;

67

Домени и меморијске класеДомени и меморијске класе

Рад са аутоматским променљивама.

#include <stdio.h>

void f1 () { int i=1; printf(”f1: %d\n”, i); }

void f2 () { int i=2; printf(”f2: %d\n”, i); i=10; }

main(){ int i=0; printf(”main: %d\n”, i); f1(); printf(”main: %d\n”, i); i=5; f2(); printf(”main: %d\n”, i);}

main: 0 f1: 1main: 0 f2: 2main: 0

68

Домени и меморијске класеДомени и меморијске класе

Статичке променљиве

• Дефинишу се навођењем кључне речи static static tip ime=vrednost

• Вредност им се одређује пре почетка извршавања програма • Узима се експлицитна вредност којом је иницијализована променљива.

Подразумева се да је почетна вредност нула, ако се другачије или ништа не наведе

• Имају трајан карактерПостоје у меморији од почетка до краја извођења програмаВредност остаје сачувана до следећег позива те функције

69

Домени и меморијске класеДомени и меморијске класе

Рад са астатичком променљивом.

#include <stdio.h>

void f () { static int brs=1; auto int bra=1; printf(”static brs=%d auto bra=%d\n”, brs, bra); brs++; bra++; }

main(){ int i; for (i=1; i<=3; i++) f();}

static brs=1 auto bra=1 static brs=2 auto bra=1 static brs=3 auto bra=1

70

Глобалне променљивеГлобалне променљиве

• Променљиве које су заједничке за већи број функција.

• Дефинишу се изван било које функције.

• Досег :од места где је дефинисан до краја фајла у ком се налази та наредба.

71

Глобалне променљивеГлобалне променљиве

• Функције које сачињавају програм не морају бити у једном фајлу.

• Скуп тих фајлова: пројекат.

• Сваки фајл унутар пројекта се преводи независно.

• Након успешног превођења врши се повезивање (linking) преведених фајлова у извршни програм.

72

Глобалне променљивеГлобалне променљиве

• Глобални идентификатори могу имати досег на све фајлове у пројекту.

• У сваком од фајлова треба да постоји декларација глобалног податка или функције која ће се у њему користити.

• У тачно једном од фајлова дефиниција.• У сваком фајлу у ком се користи

глобална променљива дефинисана у другом фајлу мора постојати тзв. екстерн (extern) декларација.

73

Домени и меморијске класе - Домени и меморијске класе - Глобалне променљивеГлобалне променљиве

Глобалне променљиве дефинишу се изван свих функција. Ако се у дефиницији не наведе почетна вредност подразумева се нула!!!

Глобална променљива доступна је у свим функцијама које су дефинисане након дефиниције дате променљиве.

Глобалне променљиве омогућавају да више функција манипулише истим скупом података, па самим тим омогућавају ефикасну размену података између функција (јер све функције приступају истим меморијским локацијама).

74

Домени и меморијске класе - Домени и меморијске класе - Глобалне променљивеГлобалне променљиве

Треба их избегавати јер се губи универзалност функције и флексибилност примене на различите сетове података.

Ако се у некој функцији дефинише променљива са истијм именом као нека глобална, тада та локална променљива маскира глобалну и глобалној се не може приступити из те функције.

Ако се у некој функцији користи нека глобална променљива то може да се експлицитно нагласи декларацијом коришћењем кључне речи extern, иако не постоји обавезада се глобалне променљиве декларишу у функцији

extern tip promjenljiva;

75

Домени и меморијске класеДомени и меморијске класе

Рад са глобалним променљивимРад са глобалним променљивим#include <stdio.h>

void f1 () { int i=1; printf(”f1: %d\n”, i); }

int i;

void f2 () { extern int i; printf(”f2: %d\n”, i); i=10; }

main(){ printf(”main: %d\n”, i); f1(); printf(”main: %d\n”, i); i=5; f2(); printf(”main: %d\n”, i);}

main: 0 f1: 1main: 0 f2: 5main: 10

Глобална променљива

i=0

Глобална променљива i није видљива у функцији f1() јер је дефинисана након функције.

У функцији f1() расположива је локална променљива i.

У функцији f2() користи се глобална, екстерна променљива i.

Декларације extern int i могла је да се изостави

76

Глобалне променљивеГлобалне променљиве

FILENAME1.c 1 extern int brojac; 2 int rezultat=2; 3 void funkcija_1(); 4 int main() 5 { 6 int i= 4; 7 printf("M3: %d, %d\n", brojac, rezultat); 8 rezultat++; 9 brojac=rezultat*i;10 printf("M6: %d, %d\n", brojac, rezultat);11 funkcija_1(); 12 printf("M8: %d, %d\n", brojac, rezultat);13 return 0;14 }

77

Глобалне променљивеГлобалне променљиве

FILENAME2.c 1 extern int rezultat;

2 int brojac = 0

3 void funkcija_1()

4 {

5 printf("F1: %d %d\n", brojac,rezultat);

6 rezultat=5;

7 brojac=1;

8 printf("F4: %d %d\n", brojac, rezultat);

9 return;

10 }

78

Домени и меморијске класеДомени и меморијске класе

Регистарске променљиве

Registarske promjenljive su automatske promjenljive za koje je izražena želja da se drže u registrima procesora, a ne u memoriji, kako bi se dobilo na brzini.

Poželjno je korišćenje registarskih promjenljivih kod promjenljivih koje se često koriste (npr. brojač)

Ne garantuje se da će promjenljiva stvarno i biti registarska. To zavisi i od konkretnog prevodioca, procesora , ukupnog broja registarskih promjenljivih do trenutka deklaracije date promjenljive...

Broj registarskih promjenljivih je ograničen i malen.

Registarske promjenljive definišu se uz pomoć ključne riječi registerregister tip ime=vrijednost

Primjer:register int i=10;register j;

79

Вектор (поље) као аргумент Вектор (поље) као аргумент функцијефункције

Пренос вектора (поља) врши се путем адресе

1. приликом позива функције шаље се адреса низа (вектора) • као стварни аргумент наводи се име низа (име низа је почетна адреса низа) 2. функција прихвата адресу низа • формални аргумент у дефиницији функције мора да садржи [ ]

број елемената низа не мора да се наводи • не ствара се копија низа већ се ради са стварним подацима

У функцији се манипулише стварним подацима, а не копијом низа. Зато функција може да промени низ, па по повратку из функције немамо оригинални него

модификовани низ !!!

80

Пример 5: Вектор као аргумент Пример 5: Вектор као аргумент функцијефункције

Програм учитава низ, позива потпрограм који проналази и враћа највећи елемент низа, који се штампа у програму.

#include <stdio.h>

int max ( int niz[], int n);

main(){ int a[] = { 2,15,5,0,8 }; int n = 5; printf(”Najveci: %d\n”, max( a,n ) );

}

int max ( int niz[], int n ){ int i, m=niz[0]; for (i=1; i<n; i++) if (niz[i]>m) m=a[i]; return (m);

}

Najveci: 15

Формални аргумент

Декларација низа без димензије

Могло је и int niz[5]

Позив функције

Шаље се адреса низа

81

Пример 6: Вектор као аргумент Пример 6: Вектор као аргумент функцијефункције

Програм позива функције за сортирање и исписивање низа.

#include <stdio.h>

void sort ( int niz[], int n);void pisi ( int niz[], int n);

main(){ int a[] = { 2,15,5,0,8 }; printf(”Pre:”); pisi( a,n ); sort( a,n ); printf(”Posle:”); pisi( a,n ); }

void pisi ( int niz[], int n ){ int i; for (i=0; i<n; i++) printf(” %d”, niz[i]); printf(”\n”); }

void sort ( int niz[], int n ){ int i,j,rb,pom; for (i=0; i<n-1; i++) { for (rb=i, j=i+1; j<n; j++) if (niz[j]<niz[rb]) rb=j; if (rb!=i) { pom=niz[i]; niz[i]=niz[rb]; niz[rb]=pom; } }}

Pre: 2 15 5 0 8Posle: 0 2 5 8 15

82

Вишедимензионално поље као Вишедимензионално поље као аргумент функцијеаргумент функције

Пренос вишедимензионалног поља врши се путем адресе

У декларацији формалних аргумената:

• прва димензија не мора да се наведе (може само [ ] )

• остале димензије морају да се наведу

Пример:

int funkcija (int a[][10][10], int p, int q)

или

int funkcija (int a[10][10][10], int p, int q)

У функцији се ради са стварним подацима,а не са копијом поља. Зато по повратку из функције поље

може бити модификовано !!!

83

Пример 7: Поље као аргумент Пример 7: Поље као аргумент функцијефункције

Програм позива потпрограме за испис и транспоновање матрица.

#include <stdio.h>

void tran ( int m[10][10], int n);void pisi ( int m[10][10], int n);

main(){ int a[10][10] = { {1,2},{3,4} }; printf(”Pre:\n”); pisi(a,n); tran( a,n ); printf(”Posle:\n”); pisi(a,n); }

void pisi (int m[10][10], int n){ int i,j; for (i=0; i<n; i++) { for (j=0; j<n; j++) printf(” %4d”, m[i][j]); printf(”\n”); }}

void tran (int m[10][10], int n){ int i,j,pom; for (i=0; i<n; i++) for (j=i+1; j<n; j++) { pom=m[i][j]; m[i][j]=m[j][i]; m[j][i]=pom; } }}

Pre: 1 2 3 4Posle: 1 3 2 4

84

Рекурзивне функције

85

Рекурзивне функцијеРекурзивне функције

• Функције које могу да позову саме себе

• Своде сложен проблем на једноставнији проблем (исте природе) који могу да реше.

86

Рекурзивне функцијеРекурзивне функције

• Пример: рачунање факторијела n! =n*(n-1)*(n-2)*(n-3)*...*1

1! = 1

0! = 1

4! = 4*3*2*1=4*(3*2*1) = 4*(3!)

3! = 3*2*1=3*(2*1) = 3*(2!)

2! = 2*1=2*(1) = 2*(1!)

1! = 1

87

Рекурзивне функцијеРекурзивне функције

long faktorijel(long broj);

main(){ ... faktorijel(4); ...}

long faktorijel(long broj){ if( broj <= 1 ) return 1; else return (broj * faktorijel(broj - 1) ); }

88

Рекурзивне функцијеРекурзивне функције

broj=4зато што je broj>1 return (4*faktorijel(3));

faktorijel(4)

broj=3зато што je broj>1 return (3*faktorijel(2));

faktorijel(3)

broj=2зато што je broj>1 return (2*faktorijel(1));

faktorijel(2)

broj=1

return (1);

faktorijel(1)

2*1=2

3*2=6

4*6=24

89

Рекурзивне функцијеРекурзивне функције

Rekurzivne funkcije (REKURZIJE)

Rekurzivna funkcija je funkcija koja sama sebe poziva!!!

Primer:

faktorijel: n! = n * (n-1)!, n>0; 0!=1

stepenovanje: xn = x * xn-1, n>0; x0=1

Fibonačijev niz: fn = fn-1 * fn-2, n>1; f0=0, f1=1

Opšte karakteristike rekurzivnih (rekurentnih) rješenja:

• problem se svodi na rešavanje istog problema, ali jednostavnijeg

• funkcija poziva samu sebe sve dok se problem ne pojednostavi do trivijalnog

• rekurzivna rešenja su manje efikasna (veći zahtjev za memorijom)

• treba ih izbjegavati, ali postoje problemi koji su po prirodi rekurzivni i koje je gotovo nemoguće rešiti bez rekurzije

90

Рекурзивне функцијеРекурзивне функције

Matematički opis rekurzije:

n! = n * (n-1)!, n>0; 0!=1

Primer: Rekurzivno izračunavanje faktorijela.

3! = 3 * 2!

2! = 2 * 1!

1! = 1 * 0!

0! = 1

1*1 = 1

2*1 = 2

3*2 = 6

int fakt (int n){ if (n == 0) return (1); else return (n * fakt(n-1));}

int fakt (int n){ return (n==0 ? 1 : n*fakt(n-1));}

91

Рекурзивне функцијеРекурзивне функције

Primer: Rekurzivna funkcija za konverziju dekadnog u binarni brojni sistem.

1410 = ?2

void kon (int b){ int cif; cif = b % 2; b /= 2; if (b>0) kon (b); printf(”%d”,cif); }

19 : 2

9 1

4 1

2 0

1 0

0 1

1410 = 100112

19cif=1b=9kon(9) => cif=1 b=4

kon(4) => cif=0 b=2

kon(2) => cif=0 b=1 kon(1) => cif=1

b=0”1”

”0” <= ”0” <=

”1” <= ”1” <=

92

ПретпроцесорПретпроцесор

• Уметање садржаја фајла (наредба #include)

• Замена лексичких симбола (наредба #define)

– Дефинисање симболичких константи

– Дефинисање макро-а

• Условно превођење (наредба #if, #ifdef, ...)

93

ПретпроцесорПретпроцесор

• Претпроцесорске наредбе не представљају део програмског језика C

• Претпроцесор је део преводиоца који треба да изврши предобраду кôда.

• Обавља одговарајуће трансформације текста којима се добија коначан облик изворног кôда који треба да буде преведен.

94

ПретпроцесорПретпроцесор

• Претпроцесорска наредба се пише у засебном реду и почиње са знаком #.

• Испред ње не могу бити друге наредбе.

• Пре превођења замењује текст у изворном кôду.

95

ПретпроцесорПретпроцесор

• Претпроцесорске наредбе се не завршавају знаком ;

• Могу да се уведу на било ком месту у програму.

• Дејство: од појављивања па надаље, док се посебном наредбом не укину или до краја програма.

96

ПретпроцесорПретпроцесор

• Неке од важнијих претпроцесорских наредби које препоручује АNSI стандард су следеће:

#include#define#if#ifdef#ifndef#elif#else#endif#undef

97

Уметање садржаја фајлаУметање садржаја фајла

Наредба #include#include ″ime fajla″

#include <ime fajla>

• Тражени фајл може и сам да садржи наредбу #include.

98

Замена лексичких симболаЗамена лексичких симбола

Наредба #define

• Користи се за дефинисање симболичких константи и макро-а.

#define SIMBOLICKA_KONSTANTA ZnakovniNiz

Пример:#define PI 3.1415926#define NASLOV "Programski jezik C"#define ZAUVEK for( ; ; )

99

Дефинисање симболичке константеДефинисање симболичке константе

• Претпроцесор претражује изворни кôд и након појављивања наредбе облика

#define SIMBOLICKA_KONSTANTA ZnakovniNiz

свако појављивање SIMBOLICKA_KONSTANTA замењује са ZnakovniNiz.

• у коментару или унутар неког другог знакованог низа неће доћи до замене.

100

Дефинисање симболичке константеДефинисање симболичке константе

#include<stdio.h>#define PI 3.1415926

main(){ float a; float r=4.23; char ch[ ]="PILICI"; /* slogovi PI LI CI */ /*L3*/ a=2*r*PI; /*L5*/ printf("Niz ch je %s a obim a je %f\n ",ch,a);} ИзлазNiz ch je PILICI a obim a je 26.577874

101

Дефинисање симболичке константеДефинисање симболичке константе

#include <stdio.h>#define WIDTH 80 /* L1 */#define LENGTH ( WIDTH + 10 ) /* L2 */ main(){ int var; var = LENGTH * 20; /* var=(80+10)*20;*/ printf("var=%d\n",var) ...}var=1800

102

Дефинисање симболичке константеДефинисање симболичке константе

• Значење претпроцесорске наредбе #define SIMBOLICKA_KONSTANTA

се може укинути наредбом:

#undef SIMBOLICKA_KONSTANTA

103

Дефинисање симболичке константеДефинисање симболичке константе

include <stdio.h>#define WIDTH 80main(){ int x=2,y; y=WIDTH*x; printf("Vrednost y=%d\n",y); #undef WIDTH y=WIDTH; /* GRESKA! 'WIDTH':undeclared identifier */}

104

Дефинисање макро-аДефинисање макро-а

#define IME(par_a, par_b,...) Zakovni_niz

• Макро-и су веома слични функцијама,начин њиховог коришћења и извршавања је различит.

• Макро-и се замењују пре превођења програма

• Функције постоје и за време извршавања програма.

105

Дефинисање макро-аДефинисање макро-а

#include<stdio.h>#define MAX(a,b) a>b ? a : b

main()

{

int broj_a, broj_b;

printf("Odredjivanje maksimuma\n\n");

printf("Upisite dva broja\n");

scanf("%d %d",&broj_a,&broj_b);

printf("Veci broj je: %d\n", MAX(broj_a,broj_b));

}

Odredjivanje maksimuma

Upisite dva broja

4,9

Veci broj je: 9

107

Условно превођењеУсловно превођење

Наредба #if, #ifdef, #ifndef... • Основна наредба за почетак условног превођења :

#if uslov

• Ако услов није испуњен,

део кôда иза наредбе #if uslov неће бити преведен.

108

Условно превођењеУсловно превођење

#define VERZIJA 1.1

#define TESTIRANJE

#ifdef TESTIRANJE

#ifndef TESTIRANJE

109

Условно превођењеУсловно превођење

• Правила употребе #if, #ifdef и #ifndef• Свака од ових наредби се мора завршити

наредбом #еndif.

• Између ове две наредбе може постојати произвољан број #еlif наредби и највише једна #еlse наредба.

• Уколико постоји #еlse наредба она мора бити последња претпроцесорска наредба пре наредбе #еndif.

110

Условно превођењеУсловно превођење

#define TST #define DAN 2main(){ #ifdef TST int a=5; #endif #if (DAN==1)

printf("Ponedeljak\n"); #elif (DAN==2)

printf("Utorak\n"); #else

printf("Nije pon. ni utorak\n"); #endif

#ifdef TST

a=a+7;

printf("a= %d\n",a);

#endif

printf("DAN je %d“,DAN);

}

Utorak

a= 12

DAN je 2

111

Условно превођењеУсловно превођење#define DAN 2main(){ #ifdef TST int a=5; #endif #if(DAN = = 1) printf("Poned.\n"); #elif(DAN = = 2)

printf("Utorak\n"); #else

printf("Nije poned. ni utorak\n"); #endif

#ifdef TST

a=a+7;

printf("a= %d\n",a);

#endif

printf("DAN je %d“ ,DAN);

}

Utorak

DAN je 2

112

Хвала на пажњи

Питања?

top related