59
Programiranje I - II deo, ˇ sk. 2008/09. g. dr Gordana Pavlovi´ c-Laˇ zeti´ c

dr Gordana Pavlovi´c-Laˇzeti´c - poincare.matf.bg.ac.rspoincare.matf.bg.ac.rs/~maricm/p1/1Finale2.pdf · U ovoj taˇcki bi´ce izloˇzen kratki pregled programskog jezika C, i

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Programiranje I - II deo, sk. 2008/09. g.

dr Gordana Pavlovic-Lazetic

5

Pregled programskog jezikaC

U ovoj tacki bice izlozen kratki pregled programskog jezika C, i to kroz prikaznjegovih osnovnih karakteristika, i kroz poredenje sa svojstvima programskog jezikaPascal.

5.1 Filozofija jezika

Programski jezik C je mali jezik (kao i Pascal) i moze jednostavno da se implemen-tira na malim masinama.

Programski jezik C potice od jezika BCPL i B, koji su korisceni za pisanjeoperativnih sistema i jezickih procesora. Ovi jezici obezbeduju efikasan interfejsprema tehnickom sistemu racunara (hardveru), nisu tipizirani i omogucuju razliciteinterpretacije jednog podatka. Osnovni doprinos C-a, u odnosu na ove jezike, jesutipizirane promenljive.

Programski jezik C implementiran je 1972. godine (Dennis Ritchie), kao jezik zaprogramiranje aplikacija pod UNIX operativnim sistemom na DEC PDP-11 serijiracunara. Godine 1977. izgradena je verzija programskog jezika C (Portable Ccompiler) nezavisna od vrste racunara, koja je omogucila prenosivost programanapisanih u C-u.

S obzirom na svoju filozofiju i namenu, programski jezik C blizak je operaci-jama masinskog nivoa, omogucuje rad sa pojedinacnim bitovima i memorijskimadresama, fleksibilan je. Ova fleksibilnost i odsustvo restrikcija cini ga primenljivimu raznovrsnijim (u odnosu na Pascal) domenima programiranja. Takode, u odnosuna Pascal, a bas zbog odsustva restrikcija (npr. stroge tipiziranosti) i malog brojatipova, programi napisani u programskom jeziku C su manje pouzdani i teze citljivinego programi napisani u programskom jeziku Pascal.

Dok je cilj izgradnje programskog jezika Pascal bio razvoj pouzdanih pro-

39

40 5. Pregled programskog jezika C

grama primenom strogih ogranicenja jezika, pomoc pri otkrivanju gresaka ionemogucenje pristupa memorijskim lokacijama izvan zone podataka (otuda i nje-gova ogranicenja), dotle je programski jezik C osloboden mnogih ogranicenja kakobi bio primenljiv u sirokom spektru aplikacija. Jezik je mali i ne ukljucuje svojstvakao sto su ulaz/izlaz, matematicke (elementarne) funkcije – sin, cos, exp, itd., alise ove komponente ”ugraduju” u C iz odgovarajucih biblioteka.

Osnovna razlika izmedu programskog jezika C i Pascal-a je upravo tretmantipova. Pascal je nastao od svojih tipiziranih prethodnika (Algol60, AlgolW), iveoma je blizu tzv. strogo tipiziranim jezicima. Pri tome se stroga tipiziranostkarakterise sledecim principima:

1. Svaki objekat u jeziku pripada tacno jednom tipu.

2. Konverzija tipova se odvija konvertovanjem vrednosti iz jednog tipa u drugi,tj. transformacijom reprezentacije vrednosti a ne razlicitom interpretacijomiste reprezentacije.

Programski jezik C, mada je tipiziran (ima tipove), nije strogo tipiziran jezik.Stroga tipiziranost povecava jasnocu programa i pouzdanost. Programski jezik C,kao deo svoje filozofije, pruza programeru slobodu interpretacije iste reprezentacije(u slucaju unije i komponenti strukture, prenosa parametara, pokazivaca).

Nedostaci stroge tipiziranosti Pascal-a ogledaju se, na primer, u strogom dimen-zionisanju nizova i nemogucnosti izgradnje procedura za rad sa nizovima razlicitihdimenzija; slaba tipiziranost C-a dopunjuje se strozim tipovima u novijim verzijamajezika.

S druge strane, a u vezi sa tipovima, ovi jezici se razlikuju po opsegu implicitnekonverzije tipova: u Pascal-u se implicitno mogu transformisati samo podintervalniu odgovarajuce osnovne tipove, i ceo u realni tip – to su konverzije kojima se negubi informacija; u C-u moze da se izvrsi implicitna konverzija izmedu bilo kojadva njegova osnovna tipa ili pokazivaca.

5.2 Struktura programa

Sledeca svojstva karakterisu strukturu programa na programskom jeziku C:

1. Program moze da se sastoji od veceg broja rutina (potprograma) koje senalaze u vecem broju izvornih datoteka (program u Pascal-u sastoji se odzaglavlja i tela programa i tacke; telo programa sastoji se od odeljaka zadeklarisanje obelezja, definisanje konstanti, definisanje tipova, deklarisanjepromenljivih, deklarisanje rutina (procedura i funkcija), i odeljka sa iskazima).

2. Jedna izvorna datoteka sastoji se od spoljasnjih (external) objekata – po-dataka i funkcija (to su podaci koji su definisani izvan funkcija a sve funkcijesu spoljasnje) i koji mogu biti deklarisani kao lokalni za tu datoteku (to su

5.2. Struktura programa 41

staticki –”static” objekti) ili globalni za sve datoteke tog programa. Dakle,vazenje imena (objekata) vezano je za fizicku datoteku, a ne za blok ili rutinu(u Pascal-u vaze normalna pravila vazenja objekata u blokovskim strukturnimjezicima; objekti su lokalni za rutine – procedure i funkcije u kojima su deklar-isani, a globalni za rutine sadrzane (deklarisane) u rutini u kojoj je objekatdeklarisan). Jedan spoljasnji objekat dostupan je svim funkcijama u istojizvornoj datoteci koje slede za definicijom tog objekta. Pristup spoljasnjimobjektima definisanim u jednoj izvornoj datoteci, od strane funkcija iz drugedatoteke, postize se navodenjem deklaracije ”external” koja samo navodi imei tip ali ne rezervise memorijski prostor.

3. Svi izvrsni iskazi sadrzani su u blokovima koji mogu da budu ugnjezdenido proizvoljne dubine. Promenljive mogu da budu deklarisane na pocetkubilo kog bloka (i vide se samo u tom bloku). Svaki iskaz zavrsava se tacaka-zapetom (;), a blokovi su uokvireni zagradama ({, }) (u Pascal-u iskazi se razd-vajaju tacka-zapetom, a blokovi se ”uokviruju” rezervisanim recima BEGIN–END; promenljive se uvode samo na pocetku rutine odnosno programa).

4. Vecina izvornih datoteka C-programa pocinje uvodnim delom sa tzv. prepro-cesorskim instrukcijama. Standardni uvodi ukljucuju se sredstvima prepro-cesora. Preprocesorska instrukcija pocinje znakom #.

5. Po konvenciji, svaki program ima funkciju main kojom pocinje izvrsavanje.

6. Sve C-ovske rutine (potprogrami) su funkcije. Svaka funkcija moze da vracavrednost, koja moze biti bilo kog tipa osim nizovskog (u Pascalu rutine su pro-cedure – koje ne vracaju vrednost i funkcije – koje vracaju vrednost skalarnogili pokazivackog tipa). C-ovske rutine navode se jedna za drugom unutar jedneizvorne datoteke, dok u Pascal-u mogu biti ugnjezdene (lokalne – deklarisanejedna unutar druge). Zato C nije blokovski jezik u punom smislu dok Pascaljeste.

7. Parametri funkcija prenose se po vrednosti, osim za nizove. Vrednost ni-zovskog parametra je adresa prvog elementa niza (u Pascal-u, parametri seprenose po vrednosti ili po imenu).

8. Izvrsavanje funkcije zavrsava se posle izvrsenja poslednjeg iskaza funkcije,ili posle izvrsenja return iskaza. Funkcija ne mora da izracunava (i vraca)vrednost, a ako to cini, onda se iskaz return koristi i za vracanje vrednostifunkcije (u Pascal-u, izvrsavanje rutine – procedure ili funkcije, zavrsava seizvrsenjem poslednjeg iskaza; svaka funkcija vraca vrednost ciji tip se deklariseu zaglavlju deklaracije funkcije, i koja se dodeljuje imenu funkcije).

9. Komentari se pisu izmedu para oznaka ”/∗”, ”∗/” (u Pascal-u, izmedu zagrada”{”, ”}”).

42 5. Pregled programskog jezika C

5.3 Primer programa

Da bismo ilustrovali strukturu programa na programskom jeziku C (i uporedili jesa strukturom programa na jeziku Pascal), razmotrimo primer funkcije za binarnopretrazivanje. Funkcija uzima niz slogova sortiranih po kljucnom polju i trazi slogsa zadatom vrednoscu kljucnog polja; vraca indeks sloga cija je vrednost kljucnogpolja jednaka trazenoj, ako takav postoji, i indikator neuspeha, u suprotnom. Akosu slogovi u nizu A a vrednost kljuca koja se trazi u promenljivoj k, algoritam mozeimati sledeci oblik:

1. Postaviti l na najmanji indeks a d na najveci indeks niza A.

2. Dok je l ≤ d, ponoviti korake 3–5. Ako je l > d, vratiti neuspeh.

3. Postaviti s na indeks na sredini izmedu l i d.

4. Ako je kljuc sloga As jednak k, vratiti s.

5. Ako je kljuc sloga As manji od k, postaviti l na s + 1, inace postaviti d nas− 1.

Ovaj algoritam se u C-u moze zapisati funkcijom BinarPret koja ima tri ar-gumenta – niz slogova A, broj slogova n i kljuc k koji se trazi. Funkcija vracacelobrojnu vrednost – indeks sloga sa kljucem k, ako takav postoji, ili −1 ako takavslog u nizu A ne postoji. Program ima sledeci oblik:

#include <stdio.h>#define NEUSPEH −1#define MAXELEM 100

typedef struct {int kljuc;char ∗vrednost;

} slog;slog A[MAXELEM];int BinarPret(slog A[ ], int n, int k);

main(){

int i,n,x;

printf(”unesi broj elemenata i celobrojne elemente niza u rastucemporetku\n”);

scanf(”%d”, &n);for(i=0;i<n; )

scanf(”%d”, &(A[i++].kljuc));printf(”unesi celobrojnu vrednost kljuca koji se trazi\n”);scanf(”%d”, &x);

5.3. Primer programa 43

printf(”indeks trazenog elementa je %d”, BinarPret(A,n,x));}int BinarPret(slog A[ ], int n, int k)/∗ vraca indeks elementa niza A sa kljucem k,

vraca NEUSPEH ako k nije u A ∗/{

int l=0, d=n-1,s;while(l <= d) {

s = (l + d)/2;if(k < A[s].kljuc) d=s-1;else if(k > A[s].kljuc) l=s+1;else return(s);

}return(NEUSPEH);

}

Struktura tipa slog ima polja kljuc i vrednost, pri cemu se polje kljuc koristi zaporedenje, a polje vrednost se i ne koristi – ono je prisutno kao predstavnik drugihinformacija koje se pamte o pojedinom slogu.

U Pascal-u, isti algoritam moze se zapisati istoimenom funkcijom BinarPretkoja koristi globalne objekte uvedene sledecim definicijama i deklaracijama:

const max = 100;neuspeh = -1;

type indeks = 1..max;string = packed array[1..20] of char;slog = record

kljuc: integer;vrednost: string;

end;podaci = array[1..max] of slog;

Deklaracija funkcije u Pascal-u ima sledeci oblik:

function BinarPret(var A:podaci; n:indeks; k:integer):integer;

var l,s,d:indeks;rezultat:integer;

beginl:=1;d:=n;rezultat:=neuspeh;while (l<=d) and (rezultat = neuspeh) dobegin

s:=(d+l) div 2;if k< A[s].kljuc then

44 5. Pregled programskog jezika C

d:=s-1else if k> A[s].kljuc then

l:=s+1else

rezultat:=send;BinarPret:=rezultat

end

5.4 Preprocesor C-a

U prethodnom primeru, program na C-u pocinje linijama kojima prethodi znak #. To su instrukcije procesoru ciji ”rad” prethodi prevodenju programa sa C-a namasinski jezik – tzv. preprocesoru.

Postoje tri vrste preprocesorskih instrukcija (sve pocinju znakom #): zamenastringova instrukcijom # define (u nasem primeru string ”NEUSPEH” zamenjujese, gdegod se pojavi u programu, stringom ”−1”), ukljucivanje teksta, obicno tek-stuelne datoteke koja sadrzi standardni skup deklaracija, tzv. standardno zaglavlje,instrukcijom # include (u nasem primeru na pocetak programa ukljucuje se tek-stuelna datoteka stdio.h), i instrukcije za uslovnu kompilaciju (kasnije o njima).

5.5 Tipovi podataka

Deklaracija promenljivih u C-u ima oblik

vrsta tip lista-promenljivih

gde je vrsta – oznaka memorijskog prostora i trajnosti promenljivih (auto, static,extern, register, typedef), tip – identifikator tipa (predefinisanog, korisnicki defin-isanog ili strukturnog – strukture ili unije).

Na primer,

int v[50];

deklarise 50-elementni celobrojni niz v.Korisnicki tip moze se definisati definicijom tipa oblika

typedef tip id-tipa,

npr.

typedef int[50] vector;

(definisan je novi tip koji se zove ”vektor” i koji je 50-elementni celobrojni niz).Niz v sada moze da se deklarise i kaovector v;

U nasem primeru, definicijom tipa strukture definisan je tip sa imenom slog.

5.5. Tipovi podataka 45

Oblast vazenja promenljive zavisi od toga gde je deklarisana i koje je vrste,i moze biti blok, funkcija, izvorna datoteka, ili sve izvorne datoteke. Trajanjepromenljive je nezavisno od njene oblasti vazenja, zavisi od njene vrste, i moze bititrajanje izvrsavanja bloka, funkcije ili programa. Na primer, promenljiva lokalnaza blok, sa trajanjem izvrsenja bloka, zove se automatska (auto) promenljiva, dokje promenljiva lokalna za blok sa trajanjem izvrsenja programa – staticka (static)promenljiva.

U nasem primeru, niz A sa elementima tipa slog je spoljasnji objekat koji se”vidi” i u funkciji main i u funkciji BinarPret, i cije je trajanje – trajanje celogprograma; celobrojne promenljive i,n,x su automatske promenljive (unutrasnje zafunkciju main sa trajanjem te funkcije), dok su promenljive l,d,s – automatskepromenljive funkcije BinarPret.

Postoji i vrsta registarske (register) promenljive koja se veoma cesto koristi pase sugerise kompilatoru da je pridruzi masinskom registru.

Promenljive se mogu inicijalizovati definicijama (u nasem primeru int l=0), alise strukturne promenljive (npr. nizovske) mogu inicijalizovati samo ako su staticke(podrazumeva se njihova inicijalizacija na 0, za razliku od Pascal-skih promenljivihkoje su inicijalno nedefinisane).

Osnovni tipovi. U C-u postoje tri osnovna tipa podataka: znakovni (char),celobrojni i realni (za razliku od Pascal-a u kome postoji i tip Boolean, kao ipodintervalni tipovi). Celobrojni tip se javlja u tri velicine (int, short, longint),realni u dve (float, double). Celi brojevi mogu biti i neoznaceni (unsigned) zamanipulisanje bitovima i adresama.

Nabrojivi tipovi. U C-u (slicno Pascal-u) postoje i nabrojivi tipovi kojise sastoje od nabrojivih konstanti sa celobrojnim vrednostima (od 0 do brojakonstanti−1, sto se podrazumeva, ili sa vrednostima koje su tim konstantama ek-splicitno dodeljene). Na primer,

enum boolean {NE, DA};je nabrojivi tip nazvan boolean sa dve nabrojive konstante od kojih prva (NE) imavrednost 0 a druga (DA) vrednost 1. Ali, u primeru

enum meseci { JAN=1, FEB, MAR, APR, MAJ, JUN, JUL, AVG, SEP, OKT,NOV, DEC };nabrojiva konstanta JAN ima vrednost 1 a svaka sledeca – za 1 vecu od prethodne.

Nabrojivi tip je alternativni vid definisanja imenovanih konstanti (pored #define).

Strukturni tipovi. U C-u su prisutna dva mehanizma za struktuiranje po-dataka: niz i struktura. Deklaracija niza ima oblik

vrsta tip elementa ime [velicina]. . .

46 5. Pregled programskog jezika C

Tip elementa moze biti bilo koji tip, ali velicina mora biti konstantni celobrojniizraz. Elementi niza ime imaju indekse od 0 do velicina −1 (u nasem primeru nizA ima elemente tipa slog a indekse od 0 do MAXELEM −1, tj. 99). Prednost C-au odnosu na Pascal kada su nizovi u pitanju jeste da parametar funkcije moze bitiniz sa proizvoljnim brojem elemenata (u Pascal-u su nizovi sa razlicitim brojemelemenata – razlicitih tipova i ne odgovaraju istom parametru), dok je prednostPascal-a u tome sto indeksi niza ne moraju biti celobrojni, a ako jesu, ne morajupocinjati unapred zadatom vrednoscu (npr. 0 ili 1).

Struktura u C-u je objekat koji se sastoji od jednog ili vise polja, gde je svakopolje – objekat proizvoljnog tipa. U nasem primeru, struktura tipa slog sastoji seod dva polja – jedno je kljuc i celobrojnog je tipa, a drugo je vrednost i tip muje pokazivac na objekte tipa karakter (zbog tesne veze izmedu pokazivaca i nizovau C-u, ”vrednost” je zapravo ime niza karaktera, tj. adresa prvog elementa nizakaraktera – v. sledeci paragraf ”Pokazivaci”). Obracanje polju strukture vrsi se naslican nacin kao i u Pascal-u – ime strukture, tacka, ime polja – u nasem primeru,A[s].kljuc.

Dve varijante tipa strukture u C-u su unija i bit-polja (o ovim varijantama bicereci kasnije).

Pokazivaci. Pokazivac u C-u pokazuje na objekat nekog specificnog tipa, tj.predstavlja memorijsku adresu tog objekta. Deklaracija

char ∗vrednost;struct slog ∗sp;

definise vrednost kao pokazivac na objekte tipa karakter a sp kao pokazivac naobjekte tipa slog. Operator ∗ (tzv. operator dereferenciranja) daje kao rezultatpromenljivu na koju pokazuje pokazivac – argument ovog operatora, tj. promenljivucija je adresa – argument ovog operatora. Tako, vrednost i sp su adrese, ∗vrednost jekarakter, a (∗sp).kljuc (ili, ekvivalentno, sp → kljuc) je ceo broj. Operator & (tzv.operator referenciranja) inverzan je operatoru ∗ i daje rezultat – adresu objekta.Tako sp moze da bude inicijalizovano sa

sp = &primerak sloga;

Nad adresama (pokazivacima) definisani su operatori poredenja, dodavanja ioduzimanja celih brojeva. Racun nad adresama izvodi se u jedinicama velicinememorije potrebne za smestanje vrednosti baznog tipa za pokazivac. Zato,vrednost + 1 pokazuje na sledeci karakter u memoriji a sp + 1 pokazuje na sledeciprimerak sloga.

Pokazivaci i nizovi su tesno povezani u C-u. Ime niza je pokazivac na prvielement niza. Tako, ako je A niz, njegovom prvom elementu moze se pristupiti bilosa A[0] ili ∗A. Slicno, vrednost[0] oznacava karakter na koji pokazuje vrednost,vrednost[−1] je prethodni karakter a vrednost[1] je sledeci karakter.

Za razliku od Pascal-a gde pokazivacke promenljive mogu da pristupe samodinamickim promenljivim, u C-u pokazivaci mogu da pristupe i eksplicitno deklar-isanim promenljivim (u nasem primeru, npr. int n; &n).

5.6. Izrazi 47

Komentar o tipovima. Dok je filozofija tipova podataka u Pascal-u – skrivanjesvojstava hardvera, adresa, bitova, filozofija tipova podataka u C-u je obezbedenjepogodnog nacina da se tim hardverom upravlja. Mada je nivo instrukcija u C-uobicno visi od masinskog, objekti kojima operise su nivoa slicnog masinskom. UC-u se moze jednostavno pristupiti specificnim fizickim adresama, kao i specificnimbitovima u reci, sto u Pascal-u nije moguce ili nije jednostavno.

Zbog mesanja buleanskog i celobrojnog tipa (svaka celobrojna vrednost 6=0 u C-u se moze interpretirati kao TRUE, a 0 – kao FALSE; logicki iazraz dobija vrednost1 ako je tacan, i 0 ako je netacan), C kompilatori ne mogu da otkriju izvesne greskekoje se lako otkrivaju u Pascal-u. Na primer, u C-u su sintaksno korektni relacijskiizrazi

1<2<3 i 3<2<1i oba se izracunavaju na 1 (TRUE). Naime, izracunavanje izraza ide sleva na desno.U prvom izrazu, 1<2 daje 1 (tacno), a 1<3 daje opet jedan. U drugom izrazu, 3<2daje vrednost 0 (netacno), a 0<1 daje opet jedan.

Nizovi razlicitih dimenzija u Pascal-u su razlicitih tipova, pa se ne mogu napisatiprocedure (funkcije) koje prihvataju nizove razlicitih duzina. Zato se ne mozenapisati biblioteka opstih rutina za obradu stringova (nizova karaktera). U C-uovaj problem ne postoji.

5.6 Izrazi

Izrazi se grade od konstanti, promenljivih, poziva funkcija, i operacija. Programskijezik C ukljucuje sledece skupove operacija:

1. aritmeticke (+,−,∗, /, % (moduo); deljenje (/) nad celim brojevima dajecelobrojni deo kolicnika)

2. logicke (&&, ||, !)

3. relacijske (==, ! =, <, <=, >, >=)

4. manipulisanje bitovima (&, |, ˆ, . . . )

5. uvecanja i umanjenja za jedan (++, −−)

6. promena tipa ((tip) izraz)

7. dodele (=, +=, − =, ∗=, /=, %=, . . . )

U C-u postoji veci broj prioriteta operacija (npr. == i ! = su nizeg prioritetaod ostalih relacijskih operacija, a sve one su viseg prioriteta od logicke operacijekonjunkcije && koja je viseg prioriteta u odnosu na disjunkciju, ||).

48 5. Pregled programskog jezika C

Operatori dodele. Za C je karakteristicno da operator dodele (=) mozeda ucestvuje u izrazu kao i svaki drugi operator. Vrednost dodele je vrednostdesnog operanda transformisana u tip levog operanda dodele. Na primer, izraz(x=sledeci())! =KRAJ dobija vrednost 1 (tacno) ili 0 (netacno), jer funkcija sledecisvoju vrednost dodeljuje promenljivoj x, i pri tome izraz x=sledeci() dobija vred-nost promenljive x; zato se ta vrednost moze dalje porediti sa konstantom KRAJ,a vrednost tog poredenja je 1 (za tacno) ili 0 (za netacno).

Pored uobicajene dodele, C ima i operatore dodele sa dodavanjem, oduziman-jem, mnozenjem i deljenjem, tj. +=, −=, ∗=, /=, %=, . . . , kao i operatore uvecanjaodnosno umanjenja, ++, −−. Na primer, v+=a+5; je ekvivalentno sa v=v+a+5;++v je uvecanje vrednosti promenljive v pre koriscenja njene vrednosti, a v++uvecanje vrednosti te promenljive posle koriscenja njene vrednosti.

Dopustanjem dodela unutar izraza programski jezik C doprinosi bocnim efek-tima, koji cine program manje preglednim, manje pouzdanim i teze izmenljivim.Ova mogucnost, s druge strane, cini program kompaktnijim od odgovarajuceg pro-grama na Pascal-u. Na primer, sledeci iskaz u C-u

while((s[i++]=getchar())! =EOF);odgovara sledecem segmentu programa u Pascal-u:

while not eof dobegin

s[i]:=getchar();i:=i+1

end

Logicki izraz. Logicki izrazi izracunavaju se uslovno, sleva na desno, samodok se ne utvrdi njihova istinitosna vrednost; desni operand operacija AND (&&),OR (||) izracunava se samo ako vrednost izraza nije utvrdena izracunavanjem levogoperanda (za razliku od Pascal-a gde se logicki izraz uvek izracunava u celosti pazato mora biti u potpunosti definisan).

Uslovni operator. Ovaj operator, u oznaci ?:, uzima tri operanda: uslov,tacno-deo, netacno-deo. Na primer, vrednost izraza

y! =0?1/y:BESKONACNOjeste 1/y ako y nije 0, i BESKONACNO, inace.

Operator ”,”. Operator ”,” omogucuje kombinovanje dva izraza u jedan. Vred-nost rezultujuceg izraza je vrednost desnog izraza. Na primer, izraz

i=0, j=1dodeljuje 0 promenljivoj i a 1 promenljivoj j, i dobija vrednost 1.

5.7. Iskazi 49

5.7 Iskazi

U programskom jeziku C, svaki izraz moze biti ”pretvoren” u iskaz ako mu se nakraj doda tacka-zapeta (”;”); izraz se tada ”izvrsava” da bi se izvrsili njegovi bocniefekti, a vrednost koju izracunava – zanemaruje se.

Dodela. Serijska kompozicija. Iskaz dodele u C-u je izraz dodele sa tacka-zapetom na kraju. Dodela se moze izvrsiti izmedu svih tipova osim nizovskog.Visestruke dodele imaju smisla jer je dodela – izraz. Na primer,

i=j=k=0;jeste izraz (odnosno iskaz) koji se izracunava zdesna ulevo tako sto promenljivak dobija vrednost 0, podizraz k = 0 dobija vrednost 0, ta vrednost se dodeljujepromenljivoj j, podizraz j = k = 0 dobija vrednost 0, a ta vrednost se dodeljujepromenljivoj i i ceo izraz dobija vrednost promenljive i (0).

Niz iskaza grupise se u jedan logicki (serijski komponovani) iskaz uokviravanjemzagradama ({, }).

Selekcija. Osnovna konstrukcija za selekciju (izbor) iskaza u C-u je oblikaif(uslov) iskaz1else iskaz2Uslov je izraz cija je istinitosna vrednost netacno ako je 0, a inace je tacno.

Semantika iskaza je ista kao i u drugim programskim jezicima.Za visestruki izbor prema vrednosti izraza programski jezik C ima iskaz switch:

switch (izraz) {case konstantni izraz1: lista iskaza1;case konstantni izraz2: lista iskaza2;

...default: podrazumevana lista iskaza;

...}Za razliku od slicnog iskaza u Pascal-u, posle izvrsenja liste iskaza pridruzenih

vrednosti izraza, izvrsavanje se nastavlja razmatranjem sledeceg slucaja, osim akose kontrola ne prenese eksplicitno (iskazom break) na drugi deo programa.

Iteracija (ponavljanje). Programski jezik C ima iterativne konstrukcije(petlje) sa proverom uslova na pocetku ili na kraju:

while (uslov) iskaz

odnosno

do iskaz while uslov

50 5. Pregled programskog jezika C

U oba slucaja iskaz se izvrsava sve dok se logicki izraz uslov izracunava navrednost tacno.

Ciklus oblikainicijalizacija petlje;while (uslov) {

iskaz;reinicijalizacija petlje;

}zapisuje se u C-u sintaksom koja objedinjuje inicijalizacije i uslov u zaglavlje petlje:

for(inicijalizacija petlje; uslov; reinicijalizacija petlje) iskaz;

Komponente zaglavlja for iskaza su izrazi, i svaki moze da bude prazan (prazanuslov ima vrednost tacno). Na primer, for(i=0; i<n; i++)A[i]=0; For-iskaz u C-unema dobra svojstva slicnog iskaza u Pascal-u (da se sigurno zavrsava, da je smeriteracije odreden iz samog teksta programa, i da je broj iteracija poznat na pocetkuizvrsavanja iskaza), ali ima vecu fleksibilnost (npr. vrednost kontrolne promenljivene mora da se menja za (+|−)1.

Bezuslovni prenos kontrole. U C-u postoje tri iskaza bezuslovnog prenosakontrole upravljanja: break, continue i goto. Break izlazi iz unutrasnje petlje iliswitch iskaza. Continue prelazi na sledecu iteraciju unutrasnje petlje, dok gotoprenosi upravljanje na obelezje (koje ima oblik identifikatora). Prenos je mogucizmedu blokova i upravljackih struktura, ali ne izmedu funkcija.

5.8 Ulaz-izlaz

Operacije ulaza i izlaza nisu deo programskog jezika C, vec se realizuju funkcijamaiz standardne C biblioteke (pripadaju tzv. okruzenju C-jezika). Standardno za-glavlje stdio.h ukljucuje rutine za citanje i pisanje podataka u blokovima proizvoljneduzine, i za citanje i ispis formatiranog teksta.

Najjednostavniji mehanizam za unosenje jeste citanje jednog po jednog karak-tera sa standardnog ulaza, obicno tastature, celobrojnom funkcijom getchar bezargumenata (void oznacava odsustvo argumenata):

int getchar(void)koja vraca sledeci ucitani karakter ili EOF kada naide na kraj datoteke.

Slicno, funkcijaint putchar(int)

koristi se za izdavanje: putchar(c) izdaje karakter c na standardni izlaz, obicnoekran.

Mehanizam formatiranja se koristi za izgradnju stringova proizvoljne forme, bilona izlazu (pri izdavanju podataka) ili u memoriji (pri ucitavanju podataka).

5.8. Ulaz-izlaz 51

Funkcija izlaza, printf, prevodi interne vrednosti (iz memorije) u niske karak-tera (stringove). Oblik njenog zaglavlja je

int printf(char ∗format, arg1, arg2, . . . )

Ova funkcija konvertuje, formatira i izdaje vrednosti svojih argumenata arg1,arg2, . . . na standardni izlaz, pod kontrolom zadatog formata. Funkcija vraca brojizdatih karaktera.

Pri pozivu funkcije printf, argument format (s obzirom da je string) pise seizmedu navodnika. Pored obicnih karaktera koji se izdaju kako su napisani, formatukljucuje i objekte za specifikaciju konverzije, tj. objekte koji govore kojim tipominterpretirati i u koji oblik konvertovati svaki od argumenata. Zato format mora daima tacno onoliko objekata za specifikaciju konverzije koliko argumenata ima printf.Ovi objekti pocinju znakom % i ukljucuju (pored ostalog) neki od karaktera ”d”,”i” (za izdavanje celog broja), ”c” za izdavanje jednog karaktera, ”s” za izdavanjestringa (niske karaktera), ”f” za izdavanje realnog broja, itd.

Na primer, poziv funkcije

printf(”indeks trazenog elementa je %d”, BinarPret(A,n,x));

iz naseg primera, izdaje tekst ”indeks trazenog elementa je”, a zatim pod kontrolomobjekta specifikacije konverzije %d (dakle, u obliku celog broja), izdaje vrednostsvog jedinog argumenta – vrednosti funkcije BinarPret(A,n,x). Ako je, na primer,vrednost te funkcije ceo broj 3, funkcija printf izdace tekst

indeks trazenog elementa je 3

Funkcija scanf je analogon funkcije printf za formatirani unos. Ova funkcijauzima nisku karaktera sa standardnog ulaza, pronalazi (prepoznaje) podniske cijasintaksa odgovara tipovima (objektima specifikacije konverzije) iz formata, kon-vertuje te podniske karaktera u odgovarajuce tipove (npr. cele, realne brojeve) idodeljuje ih promenljivim – svojim argumentima arg1, arg2, . . . . Preciznije, dodelase vrsi promenljivim cije su adrese arg1, arg2, . . . , jer, za razliku od funkcije printf,svi argumenti funkcije scanf osim prvog (formata) moraju da budu pokazivaci.

Na primer, poziv funkcije

scanf(”%d”, &x);

iz naseg primera, ucitava nisku karaktera (koja se sastoji od dekadnih cifara), kon-vertuje je u ceo broj i vrednost tog celog broja dodeljuje celobrojnoj promenljivojx.

Funkcija scanf vraca broj uspesno prepoznatih i dodeljenih vrednosti.

Kako operacije ulaza i izlaza nisu deo samog C jezika, neslaganje u tipu ilibroju komponenti formata i odgovarajucih argumenata ne moze da bude otkrivenou vreme kompilacije, nego tek u vreme izvrsavanja programa.

52 5. Pregled programskog jezika C

6

Osnovni tipovi podataka

6.1 O tipovima

U matematici se promenljive klasifikuju po znacajnim karakteristikama kao realne,kompleksne, logicke, skupovne, skupove skupova, funkcije, funkcionale, skupovefunkcija, itd. U racunarskoj obradi podataka klasifikacija se pokazuje jos vaznijom.

U matematici se tip podataka prepoznaje iz konteksta. U programiranju se tipeksplicitno deklarise, i ukazuje na dimenziju prostora koji kompilator odreduje zapodatak tog tipa. Pri tome vazi:

• tip odreduje skup vrednosti

• tip se moze odrediti iz oblika (npr. konstante) ili deklaracije (npr. promenljive),bez izvrsavanja procesa racunanja

• svaka operacija ili funkcija ”ocekuje” argumente odredenog tipa i proizvodirezultat odredenog tipa. Ako operacija uzima argumente razlicitih tipova(npr. ”+” nad tipom float, int), tip rezultata se odreduje iz jezickih pravila.

U vecini slucajeva, novi tip podataka definise se u terminima prethodno defin-isanih tipova. Vrednosti takvih tipova su konglomerati komponentnih vrednostiprethodno definisanih konstituentnih tipova, i takav, novi tip naziva se struk-tuiranim (ili strukturnim) tipom.

Ako se tip sastoji samo od jednog konstituentnog tipa, on je primitivni (iliosnovni, ili bazni) tip.

Broj razlicitih vrednosti tipa T je njegova kardinalnost. Kardinalnostobezbeduje meru prostora potrebnog za predstavljanje promenljive x tipa T (Tx).

Komponentni tipovi mogu biti opet struktuirani, ali su krajnje komponenteobavezno atomicne (primitivnih tipova). Zato je neophodno da programski jezikobezbedi mogucnost uvodenja primitivnih (nestruktuiranih) tipova.

53

54 6. Osnovni tipovi podataka

Jedan nacin za uvodenje primitivnih tipova jeste nabrajanje (enumeracija).Ovo su nabrojivi tipovi i njih definise programer, npr. u C-u

enum mesec {JAN=1, FEB, MAR, APR, MAJ, JUN, JUL, AVG, SEP, OKT,NOV, DEC};ili, u Pascal-u

dan =(pon, uto, sre, cet, pet, sub, ned)

Drugi nacin za uvodenje primitivnih tipova su predefinisani, standardni tipovipodataka. Ovi tipovi obicno ukljucuju brojevne i znakovne (a cesto i logicke)vrednosti.

Programski jezik opste namene mora da ”ponudi” i vise metoda struk-tuiranja, kojima se grade struktuirani tipovi. U matematickom smislu svi mogubiti ekvivalentni, ali se u programerskom smislu razlikuju po operatorima za kon-struisanje vrednosti i izbor komponenti tih vrednosti. Osnovne metode struk-tuiranja tipova su niz, slog i sekvenca (datoteka) – u C-u niz i struktura. Kom-pleksnije strukture se obicno ne definisu kao ”staticni” tipovi, vec se ”dinamicki”generisu za vreme izvrsavanja programa. Ove strukture ukljucuju liste, prstenove,drveta, i uopste, konacne grafove.

Najznacajniji primitivni (osnovni) operatori programskog jezika su poredenje idodela, tj. test jednakosti (i uredenja ako je definisano), i komanda za nametanjejednakosti. Razlika izmedu ova dva operatora najcesce je vidljiva i u notaciji. Naprimer, u C-u test jednakosti ima oblik x == y, dok dodela ima oblik x = y (uPascal-u test jednakosti ima oblik x = y, dok dodela ima oblik x := y; neki jezici,kao npr. Fortran ili PL/I, nazalost, ne prave tu razliku u notaciji). Ovi operatorisu definisani za skoro sve tipove podataka.

Medu osnovnim – implicitno ili eksplicitno definisanim operatorima su i tzv.operatori transfera. Oni preslikavaju tipove podataka u druge tipove podataka.

Standardni primitivni tipovi podataka zahtevaju i standardne primitivne opera-tore. Na primer, brojevni i logicki tipovi podataka zahtevaju operatore aritmetickei iskazne logike.

Svakom standardnom tipu pridruzene su dopustene operacije i standardnefunkcije. Neke standardne funkcije imaju isti tip kao i argument (na primer,funkcija koja izracunava apsolutnu vrednost broja u Pascal-u je abs(x), a u pro-gramskom jeziku C funkcije iz odgovarajuce biblioteke su abs(i), fabs(x)), a mogutransformisati i vrednost jednog tipa u drugi tip (na primer, funkcija koja vracacelobrojnu vrednost niske cifara s u C-u je atoi(∗s)).

Struktuirane vrednosti se generisu tzv. konstruktorima, a komponente seizdvajaju tazv. selektorima. Svaki struktuirani tip ima pridruzen par ovakvihoperatora transfera.

6.2 Osnovni tipovi u C-u

Standardnih osnovnih tipova u C-u je veoma malo. To su:

6.2. Osnovni tipovi u C-u 55

char – jedan bajt, moze da primi jedan karakter u lokalnom skupu karaktera;

int – ceo broj, obicno velicine celog broja na pripadnom racunaru (npr. 2, 4bajta)

float – realni broj u tzv. pokretnom zarezu, jednostruke preciznosti;

double – realni broj u pokretnom zarezu, dvostruke preciznosti

6.2.1 Znakovni tip

Znakovni tip je konacni i uredeni skup karaktera. Kao sto je vec receno u delu”Azbuka, rec, jezik, jezicki procesori”, svaki racunar ima svoj skup karaktera zakomunikaciju sa korisnikom, i taj skup nije standardizovan.

Skup karaktera je ureden prema uredenju njihovih unutrasnjih kodova u odgo-varajucoj kodnoj semi (npr. ASCII kodu).

Osnovni objekti podataka nad kojima program vrsi operacije jesu konstante ipromenljive.

Znakovna konstanta je ceo broj, zapisan u obliku jednog karaktera izmedujednostrukih navodnika, npr. ’x’. Vrednost znakovne konstante je vrednost kodatog karaktera u pripadnom karakterskom skupu odnosno kodnoj semi. Na primer,vrednost znakovne konstante ’0’ je 48, i ta dva zapisa imaju identicnu vrednost –ASCII kod znaka ’0’; ipak, zapis ’0’ je pouzdaniji jer ne zavisi od pripadne kodneseme. Znakovne konstante mogu da ucestvuju u aritmetickim izrazima bas kao idrugi celi brojevi.

Neki karakteri predstavljaju se kodnom sekvencom, na primer \n (karakter zanovi red), \t (tabulator) \b (karakter unazad – engl. backspace), \? (znak pi-tanja), \\ (kosa crta unazad – engl. backslash), itd; ove sekvence izgledaju kao dvakaraktera, ali predstavljaju jedan karakter.

Znakovna konstanta ’\0’ predstavlja karakter sa vrednoscu 0, tj. ima vrednost0. To je tzv. nula-karakter.

Znakovna konstanta moze da bude zapisana i u obliku oktalnog broja, na primer:’\101’, ’\61’, odnosno heksadecimalnog: ’\x41’, ’\x31’.

Znakovnoj konstanti (kao i konstantama drugih tipova) moze se dodeliti ime(identifikator) instrukcijom preprocesora #define, npr.

#define GRANICNIK ’$’a one se zatim mogu koristiti u izgradnji konstantnih izraza kojima se, na primer,deklarisu nizovi:

#define MAXLINE 1000char linija[MAXLINE+1]; /∗ niz znakova linija ima MAXLINE+1 element ∗/Uvodenjem identifikatora za konstante postize se pouzdanije i lakse programi-

ranje i modifikacija programa.

Niska karaktera, ili literal, ili string, jeste niz od 0 ili vise karaktera navedenihizmedu dvostrukih navodnika, kao, na primer, ”ovo je string”. String je zapravoniz karaktera sa nula-karakterom na kraju. Standardna biblioteka funkcija sadrzi

56 6. Osnovni tipovi podataka

funkciju strlen(s) koja se deklarise u standardnom zaglavlju <string.h> i koja vracaduzinu stringa s, ne racunajuci nula-karakter.

Dakle, bitna razlika izmedu znakovne konstante i stringa je sto je znakovnakonstanta ceo broj, a string je niz karaktera za kojim sledi nula-karakter.

Promenljiva ima ime (identifikator), tip, adresu i vrednost. Identifikator sesastoji od slova i cifara (prvi karakter je slovo) pri cemu se i podvlaka ( ) racunakao slovo, a mala i velika slova su razliciti karakteri. Duzina identifikatora zavisiod vrste promenljive – identifikatori unutrasnjih promenljivih mogu da budu i do31 karakter dugacki, a spoljasnjih, kao i imena funkcija, bar do 6.

Definicijom promenljivih uvode se nove promenljive u program, tj. imenapromenljivih koje ce se koristiti nabrajaju se, navode se njihovi tipovi (za znakovnepromenljive – tip char), rezervise se memorijski prostor za te promenljive (zapromenljive tipa char 1 bajt) i eventualno dodeljuju pocetne vrednosti. Deklaraci-jom promenljivih nabrajaju se promenljive koje ce se koristiti (i koje mogu bitiuvedene na drugom mestu u programu), i navode se njihovi tipovi. Dakle, defini-cije su ujedno i deklaracije, dok obratno ne vazi.

Na primer,char c, linija[1000];int granica = MAXLINE+1;

Promenljiva znakovnog tipa moze da bude oznacena i tako da joj se vrednostne menja, ili kao parametar (funkcije) kome funkcija ne moze da menja vrednost.Na primer,

const char poruka[ ] = ”warning: ”;int strlen(const char[ ]);

Na promenljive tipa char moze da se primeni kvalifikator signed (oznacen) iliunsigned (neoznacen) , pri cemu se neoznaceni tip interpretira kao skup pozitivnihbrojeva ili 0. Na primer, ako je tip char duzine 8 bita, onda promenljive tipaunsigned char imaju vrednosti od 0 do 255 (reprezentacija 00000000 predstavljavrednost 0 a reprezentacija 11111111 predstavlja vrednost 255 tj. 1 ∗ 27 + 1 ∗ 26 +1 ∗ 25 + 1 ∗ 24 + 1 ∗ 23 + 1 ∗ 22 + 1 ∗ 21 + 1 ∗ 20). S druge strane, tip signed charukljucuje vrednosti od -128 do 127 (ima ih takode 28 = 256, ali je interpretacijazapisa – ceo broj u tzv. potpunom komplementu: negativan broj se dobija kadase u binarnom zapisu odgovarajuceg pozitivnog broja binarne cifre dopune do 1– 0 se zamenjuje sa 1 a 1 sa 0, a zatim se tako transformisani zapis sabira sa 1.Tako najvecu vrednost ima zapis 01111111 – vrednost je 127, dok zapis 10000001(10000000+1) ima vrednost −127. Broj za 1 manji ima zapis 10000000 pa se njimepredstavlja broj −128).

Znakovnom tipu odgovaraju funkcije iz standardne C-biblioteke, kojima sestringovi kopiraju, dopisuju, porede, pronalaze podstringovi, odreduje duzina, itd.Ove funkcije nalaze se u standardnom zaglavlju <string.h>

Zadatak: Napisati funkciju int lower(int c) koja konvertuje karakter c (njegovASCII kod) u malo slovo (ako je c veliko slovo), inace vraca isti karakter c.

6.2. Osnovni tipovi u C-u 57

6.2.2 Celobrojni tip

U racunaru se moze predstaviti samo konacno mnogo celih brojeva, tj. celobrojnitip (npr, u C-u int, u Pascal-u integer) je konacni podskup skupa celih brojeva.Taj podskup je definisan implementacijom, i zavisi od duzine (u bajtovima tj.bitovima) kojom se ceo broj predstavlja. Ako se podatak tipa int predstavlja sadva bajta (16 bitova), onda se mogu predstaviti celi brojevi u intervalu

[−215, 215 − 1].Upotreba brojeva izvan ovog intervala dovodi do greske.Na celobrojni tip int mogu se primeniti i dodatni kvalifikatori, short i long. Oni

oznacavaju velicinu celog broja, tj. broj bitova za njegovu reprezentaciju; short int(kratki ceo broj) i ”obicni” int su bar po 16 bita (2 bajta), long int (dugacki ceobroj) je bar 32 bita (4 bajta), i vazi da je short int ≤ int ≤ long int.

U standardnom zaglavlju ¡limits.h¿ definisane su konstante-ogranicenja tipa int,zavisna od implementacije.

Celobrojni tip, slicno znakovnom, moze biti kvalifikovan kao signed (oznacen)ili unsigned (neoznacen), sa istom interpretacijom kao i odgovarajuci znakovni tip.

Tip konstante ocigledan je iz samog njenog zapisa – celobrojna konstanta imauobicajenu sintaksu (npr. 1234) i njen tip je int. Ako se celobrojna konstantazavrsava slovom l (ili L), ili ako je suvise velika da bi bila tipa int, konstanta je tipalong int; ako se zavrsava slovom u (U), odnosno ul (UL), konstanta je neoznacen,odnosno dugacki neoznacen ceo broj. Celobrojna konstanta moze da bude zapisanai u oktalnom odnosno heksadekadnom zapisu (sistemu) – ako pocinje cifrom 0odnosno cifrom 0 i slovom x (X) (cifre oktalnog sistema su 0–7, a heksadekadnog– cifre 0–9 i slova ’a’–’f’, odnosno ’A’–’F’). Tako je 31 dekadni ceo broj sa istomvrednoscu kao i oktalni ceo broj 037 tj. heksadekadni ceo broj 0x1f (tj. 0X1F).

Nad operandima celobrojnog tipa dopustene su operacije + (sabiranje), −(oduzimanje), ∗ (mnozenje), / (izracunavanje celobrojnog dela kolicnika) i %(izracunavanje ostatka pri celobrojnom deljenju). Sve operacije nad celobrojnimargumentima proizvode celobrojne rezultate.

Za operacije / i % vazi sledeca relacija:a % b = a− ((a / b) ∗ b).

Znak – moze biti i unaran (npr. –50).

Operatori uvecanja i umanjenja Pored prethodnih, na promenljive celobro-jnog tipa u C-u mogu da se primene i dva specificna operatora, obicno niskog(masinskog ) nivoa – dodavanja 1 na argument ”++” i oduzimanja 1 od argumenta”−−”.

Na primer, if(c==’\n’) ++n;Ono sto je neobicno o ovim operatorima jeste to sto se oni mogu primenjivati

pre ili posle koriscenja vrednosti promenljive. Tako, na primer, iskaz

58 6. Osnovni tipovi podataka

x = n++;dodeljuje vrednost promenljive n promenljivoj x, a zatim povecava vrednostpromenljive n za 1, dok iskaz

x = ++n;povecava vrednost promenljive n za 1 a zatim tako povecanu vrednost dodeljujepromenljivoj x.

Ove se operacije mogu primenjivati samo na promenljive (ne i na izraze).

Prioritet operacija nad celobrojnim tipovima (v. tacku 6.4) je sledeci: unarni+ i −, uvecanje (++) i umanjenje (−−) – najviseg prioriteta, zatim operatoriumnozavanja ∗, / %, i najzad operatori sabiranja i oduzimanja + i −.

Nad celobrojnim tipom, kao i nad ostalim primitivnim tipovima, dopustenesu i relacijske operacije == (jednakost), ! = (razlicitost), <, >, <=, >=, ciji jerezultat logickog tipa. Tako je vrednost poredenja 3<4 tacno (1), a 4<3 netacno(0). Relacijske operacije su nizeg prioriteta od aritmetickih.

Standardne funkcije za rad sa celim brojevima u C-u deklarisane su u stan-dardnim zaglavljima <stdlib.h> i <math.h> standardne biblioteke. Sa rezultatomcelobrojnog tipa su, na primer, abs(n) – apsolutna vrednost (n – celobrojnog tipa),atoi(s) – celobrojna vrednost niske cifara s, (zaglavlje <stdlib.h>). Funkcije zaizracunavanje najmanjeg celog broja veceg ili jednakog od x, najveceg celog brojamanjeg ili jednakog x – ceil(x), floor(x), pri cemu su i x i vrednost funkcije tiparealnog broja dvostruke tacnosti (double), na primer, nalaze se u standardnomzaglavlju <math.h>, zajedno sa drugim realnim funkcijama.

Primer: Neka je potrebno sabrati dva cela broja zadata njihovim nizovima cifara.Ako su to, na primer, trocifreni brojevi, onda program na Pascal-u moze imatisledeci oblik:

#include ¡stdio.h¿char c11, c12, c13, c21, c22, c23;int b1, b2, zbir;main(){

scanf(”%c, %c, %c, %c, %c, %c”, &c11, &c12, &c13, &c21, &c22, &c23);b1 = ((c11 – ’0’)∗10 +(c12 – ’0’))∗10 + c13 – ’0’;b2 = ((c21 – ’0’)∗10 + (c22 – ’0’))∗10 + c23 – ’0’;zbir = b1+b2;printf(”%d\n”, zbir);

}Standardna funkcija transfera stringa (koji se sastoji od karaktera – cifara) u

ceo broj (int atoi(char [])) bice prikazana u tacki 10.1.

Medutim, ako su brojevi dugi (imaju po n cifara, npr. za n=100), oni moguizaci iz dijapazona celih (pa i dugackih celih) brojeva u C-u, pa se zadatak moraresavati na drugi nacin. Jedan takav nacin je da se imitira ”pismeno” sabiranje –

6.2. Osnovni tipovi u C-u 59

zdesna ulevo, a da se i cifre zbira predstavljaju kao znakovi (karakteri) (v. tacku10.1).

6.2.3 Logicki tip

Logicki tip nije standardni tip u C-u. Moze se uvesti kao nabrojivi tip, ali, bezobzira na to, konstanta 0 u okviru logickog izraza ponasa se kao logicka vrednostnetacno, dok se konstante razlicite od 0 ponasaju kao logicka vrednost tacno. Slicno,tacan logicki izraz (na primer, poredenje 3<4) proizvodi vrednost 1, dok netacanlogicki izraz proizvodi vrednost 0.

Za logicki tip koristi se i termin ”buleanski”, kao sinonim.Za logicki tip karakteristicni su operatori konjunkcije, (&&), disjunkcije (||) i

negacije (!).Izrazi buleanskog tipa (sa istinitosnom vrednoscu) veoma su cesti u programi-

ranju. Svako poredenje ima vrednost koja je buleanskog tipa. Razmotrimo sledeciprimer.

Program koji ponavlja citanje znaka sa ulaza i izdavanje tog znaka na izlazu,sve dok se na ulazu ne pojavi znak ’$’, moze se zapisati na sledeci nacin:

char ch;main(){

for(; (ch=getchar())!=’$’; ;)putchar(ch);

}Izraz (ch=getchar())!=’$’ ukljucuje citanje karaktera sa standardnog ulaza, do-

delu tog karaktera promenljivoj ch i poredenje (na razlicitost) tog karaktera sakarakterom ’$’. Ovo poredenje je jednostavni logicki izraz koji moze da ima vred-nost tacno ili netacno. Sve dok je njegova vrednost tacno (karakter je razlicit od’$’), ponavljaju se radnje izdavanja karaktera na standardni izlaz i citanja novogkaraktera sa standardnog ulaza; kada vrednost poredenja postane netacno (ucitanikarakter nije razlicit od ’$’) – sa tim radnjama se zavrsava.

Nad jednostavnim logickim izrazima moze se graditi slozeniji logicki (buleanski)izraz (kao sto je opisano u tacki 4.1.1, ”Dvovalentna logika”). Vrednost logickogizraza izracunava se ”lenjo”: samo dok se ne utvrdi njegova istinitosna vrednost.Na primer, pri izracunavanju vrednosti logickog izraza

(3<5)||(a/b>5)ceo izraz dobija vrednost ”true” vec po izracunavanju prvog disjunkta, pa se drugidisjunkt i ne izracunava i moze biti i nedefinisan (npr. ako je b=0).

Neka je definisan nabrojivi tip boolean i deklarisane sledece promenljive (u C-u):enum boolean {N, T};int kolicina, kol1;float duzina, visina;boolean kraj;

60 6. Osnovni tipovi podataka

Tada su primeri logickih (buleanskih) izraza:kolicina < kol1(kolicina == kol1) && (duzina >= visina) && kraj(kolicina % kol1 ==0) || (kolicina <= 100).

U odnosu na matematicku notaciju, uocimo dve bitne razlike u zapisu logickihizraza u programiranju:

1) zapis, npr. minimum ≤ vrednost ≤ maximum, na koji smo toliko navikli,moze se u C-u zapisati u slicnom obliku: minimum <= vrednost <= maximum, ali,kao sto je vec naglaseno u preglednom delu, ovaj izraz ne mora da dobije ocekivanulogicku vrednost – izracunava se sleva nadesno, pa, na primer, 5<= 2 <=1 dobicevrednost 1 (tacno), mada se to ne ocekuje. Zato se pripadnost intervalu po prav-ilu zapisuje kao konjunkcija dva poredenja: minimum <= vrednost && vrednost<= maximum (u Pascal-u se ovo poredenje moze zapisati samo kao eksplicitnilogicki izraz sa konjunkcijom (and): (minimum <= vrednost) and (vrednost <=maximum));

2) realne brojeve je u programiranju bolje ne uporedivati na jednakost (==),zbog zaokrugljivanja u racunaru, vec na dovoljnu bliskost. Na primer, umestoporedenja a==b (a,b – realne vrednosti), bolje je porediti ih sa fabs(a–b)< ε, zadovoljno malo ε, npr. fabs(a–b)< fabs(a∗1E–6) (razlika na milioniti deo od a, v.”Realni tip”).

6.2.4 Realni tip

Realna konstanta u C-u mora da ima bar jednu cifru u celom delu, ili u razlomljenomdelu, i mora da ima decimalnu tacku ili eksponent; ako je u eksponencijalnomobliku, onda mora da ima bar jednu cifru i iza slova E. Zato su niske .5 ili 2. ili 1.E-2ili 1E5, 0.0005, 9.10956E–28 (masa elektrona), 123.4, 1e-2, 123.4e-2, ispravne realnekonstante u C-u dok niska 3.0E nije (v. sliku 6.1). Konstanta u eksponencijalnomobliku – npr. 123.4e-2 ima vrednost 123.4×10−2.

r.broj --

-

±°²¯+

±°²¯−

-

celi deo ±°²¯· -

- razl.deo6

?-

±°²¯·

celi deo? razl.deo -

6

±°²¯E

±°²¯e

-±°²¯+

±°²¯−

cifra -6

6

celi deo, razl.deo - cifra -6

Figure 6.1: Sintaksni dijagram realne konstante

6.2. Osnovni tipovi u C-u 61

Tip realne konstante je double (realni broj dvostruke tacnosti).Realni broj moze biti i dugacki realni broj dvostruke tacnosti cime se postize

povecana preciznost (broj znacajnih cifara). Ako se realna konstanta zavrsavaslovom f (F), ona je realni broj jednostruke tacnosti; ako se zavrsava slovom l (L),konstanta je dugacki realni broj dvostruke tacnosti.

Kvalifikator long (dugacki) moze se primeniti na promenljive tipa double. Pravavelicina (broj bajtova) za long double zavisi od racunara, ali, kao i za tip int, vazida je velicina tipa float ne veca od velicine double, a ona ne veca od velicine tipalong double.

Vrednost realnog tipa (tipa real) je element konacnog podskupa skupa realnihbrojeva koji je definisan implementacijom. Implementacija definise najmanji, na-jveci realni broj i gustinu tj. tacnost sa kojom se mogu registrovati realni brojevi(standardno zaglavlje ¡float.h¿ sadrzi definicije konstanti za realni tip koje zavise odimplementacije). Na primer, realni broj x koji je razlicit od 0 moze biti u intervalu10−38 ≤ |x| ≤ 1038, a tacnost sa kojom se realni brojevi registruju moze biti 7znacajnih cifara. Ako dva realna broja imaju po vise od 7 znacajnih cifara, i akosu im prvih 7 znacajnih cifara jednake (a prethodi im isti broj nula), onda ta dvabroja mogu da se registruju kao jednaki brojevi (osim ako se zbog zaokrugljivanjanekom od njih poveca poslednja cifra). Tako, na primer, program

#include <stdio.h>float x,y;main(){

scanf(”%f, %f”, &x, &y);printf(”x=%f, y=%f”, x, y);

}za dva razlicita ulazna broja:

123.456781, 123.456782izdaje isti rezultat (sa sest cifara u razlomljenom delu, ali sa ukupno 7 znacajnih,tj. ”tacnih” cifara): x=123.456779, y=123.456779

Isti program za ucitane brojeve1.2345678, 1.2345679

izdaje isti rezultat (sa zaokrugljivanjem na sest cifara u razlomljenom delu – svecifre su znacajne): x=1.234568, y=1.234568

Kako svaki, proizvoljno mali interval na realnoj osi sadrzi beskonacno mnogovrednosti (realna osa je kontinuum), to realni tip u programskom jeziku jestekonacni skup predstavnika intervala na realnom kontinuumu. Izracunati rezul-tati nad realnim brojevima su aproksimacije pravih rezultata. Procenom greske pripribliznom racunanju sa realnim brojevima bavi se numericka matematika.

Ipak, neku predstavu o tacnosti racunanja sa realnim brojevima mozemo dobitiiz nacina na koji se realni broj predstavlja u savremenom elektronskom racunaru.

Uobicajena reprezentacija realnog broja u racunaru je tzv. reprezentacija sapokretnom tackom (floating point representation). U ovoj reprezentaciji realni broj

62 6. Osnovni tipovi podataka

x predstavljen je parom celih brojeva, e i m, tzv. eksponent i mantisa, svaki sakonacno mnogo cifara, tako da je

x = m ∗Be,−E < e < E,−M < m < M .U ovom zapisu m se zove koeficijent ili mantisa, a e – eksponent. B, E,M su

celobrojne konstante koje karakterisu reprezentaciju. B se zove baza reprezentacijesa pokretnom tackom, i obicno nije 10 vec neki mali stepen od 2 (obicno 21, 23, 24).

Na primer, ako se realni broj predstavlja u cetiri bajta (32 bita), mantisa mozebiti predstavljena sa 24 bita (24-cifreni binarni broj odgovara 7-cifrenom dekadnombroju pa to odreduje 7 znacajnih cifara u dekadnom zapisu), a eksponent moze dabude predstavljen sa 8 bitova, pa je binarni eksponent eb (za bazu B = 2) −125 ≤eb ≤ 128, a odgovarajuci dekadni eksponent ed (t.d. 10ed ≈ 2eb) −37 ≤ ed38.

Za odabranu bazu B, dati broj x moze biti predstavljen mnogim parovima(m, e). Kanonicki ili normalizovani oblik realnog broja x definise se uslovomkoji mantisu deljenjem stepenom baze svodi na najveci razlomljen broj:

1B ≤ m < 1.Ako se koristi samo ovaj oblik, onda gustina predstavnika intervala realne prave

opada eksponencijalno sa povecanjem |x|. Na primer, interval [0.1..1] sadrzi pri-blizno isto onoliko predstavnika kao i interval [10000..100000], a tacno isto tolikoako je B = 10. Medu predstavnicima realnih brojeva uvek su 0 i 1.

Rad sa realnim brojevima u programiranju je dosta problematican. Problemeprave kako sabiranje i oduzimanje (skoro jednakih brojeva), tako i deljenje, zbog”odsecanja” znacajnih cifara. Na primer, ako su brojevi predstavljeni sa cetiriznacajne cifre,

x = 9.900, y = 1.000, z = −0.9991. (x + y) + z = 10.90 + (−0.999) = 9.9102. x + (y + z) = 9.900 + 0.001 = 9.901

pa je prekrsen zakon asocijativnosti.Mera preciznosti date aritmetike sa pokretnom tackom, ε, priblizno je 10−n,

ako racunar predstavlja realni broj sa n dekadnih cifara. Preciznost ε (ili ”epsilonmasine”) definise se kao najmanji pozitivni broj takav da 1 i 1 + ε imaju razlicitepredstavnike (npr. ε = 10−7).

Nad realnim tipom dopustene su operacije +, –, ∗, / i relacijske operacije (kao inad celobrojnim tipom). Ako je bar jedan operand realnog tipa, operacije +, ∗, –,/ daju rezultat realnog tipa. Prioritet ovih operacija je kao i kod celobrojnog tipa.

Standardne funkcije koje se primenjuju nad realnim tipovima nalaze se u stan-dardnom zaglavlju math.h. To su trigonometrijske funkcije sin, cos, tan, sinh, cosh,tanh, . . . , eksponencijalna (exp) i logaritamske funkcije – log (prirodni logaritam),log10 (logaritam sa osnovom 10), pow(x,y) (xy), sqrt (kvadratni koren), ceil, floor(ranije pomenute), itd. Za sve ove funkcije i argumenti i vrednost funkcija su tipadouble.

Pri formatiranom ucitavanju ili izdavanju realnog broja, potrebno je prenetipodatak sa jednog medija na drugi (sa tastature u memoriju odnosno iz memorije

6.3. Izrazi 63

na ekran), i transformisati reprezentaciju podatka. Obe radnje obavlja za nas pro-gramski sistem. Standardna funkcija transfera stringa koji se sastoji od karaktera uzapisu realnog broja bez eksponenta, u realni broj, moze imati sledecu deklaraciju:

#include <ctype.h>/∗ atof: konvertuje string s u realni broj dvostruke tacnosti ∗/double atof(char [ ]){

double vred, stepen;int i, znak;for (i=0; s[i]==’\b’ || s[i] == ’\t’; i++)/∗ preskoci sve beline i tabulatore ∗/;znak = (s[i] == ’–’)? –1:1;if (s[i]==’+’ || s[i]==’–’) i++;

/∗ celobrojni deo ∗/for(vred=0.0; ’0’<=s[i] && s[i] <=′ 9′; i++)

vred = 10.0 ∗ vred + (s[i]-’0’);if(s[i]==’.’)i++;

/∗ razlomljeni deo ∗/for(stepen=1.0; ’0’<= s[i]&& s[i]<=’9’; i++){

vred = 10.0 ∗ vred + (s[i] – ’0’);stepen ∗=10.0;

}return znak ∗ vred / stepen;

}Zadatak: Prosiriti funkciju atof tako da prepoznaje realnu konstantu i u ekspo-nencijalnom obliku i od nje gradi realni broj dvostruke tacnosti.

6.3 Izrazi

Izraz kombinuje promenljive, konstante i operacije i tako proizvodi novi objekat sanovom vrednoscu i pripadnim tipom.

6.3.1 Operatori nad bitovima

Pored uobicajenih (prethodno pomenutih) aritmetickih, relacijskih i logickih oper-atora, programski jezik C ima i operatore nad bitovima.

Operatori za manipulisanje pojedinacnim bitovima u C-u su:& – AND nad bitovima (u rezultatu postavlja 1 samo u one bitove u kojima

oba operanda imaju 1);| – inkluzivni OR nad bitovima (postavlja 1 u sve one bitove u kojima bar jedan

od operanada ima 1);

64 6. Osnovni tipovi podataka

ˆ – ekskluzivni OR nad bitovima (postavlja 1 samo u one bitove u kojima tacnojedan operand ima 1);

<< – levi sift (pomeranje levog operanda ulevo za broj bitova sadrzan u desnomoperandu; u oslobodene bitove upisuje se 0; analogno sa mnozenjem odgovarajucimstepenom dvojke)

>> – desni sift (pomeranje levog operanda udesno za broj bitova sadrzan udesnom operandu; najvisi bit se ili ponavlja (aritmeticki sift) ili se u njega upisuje0 – logicki sift).

˜– jednostruki komplement (bitovi 1 zamenjuju se sa 0, a 0 sa 1).

Operator AND nad bitovima koristi se za maskiranje nekih bitova. Na primer,n = n & 0177;

postavlja na 0 sve bitove osim najnizih 7 bitova od n.

Dodelax = x &˜077;

izvrsava se tako sto se prvo operatorom jednostrukog komplementa u konstanti 077postavljaju 0-bitovi na 1 a 1-bitovi na 0, a zatim se u x ostavljaju samo 1-bitovi izgornjih 10 pozicija (donjih 6 su bili 1-bitovi i postali su 0-bitovi).

6.3.2 Konverzija tipova

Do konverzije tipova dolazi u nekoliko situacija:

1. Kada se uz aritmeticki binarni operator navedu operandi razlicitog tipa, oni sekonvertuju na zajednicki tip koji se odreduje prema sledecem skupu pravila:

Ako je jedan od operanada tipa long double, konvertovati drugi operand ulong double,

inace, ako je jedan od operanada tipa double, konvertovati i drugi u tip double,

inace, ako je jedan od operanada tipa float, konvertovati i drugi u tip float,

inace, konvertovati tipove char i short u tip int.

Ako je jedan od operanada tipa long int, konvertovati i drugi u tip long int.

Automatske konverzije vrse se iz ”uzih” u ”sire” tipove pri cemu se ne gubiinformacija (npr celobrojni u realni tj. int u float). Konverzija vrednostiizraza kojom moze da se izgubi informacija (npr. iz long int u int ili shortint, iz float u int kao u izrazu i=f) je dopustena.

Karakteri su kratki celi brojevi (short int) i sa njima se moze izvoditi kom-pletna aritmetika.

Pri konverziji karaktera (jednog bajta) u ceo broj (bar dva bajta), karakter(tj. njegova celobrojna vrednost) upisuje se u nizi bajt celog broja. U slucajuda se pri toj konverziji karakteri interpretiraju kao neoznaceni – unsigned (stozavisi od masine), visi bitovi celog broja popunjavaju se nulama i odgovarajuci

6.4. Prioritet operatora. 65

ceo broj je uvek pozitivan. Ako se karakter interpretira kao oznaceni (signed)broj, karakter koji u najvisem bitu ima 1 prevodi se u negativan broj ( i visibitovi se popunjavaju jedinicama).

2. Pri dodeli (=), tip desne strane u dodeli konvertuje se u tip leve strane dodele.Pri tome, karakter se konvertuje u ceo broj, dugi celi brojevi konvertuju seu krace odbacivanjem potrebnog broja visih bitova. Dodela realnog brojacelobrojnoj promenljivoj odseca razlomljeni deo.

3. Najzad, konverzija tipova se moze vrsiti i eksplicitno, unarnim operatorompodesavanja tipova (engl. cast) oblika

(ime-tipa) izraz

Tada se izraz konvertuje u navedeni tip primenom prethodnih pravila. Naprimer, funkcija sqrt definisana u standardnoj biblioteci u standardnom za-glavlju <math.h>, ima argument tipa double i proizvodi besmisleni rezultatako se primeni na argument drugog tipa (jer se reprezentacija argumenta togdrugog tipa interpretira kao tip double). Zato se ova funkcija moze pozvati zacelobrojni argument tako sto se on prvo eksplicitno konvertuje u tip double:

sqrt((double) n)

Ili, razlomljeni kolicnik celih brojeva i,j:

x=(float) i /j;

6.4 Prioritet operatora.

Programski jezik C ima veliki broj prioriteta operatora zbog cega su zagrade gotovonepotrebne (osim da povecaju citljivost).

Dosad opisani oparatori mogu se grupisati po prioritetima u sledece grupe iporedati na sledeci nacin (prioritet opada sa porastom rednog broja):

1. (), [ ] sleva nadesno2. !, , ++,−−, +, –, ∗, &, (tip) zdesna nalevo3. ∗, /, % sleva nadesno4. +, – sleva nadesno5. <<, >> sleva nadesno6. <, <=, >, >= sleva nadesno7. ==, ! = sleva nadesno8. & sleva nadesno9. ˆ sleva nadesno10. | sleva nadesno11. && sleva nadesno12. || sleva nadesno13. ?: zdesna ulevo14. =, +=, −=, /=, %=, &=, ˆ=, |=, <<=, >>= zdesna ulevo15. , sleva udesno

Unarni operatori +, –, ∗ & imaju visi prioritet od svojih binarnih analogona.

66 6. Osnovni tipovi podataka

7

Formalni opis konstrukcijajezika

Postoje dva nacina da se definisu sintaksno ispravne konstrukcije vestackog jezika,na primer identifikatora, konstante, izraza, i sl. Ako je jezik konacan (i mali),moguce je formirati spisak svih niski (reci) jezika. Jedan primer takvog jezika jejezik saobracajnih znakova. Drugi takav primer je jezik nad azbukom A = {a, b}predstavljen sledecim skupom reci: {a, b, aa, bb, ab, ba, aaa, bbb}.

Ako je jezik veliki, i posebno ako je beskonacan, potrebno je zadati konacniskup pravila kojima se grade sve sintaksno ispravne konstrukcije jezika, tj. sve recijezika.

U matematici postoji oblast koja izucava tzv. formalne jezike, koji se, premaodredenim pravilima, izgraduju nad datom azbukom. Programski jezici su samojedan podskup skupa formalnih jezika. U opstem slucaju formalnih jezika, nacinza izgradnju ispravnih konstrukcija – reci jezika zadaje se formalizmom koji sezove formalna gramatika. Ovaj formalizam, pored azbuke samog jezika (skupazavrsnih simbola), koristi jos jedan skup simbola, disjunktan sa azbukom jezika,tzv. pomocnih simbola pomocu kojih se izgraduju ispravne reci jezika. Tu je,naravno, i skup pravila, koja opisuju kako se ispravne konstrukcije jezika grade.

7.1 Formalna gramatika

Ilustrujmo formalizam formalnih gramatika prvo jednim primerom.

Primer 1.Posmatrajmo azbuku koja se sastoji od cifara dekadnog brojnog sistema i

znakova aritmetickih operacija +,−, tj. A = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +,−}, i pos-matrajmo cele brojeve nad ovom azbukom. Tako, na primer, niske +1205, 1205 i−1205 jesu celi brojevi, a niske 12+05, 1205+, 12−05, 1205− to nisu. Jezik celih

67

68 7. Formalni opis konstrukcija jezika

dekadnih brojeva (sa dopustenim nevazecim nulama) moze se izgraditi nad ovomazbukom primenom sledecih pravila:

1. broj je neoznacen ceo broj, + neoznacen ceo broj, ili − neoznacen ceo broj;

2. neoznacen ceo broj je cifra, ili neoznacen ceo broj na koji je dopisana cifra;

3. cifra je svaki simbol iz skupa {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}.

U izgradnji reci ovog jezika (celih dekadnih brojeva) ucestvuju pojmovi ”broj”,”neoznacen ceo broj”, ”cifra” ( ili, mozemo ih oznaciti simbolima B, b, c), koji cinepomocni skup simbola. Reci se izgraduju primenom navedenih pravila, a u izgradnjireci polazi se upravo od pomocnog simbola ”broj” tj. B, jer je to osnovni objekatjezika koji gradimo. Umesto recenicama prirodnog jezika pravila zapisujemo krace– i preciznije, na sledeci nacin:

1’. B −→ b|+ b| − b;

2’. b −→ c|bc;3’. c −→ 0|1|2|3|4|5|6|7|8|9;

Polazeci od pocetnog simbola – ceo dekadni broj (B), i primenjujuci praviladobicemo ispravne reci iz jezika, tj. korektne cele dekadne brojeve. Na primer,broj 1234 moze se izvesti iz pocetnog simbola B primenom nekih od navedenihpravila na sledece niske:

B ⇒ b ⇒ bc ⇒ bcc ⇒ bccc ⇒ cccc ⇒ 1ccc ⇒ 12cc ⇒ 123c ⇒ 1234.Proces izvodenja je zavrsen jer smo dobili rec – broj koji se sastoji samo od

slova azbuke nad kojom se jezik gradi. Ovo nije jedino izvodenje broja 1234, jer sei drugacijim redosledom zamene simbola c odgovarajucom cifrom moze dobiti istibroj (npr. . . . cccc ⇒ ccc4 ⇒ cc34 ⇒ c234 ⇒ 1234).

Takode, polazeci od pocetnog simbola i primenjujuci pravila ne moze se dobitinijedna niska koja ne pripada jeziku – npr. ne moze se dobiti niska 12+23.

Primenom navedenih pravila moze se dobiti svaki ceo dekadni broj. Ako jebroj n-tocifren, dovoljno je jedanput primeniti pravilo B −→ b(−b,+b), n − 1puta primeniti pravilo b −→ bc, jedanput pravilo b −→ c, i n puta pravilo oblikac −→(odgovarajuca cifra).

Formalna gramatika je uredena cetvorka (N,T, P, S), gde je:N – konacni skup pomocnih (nezavrsnih, neterminalnih) simbola koji se koriste

u izvodenju niski jezika (ali ne ucestvuju u samim niskama jezika);T – konacni skup zavrsnih (terminalnih) simbola – azbuka, tj. skup slova nad

kojim se definise jezik; uslov za skup T je da je N ∩ T = ∅.P – konacni skup pravila izvodenja niski nad N ∪ T iz drugih niski nad N ∪ T ,

tj. konacni podskup skupa (N∪T )∗N(N∪T )∗×(N∪T )∗; element (a, b) iz skupa Pzove se gramaticko pravilo i zapisuje se u obliku a → b. Niska a mora da sadrzi bar

7.2. Meta jezici 69

jedan element iz skupa pomocnih simbola (N), dok niska b moze biti proizvoljnaniska nad unijom skupova zavrsnih i pomocnih simbola.

S – pocetni simbol, S ∈ N .

Sada se za prethodni primer formalna gramatika moze definisati sledecimskupovima:

N = {c, b, B};T = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +,−};P = {c → 0, c → 1, c → 2, c → 3, c → 4, c → 5, c → 6, c → 7, c → 8,

c → 9, b → c, b → bc,B → b,B → +bB → −b};S = B.Za datu gramatiku G(N, T, P, S), gramaticka forma se definise na sledeci nacin:1. pocetni simbol S je gramaticka forma;2. ako je xyz gramaticka forma i y −→ u gramaticko pravilo, onda je xuz takode

gramaticka forma (to su sve niske koje se mogu dobiti iz S primenom pravila iz P ).Zavrsna niska ili niska generisana gramatikom je gramaticka forma koja ne

sadrzi pomocne simbole.Jezik generisan gramatikom je skup zavrsnih niski izvedenih iz pocetnog simbola

S.

7.2 Meta jezici

Programski jezici cine jedan pravi podskup skupa formalnih jezika. Njihova sintaksase zbog toga moze opisati sredstvima koja su pogodnija (od formalnih gramatika)za predstavljanje i jednostavnija za razumevanje. Ta sredstva su tzv. meta jezici.To su jezici kojima se opisuje jezik koji se izucava. Sam jezik koji se izucava, npr.programski jezik, zove se objekt jezik.

Kada je rec o prirodnom jeziku, onda se njegova sintaksa i semantika opisujutakode prirodnim jezikom, tj. i objekt jezik i meta jezik u slucju prirodnog jezikaje – taj prirodni jezik. Na primer, u gramatikama srpskog jezika opisuju se, opetrecenicama srpskog jezika, pravila koja vaze za konstrukciju pravilne recenice, zapromenu pojedinih vrsta reci, itd. U recniku srpskog jezika moze se naci znacenjepojedinacnih reci i fraza srpskog jezika.

Sa vestackim jezikom, i posebno programskim jezikom, stvar stoji bitnodrugacije. Na primer, za jezik saobracajnih znakova ”sintaksa” (izgled) kon-strukcija (saobracajnih znakova), s obzirom da ih je konacno mnogo, opisuje seeksplicitnim pobrojavanjem slika koje te znakove predstavljaju, dok se njihova ”se-mantika” (znacenje) opisuje prirodnim jezikom. Programski jezik je beskonacanjer se u njemu moze napisati beskonacno mnogo programa. Sintaksu programskogjezika moguce je takode opisati prirodnim jezikom, ali bi taj opis bio glomazan inajcesce neprecizan, kao sto pokazuje sledeci primer. Moze se reci: program naprogramskom jeziku C sastoji se od preprocesorskih kontrolnih linija (npr. #in-clude, #define) deklaracija globalnih promenljivih i definicija funkcija. Sledio biopis pravila po kojima se gradi definicija funkcije, preprocesorska kontrolna linija,

70 7. Formalni opis konstrukcija jezika

lista parametara, parametar, blok, iskaz, izraz, identifikator, itd. do najjednos-tavnijih konstrukcija jezika. Zato se za opisivanje sintakse programskog jezika neupotrebljava prirodni jezik vec neki namenski graden, pregledniji i jednostavnijijezik.

Za formalno opisivanje sintakse programskog jezika koriste se najcesce dva metajezika: Bekusova notacija (tj. Bekus-Naurova forma, BNF) i sintaksni dijagrami.

Formalno opisivanje semantike je dosta kompleksno, pa se po pravilu u praksi se-mantika opisuje vezivanjem za sintaksu, ili intuitivno, koriscenjem prirodnog jezika.

7.2.1 Bekus-Naurova forma

Bekus-Naurova forma je jedan meta jezik za formalno opisivanje sintakse program-skih jezika. U ovoj notaciji sintaksa programskog jezika opisuje se pomocu konacnogskupa metalingvistickih formula (MLF).

Metalingvisticka formula se sastoji iz leve i desne strane razdvojene specijalnim,tzv. ”univerzalnim” metasimbolom (simbolom metajezika koji se koristi u svimMLF) ”::=” koji se cita ”po definiciji je”, tj. MLF je oblika

A ::= a,gde je A – metalingvisticka promenljiva, a a – metalingvisticki izraz.

Metalingvisticka promenljiva je fraza prirodnog jezika u uglastim zagradama(<,>), i ona predstavlja pojam, tzv. sintaksnu kategoriju objekt-jezika. Onaodgovara pomocnom simbolu formalne gramatike. Na primer, u programskomjeziku, sintaksne kategorije su <program>, <ceo broj>, <cifra>, <znak broja>,<ime promenljive>, itd. U prirodnom jeziku, sintaskne kategorije su < rec>,<recenica>, <interpunkcijski znak>, itd. Metalingvisticka promenljiva ne pripadaobjekt jeziku.

”Sitnije” sintaksne kategorije nazivaju se leksickim kategorijama ili recima(imaju znacenje ali ne stoje samostalno; npr. identifikator, konstanta u program-skom jeziku). ”Krupnije” sintaksne kategorije nazivaju se recenicama (osim stoimaju odredeno znacenje, egzistiraju samostalno; npr. iskaz u programskom jeziku).

Metalingvisticki izraz se gradi od metalingvistickih promenljivih i metal-ingvistickih konstanti, uz koriscenje drugih specijalnih, tj. univerzalnih metal-ingvistickih simbola.

Metalingvisticke konstante su simboli objekt jezika. To su, na primer,0, 1, 2,+,−, ali i rezervisane reci programskog jezika, npr. IF, THEN, BEGIN,FUNCTION, itd.

Metalingvisticki izraz moze se sastojati od jedne metalingvisticke promenljiveili jedne metalingvisticke konstante, a moze se izgraditi i na jedan od sledeca dvanacina:

1. na vec formirani metalingvisticki izraz dopise se ML promenljiva ili ML kon-stanta i tako se dobije novi ML izraz;

2. konacni niz prethodno formiranih ML izraza razdvojenih specijalnim tj. uni-verzalnim metasimbolom ”|” (cita se ”ili”) predstavlja novi ML izraz.

7.2. Meta jezici 71

Metalingvisticka formula A ::= a ima znacenje: ML promenljiva A po definicijije ML izraz a.

Svaka metalingvisticka promenljiva koja se pojavljuje u metalingvistickomizrazu a mora se definisati posebnom MLF.

Primer 2.Jezik celih brojeva u dekadnom brojnom sistemu moze se opisati sledecim

skupom MLF:<ceo broj >::=<neoznacen ceo broj > | <znak broja> <neoznacen ceo broj><neoznacen ceo broj>::=<cifra> | <neoznacen ceo broj><cifra><cifra>::= 0|1|2|3|4|5|6|7|8|9<znak broja>::= +|−Navedene MLF mogu se procitati na sledeci nacin:Ceo broj je po definiciji neoznacen ceo broj ili znak broja za kojim sledi

neoznacen ceo broj.Neoznacen ceo broj je po definiciji cifra ili neoznacen ceo broj za kojim sledi

cifra.Cifra je po definiciji 0 ili 1 ili 2 ili 3 ili 4 ili 5 ili 6 ili 7 ili 8 ili 9.Znak broja je po definiciji + ili −.

Upotreba univerzalnog metasimbola ”|” samo skracuje zapis MLF a ne povecavaizrazajnu moc notacije. Tako, na primer, prva MLF ima znacenje ekvivalentnoznacenju sledece dve MLF:

<ceo broj> ::= <neoznacen ceo broj><ceo broj> ::= <znak broja><neoznacen ceo broj>

Radi kraceg zapisa i pojednostavljenja MLF uvode se razne modifikacijeBekusove notacije. One se postizu uvodenjem novih metasimbola (simbola metajezika). Jedna takva modifikacija, poznata kao prosirena Bekus-Naurova forma,(EBNF – Extended Backus Naur Form) ukljucuje male, srednje i velike (viticaste)zagrade, sa sledecim znacenjem:

– navodenje konstrukcije izmedu otvorene i zatvorene viticaste zagrade {. . . }definise ponavljanje navedene konstrukcije 0 ili vise puta; na primer,

<neoznacen ceo broj>::=<cifra>{<cifra>}(neoznacen ceo broj sastoji se od jedne cifre za kojom moze da sledi proizvoljni nizcifara);

– navodenje konstrukcije izmedu otvorene i zatvorene srednje zagrade [. . . ]definise opciono pojavljivanje konstrukcije (njeno pojavljivanje 0 ili 1 put); naprimer,

<ceo broj>::= [<znak broja>]<neoznacen ceo broj>(ceo broj je neoznacen ceo broj ispred koga se moze (ali i ne mora) navesti znakbroja);

– navodenje konstrukcija izmedu otvorene i zatvorene male zagrade (. . . )definise grupisanje konstrukcija; na primer,

<ceo broj> ::= [(+|−)] <cifra>{<cifra>}

72 7. Formalni opis konstrukcija jezika

(ceo broj je cifra za kojom sledi proizvoljni niz cifara, a kojoj moze (ali i ne mora)da prethodi znak + ili −).

Ako simboli zagrada (malih, srednjih, velikih) mogu da pripadaju i objektjeziku, njihovo koriscenje kao metasimbola se oznacava njihovim podvlacenjem.

7.2.2 Primer – sintaksa izraza

Prioriteti operatora odrazeni su u sintaksi izraza. Slede neke od metalingvistickihformula kojima se u Bekus Naurovoj formi opisuje sintaksa izraza u C-u:

7.2. Meta jezici 73

<izraz > ::= <iz.dodele> | (najnizi prioritet<izraz>,<iz.dodele> operatora ”,”)

<iz.dodele> ::= <usl.izraz> | (sledeci prioritet imaju<un.izraz> <op.dodele><iz.dodele> dodela i operator ?:)

<op.dodele> ::= =, ∗ =, / =, %=, + =, − =, . . .

<usl.izraz> ::= <OR izraz> |<OR izraz> ? <izraz> : <usl.izraz>

<OR izraz> ::= <AND izraz> | (visi prioritet<OR izraz> || <AND izraz> od OR izraza)

<AND izraz> ::= <poredenje> |<AND izraz> && <poredenje>

<poredenje> ::= <rel.izraz> |<poredenje> == <rel.izraz> | (nizi prioritet od<poredenje> ! = <rel.izraz> operatora uredenja)

<rel.izraz> ::= <adit.izraz> |<rel.izraz> < <adit.izraz> | (vis prioritet od<rel.izraz> > <adit.izraz> | operatora jednakosti)<rel.izraz> <= <adit.izraz> |<rel.izraz> >= <adit.izraz> |

<adit.izraz> ::= <multip.izraz> |<adit.izraz> + <multip.izraz> | (nizi prioritet od<adit.izraz> – <multip.izraz> operatora umnozavanja)

<multip.izraz> ::= [(tip)] <un.izraz> |<multip.izraz> ∗ [(tip)] <un.izraz> | (visi prioritet od<multip.izraz> / [(tip)] <un.izraz> | operatora dodavanja<multip.izraz> % [(tip)] <un.izraz>

<un.izraz> ::= <post izraz> |++<un.izraz> | (unarni operatori su−−<un.izraz> | najviseg prioriteta)<un.operator> [(tip)]<un.izraz>

<un.operator> ::= &, ∗, +, –, , !

<post izraz> ::= <prim.izraz> |<post izraz>[<izraz>] (element niza)<post izraz>(<lista argumenata>) (poziv funkcije)<post izraz>.<identifikator> (polje strukture)<post izraz>→<identifikator> (polje strukture)<post izraz>++<post izraz>−−

<prim.izraz> ::= <identifikator> |<konstanta><string>(<izraz>)

74 7. Formalni opis konstrukcija jezika

8

Iskazi – upravljanje

Iskazima se opisuje sustinski koncept programskog jezika – radnja, akcija. Iskazomse saopstava racunaru da treba da uradi nesto sa podacima.

U programskom jeziku C, svaki izraz postaje iskaz kada se dopuni karakterom’;’, npr.

x=0;i++;printf(. . . );

Strukturni iskazi programskog jezika su oni koji se sastoje od drugih, kompo-nentnih iskaza. Iskazi koji nisu strukturni jesu jednostavni (primitivni, prosti)iskazi.

Strukturni iskazi predstavljaju, pre svega, upravljacke ili kontrolne strukture,tj. iskaze koji upravljaju (ili kontrolisu) izvrsenjem iskaza od kojih se sastoje.

Osnovne upravljacke strukture su one koje obezbeduju da se, njihovim kombino-vanjem, zapise proizvoljni algoritam. To su serijska struktura, koja proizvodi redno(serijsko) izvrsenje komponenti, selektivna struktura koja proizvodi izvrsenje jedneod komponenti u zavisnosti od ispunjenosti zadatog uslova, i repetitivna strukturakoja proizvodi ponovljeno izvrsenje komponentnih iskaza.

8.1 Iskaz dodele

Osnovni iskaz proceduralnih programskih jezika je iskaz dodele:a ← Ψ,

gde je a – identifikator promenljive, a Ψ – izraz cija se vrednost izracunava, trans-formise u tip promenljive a i dodeljuje kao nova vrednost promenljivoj a. Pri tomese stara vrednost promenljive a gubi.

Razne sintakse iskaza dodele ukljucuju sledece zapise:a := Ψa = Ψ

ili dijagramski, slika 8.1.

75

76 8. Iskazi – upravljanje

?

a ← Ψ

?

Figure 8.1: dijagramski prikaz iskaza dodele

Iskaz dodele moze se okarakterisati svojim preduslovom i svojim pos-tuslovom.

Na primer (slika 8.2), formalna specifikacija iskaza dodele i ← j + 1 moze sezapisati i u obliku:

{j > 1}i ← j + 1{i > 2}

?

i ← j + 1

?

Qr {j > 1 – preduslov}

Rr {i > 2 – postuslov}

Figure 8.2: primer iskaza dodele; predsulov i postuslov

Moze se uociti da i predulsov {i > 0, j > 1} obezbeduje isti postuslov {i > 2} uslucaju prethodnog iskaza dodele, tj. {i > 0, j > 1}i ← j + 1{i > 2}

Uopste, da bi vazio postuslov R iskaza dodele a ← Ψ, mora vaziti preduslovQ = Ra

Ψ, tj. mora vaziti relacija (odnos izmedu promenljivih) R u kojoj jesvako pojavljivanje promenljive a zamenjeno izrazom Ψ. Ovo tvrdenje se zapisuje{Ra

Ψ}a ← Ψ{R}, i naziva se aksioma dedele. Na primer,{i > 0}i ← i + 1{i > 1}, jer je Ri

i+1 ≡ i + 1 > 1 ≡ i > 0 ≡ Q.Razni preduslovi jednog iskaza dodele obezbeduju vazenje zadatog postuslova.

Relacija Q = RaΨ obezbeduje tzv. najslabiji preduslov (engl. wp – weakest

precondition), tj. wp(a ← Ψ, R) = RaΨ.

U programskom jeziku C, pored osnovnog iskaza dodele postoje i iskaze dodele saaritmetickim operatorima (+=, −=, ∗=, /=, %=) i bitovskim logickim operatorima(&=, ˆ=, |=, <<=, >>=). Takvi iskazi dodele imaju oblik a += Ψ, a −= Ψ, a∗= Ψ, a /= Ψ, a %= Ψ, a &= Ψ, a ˆ= Ψ, a |= Ψ, a <<= Ψ, a >>= Ψ, gdeje a – promenljiva a Ψ – izraz. Ovim iskazima dodele promenljivoj a dodeljuje sevrednost izraza koji se dobije kada se binarni operator uz dodelu (+, −, ∗, . . . )primeni na vrednost promenljive a kao levi argument, a izraz Ψ – kao desni. Dakle,

8.2. Serijski komponovani iskaz 77

ovi iskazi dodele ekvivalentni su iskazima ”obicne” dodele oblika a = a + Ψ, a = a− Ψ, a = a ∗ Ψ, a = a / Ψ, a = a % Ψ, a = a & Ψ, a = a ˆ Ψ, a = a | Ψ, a = a<< Ψ, a = a >> Ψ, redom.

8.2 Serijski komponovani iskaz

Serijski komponovani iskaz je oblikaS1;S2;. . .Sn;

gde su S1; S2; . . . , Sn; – iskazi.

Obicno se komponentni iskazi ”zagraduju” nekim parom oznaka, npr. pocetak,kraj, ili, u Pascal-u, begin, end, ili, u C-u, zagradama ”{”, ”}”:

{S1;S2;. . .Sn;

}U C-u, komponovani serijski iskaz zove se i blok, i u njemu se mogu deklarisati

promenljive lokalne za taj blok. Dijagramski, ovaj iskaz se predstavlja semom naslici 8.3.

Vazenje preduslova Q0 serijskog komponovanog iskaza obezbeduje vazenje nje-govog postuslova Qn, ako vazenje relacije Qi pre izvrsenja komponentnog iskazaSi+1 obezbeduje vazenje njegovog postuslova Qi+1, za i = 0, 1, . . . , n− 1.

Na primer, na ovaj nacin dobija s zakljucak o korektnosti swap-algoritma (pro-grama) – programa za razmenu vrednosti dve promenljive x, y:

Iz{x = X ∧ y = Y }t ← x{x = X, y = Y, t = X},{x = X ∧ y = Y ∧ t = X}x ← y{x = Y, y = Y, t = X},{x = Y ∧ y = Y ∧ t = X}y ← t{x = Y, y = X, t = X},

(X,Y su konstante, x, y, t – promenljive),sledi{x = X ∧ y = Y }t ← x;x ← y; y ← t{x = Y, y = X}

8.3 Uslovni iskazi (selektivna, alternirajuca up-ravljacka struktura)

Uslovni iskaz je oblikaako p onda S1 inace S2, ili, u sintaksi C-a,if (p)

78 8. Iskazi – upravljanje

?

S1

S2

Sn

?

?

?

?

...

Q0r

Q1r

Q2r

Qn−1r

Qnr

Figure 8.3: serijski komponovani iskaz

S1;else

S2;gde je p – logicki izraz , a S1;, S2; su iskazi. Deo else moze da se izostavi. Ako jevrednost logickog izraza p – tacno (tj. u C-u ima vrednost razlicitu od 0), izvrsavase iskaz S1;, a ako je vrednost logickog izraza p – netacno (tj. u C-u ima vrednost0), i ako postoji else deo, izvrsava se iskaz S2;.

Dijagramski, ovaj iskaz se predstavlja semom na slici 8.4.

Uslovni iskaz moze imati i nepotpuni oblik, dijagramski prikazan na slici 8.5.

Komponentni iskazi S1;S2; u uslovnom iskazu mogu biti proizvoljni iskazi, pa idrugi uslovni iskazi. Posebno, moze se dogoditi da je prvi komponentni iskaz (S1;)potpunog uslovnog iskaza – nepotpuni uslovni iskaz, ili da je jedini komponentniiskaz nepotpunog uslovnog iskaza – potpuni uslovni iskaz, tj. moze se dobiti iskazkoji se u sintaksi C-a zapisuje u obliku

if (p) if (p1) S3; else S4;

pri cemu nije jasno da li ”else” grana pripada ”unutrasnjem” ili ”spoljasnjem” ifiskazu, tj. da li ovaj iskaz odgovara dijagramu na slici 8.6 ili dijagramu na slici 8.7.

8.3. Uslovni iskazi (selektivna, alternirajuca upravljacka struktura) 79

?

?

¡¡@@

@@¡¡

p

S1 S2

¾?

Qr

Rr

DA

NE

Figure 8.4: uslovni iskaz

?¡¡@@

@@¡¡

p

?

?

S1

¾

Qr

Rr

DA

NE

Figure 8.5: nepotpuni uslovni iskaz

Ovakva dvoznacnost resava se specificnim konvencijama (dogovorima) u okviruspecificnog programskog jezika. Na primer, u C-u, ovaj iskaz pridruzuje jedino elsenajblizem if (odgovara dijagramu na slici 8.6), tj. ima znacenje

if (p){

if (p1) S3; else S4;}

Drugo znacenje se moze ostvariti eksplicitnim zagradivanjem tj. sintaksom ob-lika

if (p){

if (p1) S3;}

else S4;

80 8. Iskazi – upravljanje

?

?

¡¡@@

@@¡¡

p

?

S4

?¡¡@@

@@¡¡

p1

S3

¾

DA

NE

DA

NE

Figure 8.6: kombinovanje potpunog i nepotpunog uslovnog iskaza – slucaj 1

koja sada odgovara dijagramu na slici 8.7.Posebno cest slucaj visestruke ”odluke” pri grananju je drugi if-iskaz u else delu

if-iskaza, tj. visestruki if-iskaz ima oblikif (p1)

S1;else if (p2)

S2;else if (p3)

. . .else

S;

Tacnost jednog od uslova pi rezultuje izvrsenjem odgovarajuceg iskaza Si cimese zavrsava izvrsenje celog visestrukog if-iskaza.

Na primer, u funkciji BinarPret (v. 5.3), visestruki if-iskaz koristi se za od-luku da li je vrednost kljuca u sredini sortiranog (pod)niza manja, veca ili jednakatrazenoj vrednosti:

int BinarPret(slog A[ ], int n, int k){

int l=0, d=n-1,s;while(l <= d) {

s = (l + d)/2;if(k < A[s].kljuc) d=s-1;else if(k > A[s].kljuc) l=s+1;else return(s);

8.3. Uslovni iskazi (selektivna, alternirajuca upravljacka struktura) 81

?

?

¡¡@@

@@¡¡

p

?

?

S4

?¡¡@@

@@¡¡

p1

S3

¾

DA

NE

DA

NE

Figure 8.7: kombinovanje potpunog i nepotpunog uslovnog iskaza – slucaj 2

}return(NEUSPEH);

}

8.3.1 Uslovni iskaz sa visestrukim grananjem

Uslovni iskaz omogucuje izbor jednog od dva iskaza na osnovu dva iskljuciva uslova,p, ¬p – ili je vrednost logickog izraza tacno, ili je netacno. U nekim slucajevimapotreban je izbor jednog od konacnog broja (n) iskaza (akcija), i to na osnovu jed-nakosti izraza sa jednim od konacnog broja – n konstantnih celobrojnih vrednosti.

Tada odgovarajuci selektivni iskaz visestrukog grananja (tzv. prekidac – engl.switch) u C-u ima oblik:

switch (i) {case i1: S1;case i2: S2;. . .case in: Sn;default: S;

}Na primer, sledeci iskaz analizira karakter c i uvecava broj pojavljivanja odgo-

varajuce cifre, beline ili ostalih karaktera, u zavisnosti od toga da li je karakter ccifra, belina ili nesto trece:

switch (c) {

82 8. Iskazi – upravljanje

case ’0’: case ’1’: case ’2’: case ’3’: case ’4’:case ’5’: case ’6’: case ’7’: case ’8’: case ’9’:

brcif[c–’0’]++;break;

case ’ ’:case ’\n’:case ’\t’:

brbel++;break;

default:brost++;break;

}Iskaz visestrukog grananja je uopstenje uslovnog iskaza na izbor jedne od

konacno mnogo akcija – komponentnih iskaza. Iskaz se sastoji od jednog izraza – se-lektora i liste iskaza, od kojih svaki ima jedno ili vise obelezja slucaja – konstantnihcelobrojnih vrednosti. U prethodnom primeru, selektor je promenljiva c znakovnogtipa (sa celobrojnom vrednoscu!), a u zavisnosti od vrednosti promenljive c u vremeizvrsavanja iskaza, izvrsice se jedan od komponentnih iskaza – onaj cije je obelezjejednako vrednosti promenljive c; ako takav iskaz, odnosno obelezje, ne postoji, tj.ako karakter c nije ni cifra ni belina, izvrsava se podrazumevani – default – iskaztj. uvecanje broja ”ostalih” karaktera.

Posle izvrsenja izabranog komponentnog iskaza, izvrsenje se nastavlja nasledecem slucaju, osim ako se posle komponentnog iskaza navede iskaz bezuslovnogskoka break; on rezultuje momentalnim zavrsavanjem prekidackog (switch) iskaza.

8.4 Repetitivni iskazi

Repetitivni iskazi su iskazi kojima se realizuje kontrolna struktura ponavljanja kom-ponentnih iskaza. Ovi iskazi sadrze jedan logicki izraz – uslov i niz komponentnihiskaza (ili jedan, proizvoljno kompleksan iskaz) cije se izvrsavanje ponavlja sve dokje uslov ispunjen.

U programskom jeziku C postoji iskaz ciklusa u kome se prvo proverava tacnostuslova pa se onda, ako je uslov tacan, izvrsavaju komponentni iskazi (tzv. iskazciklusa sa pred-proverom uslova, while - iskaz), i iskaz ciklusa u kome sekomponentni iskazi izvrsavaju pre nego sto se proverava istinitost uslova, a zatim,ako je uslov jos uvek ispunjen, komponentni iskazi se ponovo izvrsavaju (tzv. iskazciklusa sa post-proverom uslova, do-while iskaz).

Za komponentne iskaze repetitivnih iskaza koriste se termini ”ciklus” i ”petlja”.Jedna specificna struktura iskaza ciklusa sa pred-proverom uslova je posebno

cesta pa je izdvojena u poseban iskaz – for iskaz. To je struktura while iskaza ukome se, posle pocetne dodele vrednosti promenljivoj iz uslova, izracunava uslov, i

8.4. Repetitivni iskazi 83

sve dok je tacan ( 6= 0), izvrsava se ciklus i dodeljuje nova vrednost promenljivoj izuslova.

8.4.1 Iskaz ciklusa sa pred-proverom uslova

Ovaj iskaz je oblikadok je p uradi S

ili, u sintaksi C-a,while (p) S;U ovom iskazu p je logicki izraz a S – iskaz.

Ako se uoci invarijantni predikat (relacija) P za iskaz S, tj. relacija P za kojuvazi {P ∧ p} S {P}, onda se za repetitivni iskaz sa pred-proverom uslova mozeutvrditi odnos (medu njenim promenljivim) iskazan slikom 8.8.

?¡¡@@

@@¡¡

p

?

S

-

?

P

P

rr

P ∧ pr

Pr P ∧ ¬pr

DA

NE

Figure 8.8: iskaz ciklusa sa pred-proverom uslova

Problem je pronaci invarijantni predikat P – staticku relaciju dinamickogprocesa petlje.

Primer – mnozenje dva nenegativna cela brojaRazviti program za mnozenje dva nenegativna cela broja.

Formalna specifikacija ovog problema je oblika:{x, y ∈ N ∪ {0}} → {z = x ∗ y}Resenje problema sastoji se iz dva koraka: izgraditi program za resavanje prob-

lema i dokazati korektnost tog programa tako sto ce se, uocavanjem veza kojepostoje medu promenljivim u raznim tackama izvrsenja programa, doci do logickogizraza sa vrednoscu T u krajnjoj tacki izvrsavanja programa, koji je jednak pos-tuslovu.

Za svaki problem, pa i za ovaj koji razmatramo, postoji veci broj algoritama.Algoritam za nas problem polazi od cinjenice da je mnozenje skraceno sabiraje,i moze da se izgradi iterativno (postupno), i to tako sto ce se na medurezultat,

84 8. Iskazi – upravljanje

koji je na pocetku = 0, dodavati x puta vrednost y. Dakle, z = y + y + . . . y (xputa). Algoritam mora da uvede pomocnu promenljivu koja ce brojati te iteracije(dodavanja), i to ili broj jos potrebnih dodavanja (koji je na pocetku x a smanjujese za po 1 sve dok ne postane 0), ili broj ostvarenih dodavanja (koji je na pocetku0 a povecava se za po 1 dok ne postane = x).

Dakle, mi cemo za nas problem razviti dva algoritma. Svaki od njih ce daobezbedi da se, polazeci od zadatog preduslova (x, y ∈ N ∪ {0}), izvrsavanjemalgoritma, dobija vazenje postuslova {z = x ∗ y}.

Algoritam 1Neka je promenljiva koja broji jos potrebna dodavanja u. Algoritam (program)

tada ima sledeci oblik:

{z = 0;u = x;while (u > 0) {

z = z + y;u = u− 1;

}}Kada smo vec, na intuitivan nacin, dosli do ovog algoritma, treba ispitati (tj.

dokazati) njegovu korektnost, tj treba se uveriti da ce se, za vrednosti ulaznihpromenljivih (x, y) koje zadovoljavaju pocetni preduslov (x, y ∈ N ∪{0}) algoritamzavrsiti i da ce na kraju vaziti trazeni postuslov (z = x ∗ y).

To se moze ustanoviti uocavanjem invarijante while petlje koja odrazavafilozofiju naseg resenja:

P: {z + u ∗ y = x ∗ y, u ≥ 0}.Naime, kada se na medurezultat z jos potreban broj puta (u) doda vrednost

y, dobice se proizvod brojeva x i y. Na pocetku svakog izvrsenja petlje vazice daje u > 0 (jer se inace petlja ne izvrsava), a kada se iz petlje izade vazice negacijatog uslova tj. u = 0. Zato ce i invarijanta u tom trenutku (toj tacki) imati oblikz + 0 ∗ y ≡ z = x ∗ y, a to je upravo zeljeni postuslov.

Sada algoritam moze da se obelezi relacijama koje vaze u pojedinim njegovimkoracima (zapisane kao komentari iza iskaza posle cijeg izvrsenja vaze):

Specifikacija: {x, y ∈ N ∪ {0}} → {rezultat z = x ∗ y}{

z = 0; u = x; /∗ z + u ∗ y = x ∗ y, u ≥ 0 ∗/while (u > 0) {

z = z + y; /∗ z + (u− 1) ∗ y = x ∗ y, u > 0 ∗/u = u− 1; /∗ z + u ∗ y = x ∗ y, u ≥ 0 ∗ /

}} /∗ z = x ∗ y ∗/Graficki, (slika 8.9).

8.4. Repetitivni iskazi 85

u ← u− 1

z ← z + y

u ← x

z ← 0

HHH©©©

©©©HHH

u > 0

-

½¼

¾»kraj

NE {u = 0}{z + u ∗ y = x ∗ y, u = 0(z = x ∗ y)}

DA

{z + u ∗ y = x ∗ y, u ≥ 0}

{z + (u− 1) ∗ y = x ∗ y, u > 0}

{z + u ∗ y = x ∗ y, u ≥ 0}

Figure 8.9: Dijagramski prikaz algoritma za mnozenje dva broja uzastopnim doda-vanjem – prvo resenje

Algoritam 2Neka je n promenljiva koja broji izvrsena dodavanja y-a na medurezultat. Al-

goritam tada ima sledeci oblik:

{z = 0;n = 0;while (n < x) {

z = z + y;n = n + 1;

}}Da bismo dokazali korektnost ovog algoritma, uocimo invarijantu while

petlje koja odrazava filozofiju ovog, drugog resenja:P: {z = n ∗ y, n ≤ x}.

Naime, u svakom trenutku izvrsavanja petlje, medurezultat z sadrzi n puta dodatsabirak y, sve dok je n ≤ x. Kada se sa n dode do x, dobice se da je z jednak basproizvodu brojeva x i y.

Sada algoritam moze da se obelezi relacijama koje vaze u pojedinim njegovimkoracima:

Specifikacija: {x, y ∈ N ∪ {0}} → {rezultat z = x ∗ y}

86 8. Iskazi – upravljanje

{z = 0; n = 0; / ∗ z = n ∗ y, n ≤ x ∗ /while (n < x) {

z = z + y; / ∗ z = (n + 1) ∗ y, n < x ∗ /n = n + 1; / ∗ z = n ∗ y, n ≤ x ∗ /

}/ ∗ n ≤ x, n ≥ x, z = n ∗ y ⇒ z = x ∗ y ∗ /

}Graficki, (slika 8.10).

n ← n + 1

z ← z + y

n ← 0

z ← 0

HHH©©©

©©©HHH

n < x

-

½¼

¾»kraj

NE {n = x}{z = n ∗ y, n = x(z = x ∗ y)}

DA

{z = n ∗ y, n ≤ x}

{z = (n + 1) ∗ y, n < x}

{z = n ∗ y, n ≤ x}

Figure 8.10: Dijagramski prikaz algoritma za mnozenje dva broja uzastopnim do-davanjem – drugo resenje

8.4.2 For iskaz

Iskaz ciklusa sa parametrom – for iskaz – veoma je slican while iskazu, a izbor jednogod njih, osim sto je stvar ukusa, zavisi od prirode akcije koju treba da realizuju.

Vecina proceduralnih programskih jezika ima neki oblik iskaza ciklusa saparametrom. On ukljucuje parametar, iskaz koji se u ciklusu ponavlja, i uslovkoji treba da je ispunjen (tacan) da bi se iskaz u ciklusu ponavljao. Komponenteovog iskaza su inicijalna dodela vrednosti parametru, a zatim, ponovljeno, svedok je uslov definisan za parametar tacan, izvrsenje iskaza u ciklusu i promenavrednosti parametra.

Dakle, apstraktni oblik for iskaza je

8.4. Repetitivni iskazi 87

for (i=poc vrednost, uslov(i), i=nova vrednost) <iskaz>

Razni programski jezici vezuju specificnu sintaksu i semantiku za for iskaz. Nekizahtevaju obavezno prisustvo svih njegovih komponenti i strogo kontrolisanu inici-jalnu dodelu i promenu vrednosti parametra. Tako, na primer, u Pascal-u, param-etar ciklusa mora da bude promenljiva skalarnog tipa, a promena vrednosti je im-plicitna i moze da bude samo dodela sledece ili prethodne vrednosti. Zato je for-iskaz u Pascal-u dobro definisan, uvek se zavrsava i zna se broj ponavljanja iskazau ciklusu. Drugi programski jezici, kao sto je programski jezik C, dopustaju flek-sibilnost tako da pojedine komponente mogu da se izostave, a promena vrednostiparametra moze da ima proizvoljan oblik. U programskom jeziku C, sta vise, nemora ni da bude prisutan koncept parametra kao promenljive, vec su inicijalna do-dela i promena vrednosti – proizvoljni izrazi opsteg tipa. Zato je for iskaz slicnijiwhile iskazu, ne mora da se zavrsava a i ako se zavrsava ne moze se odrediti (uopstem slucaju) broj ponavljanja iskaza u ciklusu.

U programskom jeziku C for iskaz je oblikafor(izraz1; izraz2; izraz3)

iskaz

i ekvivalentan je sledecem paru iskaza (osim sto se iz for-iskaza moze ”prinudno”izaci iskazima bezuslovnog skoka – break, continue, goto):

izraz1;while (izraz2) {

iskazizraz3;

}

Izrazi izraz1, izraz2, izraz3 su proizvoljni izrazi. Ipak, najcesce su izraz1 i izraz3– dodele ili pozivi funkcija, dok je izraz2 – logicki izraz. Svaki od izraza moze dase izostavi, ali znakovi ’;’ moraju da ostanu. Tako je iskaz

for (;;) {. . .}

iskaz beskonacne petlje (osim ako se u okviru ciklusa ne navede iskaz bezuslovnogskoka).

Dok se while iskaz koristi u slucajevima kada nema inicijalne dodele i promenevrednosti, na primer

while ((c=getchar()) == ’ ’ || c==’\n’ || c==’\t’);/∗ preskociti beline, tabulatore i znake za novi red ∗/

for iskaz se koristi kada su te aktivnosti prisutne, na primerfor(i=0; i<n; i++)

blok/∗ ponavljanje bloka iskaza za sve vrednosti i od 0 do n–1 ∗/

88 8. Iskazi – upravljanje

8.4.3 Iskaz ciklusa sa post-proverom uslova

Ovo je iskaz oblikaponavljaj S dok p

ili, u sintaksi C-a,

doS

while (p);

Opet, p je logicki izraz a S – iskaz.Iskaz S se izvrsava jednom bezuslovno, a zatim, sve dok je vrednost logickog

izraza p – tacno (6= 0), iskaz S se ponovo izvrsava. (slika 8.11).

Neka je invarijanta ciklusa sa iskazom S relacija P (relacija P vazi posle svakogizvrsenja iskaza S u ciklusu). Ako za relaciju P uocimo preduslove:

{Q}S{P}, {P ∧p} S {P}, tada se odnos preduslova i postuslova, tj. invarijantapetlje iskaza ciklusa sa post-proverom uslova moze prikazati slikom 8.11.

?

¡¡@@

@@¡¡

p

S

-

?

Qr

Pr

P ∧ ¬prNE

DA

Figure 8.11: iskaz ciklusa sa post-proverom uslova – preduslov, invarijanta petlje ipostuslov

Iskaz ciklusa sa post-proverom uslova je analogan repeat-until iskazu Pascal-a,osim sto se ciklus ponavlja sve dok je uslov tacan (kod repeat-until iskaza, ciklusse ponavlja dok uslov ne postane tacan).

Iskaz do-while se rede koristi od while iskaza ali u slucajevima kada se ciklusprema prirodi problema izvrsava bar jednom – i to bezuslovno, prirodno je koristitido-while iskaz.

Primer – Euklidov algoritam

Rec je o Euklidovom algoritmu za odredivanje najveceg zajednickog deliocadva prirodna broja. Prikazimo prvo izvrsavanje algoritma na jednom primeru.Pretpostavljamo da su elementarne operacije algoritma mnozenje i deljenje.

8.4. Repetitivni iskazi 89

Naci najveci zajednicki delilac (nzd) brojeva 14 i 5.14:5=2(4); (14 podeljeno celobrojno sa 5 jeste 2 i ostatak pri deljenju je 4);5:4=1(1);4:1=4(0).Dakle, nzd(14,5)=nzd(5,4)=nzd(4,1)=1.

Specifikacija:{a, b ∈ N ∪ {0}} → {rezultat : nzd(a, b)}Algoritam se zasniva na sledecem razmatranju: ako su brojevi a i b razliciti, naci

ostatak pri celobrojnom deljenju veceg manjim. Zatim, sve dok ostatak ne bude= 0, ponoviti celobrojno deljenje delioca i ostatka iz prethodnog deljenja. Ako sedeljenik oznaci kao ”prvi” broj a delilac kao ”drugi”, onda se algoritam zasniva napretpostavci da je nzd(prvi, drugi) = nzd(drugi, ostatak). Algoritam je prikazanna slici 8.12.

drugi ← ost

prvi ← drugi

ost ← prvi− kol ∗ drugi

kol ← prvi / drugi

drugi ← b

prvi ← a

HHH©©©

©©©HHH

ost <> 0

PPPPP³³³³³

³³³³³PPPPP

prvi < drugi

¾razmena (prvi, drugi)

DA

NE-

nzd ← drugi

½¼

¾»kraj

{nzd(a, b) = nzd(prvi, drugi)} – trivijalno

{nzd(a, b) = nzd(prvi, drugi)}

{nzd(a, b) = nzd(prvi, drugi)}

{nzd(a, b) = nzd(prvi, drugi)}

NE{nzd(a, b) = drugi}

DA {nzd(prvi, drugi) = nzd(drugi, ost)}{⇒ nzd(drugi, ost) = nzd(a, b)}

Figure 8.12: Euklidov algoritam – deljenje

90 8. Iskazi – upravljanje

Da bi se dokazale relacije u navedenim tackama algoritma, potrebno je dokazatisledece:

1. nzd(a, b) = nzd(b, a) (npr. nzd(5, 14) = nzd(14, 5))

2. nzd(a, b) = b ≡ b|a, tj. a : b = kol(0)(ost = 0) (nzd(a, b) = b ako je b delilacod a)

3. nzd(a, b) = nzd(prvi, drugi) – invarijanta ciklusa (petlje)

4. nzd(prvi, drugi) = nzd(drugi, ost)

Prve dve tacke dokazuju se trivijalno; tacka 3. sledi iz tacke 4. Da bi sejednakost iz tacke 4. dokazala potrebno je, za proizvoljne brojeve x, y ∈ N ∪ {0},dokazati jednakost

nzd(x, y) = nzd(y, ost), gde je x : y = k(ost), tj. x = y ∗ k + ostPretpostavimo da je nzd(x, y) = q (pretpostavka (1).Tada vazi i q|y, q|ost, zato sto je ost = x− y ∗ k(∈ N ∪ {0}), tj.q je zd(y, ost) (zajednicki delilac od y, ost).Ako postoji veci zajednicki delilac q1 za y, ost, (q1 > q), ondaq1|y, q1|ost ⇒ q1|x(= y ∗ k + ost) (q1 je i zd za y i x),pa q nije nzd(x,y), jer postoji q1 > q t.d. je q1 zajednicki delilac od x, y. To je

suprotno pretpostavci (1).Dakle, ne postoji q1 > q t.d. q1 jeste zd(y, ost), tj. q je i najveci zajednicki

delilac za y, ost (q = nzd(y, ost)).

Zavrsavanje: Kada je ost = 0, tada je nzd(prvi, drugi) = drugi (prema tacki2.).

Iz nzd(a, b) = nzd(prvi, drugi) tada imamo i nzd(a, b) = drugi.

Ako se, pored operacije celobrojnog deljenja, koristi i operacija odredivanja os-tatka pri celobrojnom deljenju, npr. % (kao u C-u), i ako se dodela promenljivimprvi, drugi izvrsi pre provere kraja ciklusa (ost <> 0), dobije se algoritam (pro-gram) sa iskazom ponavljanja sa post-proverom uslova oblika

{prvi = a; drugi = b;if (prvi < drugi) swap(prvi, drugi);do { /∗ NZD(a, b) = NZD(prvi, drugi) ∗/

ost = prvi % drugi;prvi = drugi;drugi = ost;

} while (ost! = 0);/∗ prvi = NZD(a, b) ∗/

}(na kraju je NZD(a, b) = prvi a ne drugi zato sto je izvrsena jedna suvisna izmenavrednosti promenljivih prvi, drugi).

8.4. Repetitivni iskazi 91

I promenljiva ost moze da se eliminise, pri cemu se dobije program sledecegoblika:

{prvi = a; drugi = b;do { {NZD(a, b) = NZD(prvi, drugi)}

prvi = prvi % drugi;swap(prvi, drugi);

} while (drugi! = 0);/∗prvi = NZD(a, b)∗/

}Primenom aksiome do – while iskaza moze se i formalno dokazati korektnost

ovih programa.

Slicno, ako se Euklidov algoritam izrazi operacijom oduzimanja (umesto del-jenja), on ima oblik na slici 8.13.

drugi ← z

prvi ← drugi

z ← prvi− drugi

(dodela vrednosti drugi, prvi− drugi

promenljivim prvi, drugi – redom

razmena (prvi, drugi)

drugi ← b

prvi ← a

PPPPP³³³³³

³³³³³PPPPP

prvi < drugi

PPPPP³³³³³

³³³³³PPPPP

prvi = drugi

nzd ← drugi

½¼

¾»kraj

¾

DA

NE

- {nzd(a, b) = nzd(prvi, drugi)}

{nzd(a, b) = nzd(prvi, drugi) ∗∗= nzd(drugi, prvi− drugi)}

{nzd(a, b) = nzd(prvi, drugi)}

NE

DA

Figure 8.13: Euklidov algoritam – oduzimanje

Potrebno je dokazati relaciju ∗∗, tj. jednakostnzd(prvi, drugi) = nzd(drugi, prvi− drugi):Kako je q = nzd(prvi, drugi), to q deli i prvi, i drugi, pa i njihovu razliku, tj.

q|drugi, q|prvi− drugi.

92 8. Iskazi – upravljanje

Pretpostavimo da q nije nzd(drugi, prvi − drugi). To znaci da postoji q1 > qt.d. q1 deli i drugi i prvi− drugi. Ali tada imamo da

q1|drugi, i q1|prvi, tj.q1 > q je zd(prvi, drugi), sto je suprotno pretpostavci da je q najveci takav (q =

nzd(prvi, drugi)). Dakle, iz protivurecnosti sledi da je q i nzd(drugi, prvi−drugi).

Kao i u realizaciji deljenjem, i Euklidov algoritam sa oduzimanjem moze sezapisati u kracem obliku:

{prvi = a; drugi = b;while (prvi! = drugi) {

if (prvi > drugi)prvi = prvi− drugi;

elsedrugi = drugi− prvi;

/∗ NZD(a, b)= NZD(prvi, drugi)∗/}/∗ NZD(a, b) = prvi = drugi∗/

}Primenom aksioma iskaza dodele, serijskog komponovanog iskaza i while iskaza

moze se dokazati korektnost ovog programa.

Iz prethodnih primera je ocigledan znacaj koji utvrdivanje invarijante petlje (bezobzira koji oblik iskaza ciklusa je u pitanju) ima za utvrdivanje vazenja postuslovatj. relacije koja treba da vazi po zavrsenju izvrsavanja petlje. Zato jedna odnajvrednijih lekcija koju svaki programer treba da nauci jeste da je eksplicitnonavodenje relevantne invarijante (jer moze ih biti puno) za svaku petlju najvrednijielement dokumentacije programa.

8.4.4 Ekvivalentnost repetitivnih iskaza while i do-while

Mada jedan od iskaza while, do-while moze biti adekvatniji od drugog u izrazavanjuupravljacke strukture ponavljanja iskaza u nekoj situaciji, ova dva iskaza su ekvi-valentna u svojoj izrazajnoj moci. Sve sto se moze izraziti jednim, moze i drugim.Tako se iskaz

while (p)S

moze zapisati i sledecim ekvivalentnim iskazom:if (p)

doS

while (p);Takode, iskazdo {

8.4. Repetitivni iskazi 93

S1;S2;. . .Sk;

} while (p);moze se realizovati sledecim iskazom dodele i while iskazom:

{t=1;while (t || p) {

S1;S2;. . .Sk;t=0;

}

8.4.5 Zavrsavanje petlje

Repetitivna struktura je izuzetno vazna u programiranju. Vazno svojstvo svakogprograma je da se on zavrsava posle konacnog broja operacija.

Za osnovnu repetitivnu strukturu (iskaz ciklusa sa pred-proverom uslova), slika8.8, minimalni zahtev za zavrsavanje je da iskaz S menja vrednost jedne ili visepromenljivih tako da posle konacnog broja prolaza uslov p vise nije zadovoljen (dase petlja zavrsava).

Formalno, konacnost ponavljanja se izvodi pomocu celobrojne funkcije t kojazavisi od nekih promenljivih programa, i to tako sto se pokazuje da:

a) ako je p tacno, onda je t > 0 i

b) svako izvrsavanje iskaza S smanjuje vrednost funkcije t.

Primer Neka se, za dva razlicita prirodna broja a, b, sve dok je a 6= b, izvrsavajedan od iskaza a ← a− b, b ← b− a, u zavisnosti da li je a > b ili b > a, tj.

a ← a− b ako je a > b, ib ← b− a ako je b > a.

Uslov p je a 6= b (program nalazi najveci zajednicki delilac polaznih brojeva a, b,pri cemu se ne cuva pocetna vrednost tih brojeva; dijagram na slici 8.14; uporedisa Euklidovim algoritmom – oduzimanjem).

Zgodno je za funkciju t(a, b) izabrati t =max(a, b).Ako je a > b, izvrsenjem iskaza a ← a − b, a se smanjuje za b a b ostaje

nepromenjno. Kako je a > 0, b > 0 pre izvrsenja iskaza dodele, te dve relacijeostaju nepromenjene (invarijantne) a t se smanjuje.

94 8. Iskazi – upravljanje

?

?

¡¡@@

@@¡¡

a 6= b

?

-

nzd← a

½¼

¾»kraj

b ← b− a

?¡¡@@

@@¡¡

a > b

a ← a− b

¾

DA

NE

DA

NE

Figure 8.14: najveci zajednicki delilac brojeva a, b

Ako je b > a, izvrsavanjem iskaza b ← b − a, b (pa i t=max(a, b)) se smanjuje,dok a ostaje nepromenjeno.

Kako se t=max(a, b) smanjuje u svakom ponavljanju petlje, a, s druge strane,min(a, b) ostaje > 0, sledi da ce u nekom trenutku postati max(a, b)=min(a, b), paa 6= b vise nije zadovoljeno. Ovime se ponavljanje zavrsava.

Primer – deljenje prirodnih brojevaIzgraditi algoritam koji, za dva prirodna broja x, y, odreduje celobrojni deo

kolicnika q pri deljenju x sa y, i ostatak r pri tom deljenju. Formalna specifikacijaproblema je oblika

{x, y ∈ N} → {q, r ∈ N : x = q ∗ y + r, r < y}Deljenje se moze realizovati ponovljenim oduzimanjem. Ako promenljive q i r

oznacavaju kolicnik i ostatak pri celobrojnom deljenju, onda se q moze izracunatiuzastopnim uvecanjem za 1 (polazeci od 0) onoliko puta koliko se puta y mozeoduzeti od x. Ostatak r se dobije kao razlika poslednjeg takvog oduzimanja (kojaje < od y). Na kraju petlje treba da vazi uslov x = q ∗ y + r, r < y, pa na osnovuprvog dela tog uslova formulisemo invarijantu petlje P: x = q ∗ y + r, a negacijomdrugog poredenja formulisemo uslov iskaza ponavljanja p: r ≥ y. Algoritam imasledeci oblik:

{q = 0; r = x;while (r >= y) { /∗ x = q ∗ y + r, r >= y ∗ /

r = r − y; q = q + 1;}

8.5. Iskazi bezuslovnog skoka 95

/∗ x = q ∗ y + r, r < y ∗ /}Sto se tice granicne funkcije t, ona se dobija iz uslova p: r ≥ y; moze se za t

izabrati razlika r − y. Za funkcije t vazi:

a) t ≥ 0 (jer je r ≥ y ) i

b) izvrsavanje S smanjuje vrednost od r pa i od t, zavrsavanje je garantovano.Posebno je znacajan pocetni uslov y > 0.

Dijagramski je algoritam predstavljen slikom 8.15.

?¡¡@@

@@¡¡

r ≥ y

?

?

q ← 0r ← x

q ← q + 1r ← r − y

-

?

(q ∗ y + r = x) ∧ (r ≥ 0)

(q ∗ y + r = x) ∧ (0 ≤ r < y)

½¼

¾»kraj

DA

NE

Figure 8.15: algoritam deljenja prirodnih brojeva uzastopnim oduzimanjem

8.5 Iskazi bezuslovnog skoka

Pored iskaza bezuslovnog skoka – goto obelezje, u C-u postoje i iskazi break i con-tinue. Iskaz break obezbeduje momentalni izlazak iz unutrasnje for, while, do –petlje, kao i iz prekidackog – switch iskaza. Iskaz continue obezbeduje momentalniprelaz na sledecu iteraciju unutrasnje for, while ili do – petlje.

Primer – goto: nalazenje zajednickog elementa dva niza a i bfor (i=0; i<n; i++)

for (j=0; j<m; j++)if (a[i] == b[j])

goto nadjen;/∗ nije nadjen zajednicki element ∗/

96 8. Iskazi – upravljanje

. . .nadjen:

/∗ nadjen jedan zajednicki element: a[i]==b[j] ∗/. . .

Primer – break: eliminise zavrsne znakove za belinu, tabulator, novi red, izstringa s

int elimbel(char s[ ]) {int n;for (n=strlen(s)–1; n>=0; n−−)

if (s[n]! =’ ’ && s[n] ! = ’\t’ && s[n]! = ’\n’)break;

s[n+1] = ’\0’;return n;

}Primer – continue: obrada samo ne-negativnih elemenata niza a

for (i=0; i< n; i++) {if (a[i] < 0) /∗ preskoci negativne elemente ∗/

continue;. . . /∗ obradi pozitivne elemente ∗/

}