39
UVOD Prvi računari koji su se pojavili bili su vrlo složeni za korištenje. Njih su koristili isključivo stručnjaci koji su bili osposobljeni za komunikaciju sa računarom. Ta komunikacija se sastojala od dva osnovna koraka: davanje uputstava računaru i čitanje rezultata obrade. Samo unošenje uputstava se sastojalo od mukotrpnog unosa niza nula i jedinica. Ti nizovi su davali računaru uputstva kao što su: “saberi dva broja”, ”premjesti podatak sa jedne memorijske lokacije na drugu” i sl. Kako je takve programe bilo vrlo složeno pisati, a još složenije čitati i ispravljati, ubrzo su se pojavili prvi programerski alati nazvani asembleri. U asemblerskom jeziku svaka mašinska instrukcija predstavljena je mnemonikom koji je razumljiv ljudima koji čitaju program. Tako se sabiranje najčešće obavlja mnemonikom ADD , dok se premještanje obavlja mnemonikom MOV. Time se postigla bolja čitljivost programa, no i dalje je bilo vrlo složeno pisati programe i ispravljati ih jer je bilo potrebno davati sve, pa i najmanja uputstva računaru za svaku pojedinu opciju. Zbog toga se pojavljuje niz viših programska jezika, koji preuzimaju na sebe neke "dosadne" programerske poslove. Tako je FORTRAN bio posebno pogodan za matematičke proračune, zatim BASIC koji se vrlo brzo učio, te COBOL koji je bio u pravilu namijenjen upravljanju bazama podataka. Oko 1972. se pojavljuje jezik C, koji je direktna preteča današnjeg jezika C++. To je bio prvi jezik opšte namjene te je postigao neviđen uspjeh. Više je razloga tome: jezik je bio jednostavan za učenje, omogućavao je modularno pisanje programa, sadržavao je samo naredbe koje se mogu jednostavno prevesti u mašinski jezik, davao je brzi kod. No kako je razvoj programske podrške napredovao, stvari su se i na području programskih jezika počele mijenjati. Složeni projekti od nekoliko stotina hiljada, pa i više redova više nisu rijetkost, pa je zbog toga bilo potrebno uvesti dodatne mehanizme kojima bi se takvi programi učinili jednostavnijima za izradu i

Seminar Ski Text

Embed Size (px)

Citation preview

Page 1: Seminar Ski Text

UVOD

Prvi računari koji su se pojavili bili su vrlo složeni za korištenje. Njih su koristili isključivo stručnjaci koji su bili osposobljeni za komunikaciju sa računarom. Ta komunikacija se sastojala od dva osnovna koraka: davanje uputstava računaru i čitanje rezultata obrade. Samo unošenje uputstava se sastojalo od mukotrpnog unosa niza nula i jedinica. Ti nizovi su davali računaru uputstva kao što su: “saberi dva broja”, ”premjesti podatak sa jedne memorijske lokacije na drugu” i sl. Kako je takve programe bilo vrlo složeno pisati, a još složenije čitati i ispravljati, ubrzo su se pojavili prvi programerski alati nazvani asembleri.

U asemblerskom jeziku svaka mašinska instrukcija predstavljena je mnemonikom koji je razumljiv ljudima koji čitaju program. Tako se sabiranje najčešće obavlja mnemonikom ADD , dok se premještanje obavlja mnemonikom MOV. Time se postigla bolja čitljivost programa, no i dalje je bilo vrlo složeno pisati programe i ispravljati ih jer je bilo potrebno davati sve, pa i najmanja uputstva računaru za svaku pojedinu opciju.

Zbog toga se pojavljuje niz viših programska jezika, koji preuzimaju na sebe neke "dosadne" programerske poslove. Tako je FORTRAN bio posebno pogodan za matematičke proračune, zatim BASIC koji se vrlo brzo učio, te COBOL koji je bio u pravilu namijenjen upravljanju bazama podataka.

Oko 1972. se pojavljuje jezik C, koji je direktna preteča današnjeg jezika C++. To je bio prvi jezik opšte namjene te je postigao neviđen uspjeh. Više je razloga tome: jezik je bio jednostavan za učenje, omogućavao je modularno pisanje programa, sadržavao je samo naredbe koje se mogu jednostavno prevesti u mašinski jezik, davao je brzi kod.

No kako je razvoj programske podrške napredovao, stvari su se i na području programskih jezika počele mijenjati. Složeni projekti od nekoliko stotina hiljada, pa i više redova više nisu rijetkost, pa je zbog toga bilo potrebno uvesti dodatne mehanizme kojima bi se takvi programi učinili jednostavnijima za izradu i održavanje, te kojima bi se omogućilo da se jednom napisani kod iskoristi u više različitih projekata.

Bjarne Stroustrup (rođen u Danskoj) je 1979. godine započeo rad na jeziku "C s klasama" (engl. C with Classes). Kada se 1979. zaposlio u Bell Labs (kasnije AT&T) u Murray Hillu, započeo je rad na onome što će kasnije postati C++. Pri tome je iskoristio svoje iskustvo stečeno prilikom rada na doktoratu te pokušao stvoriti univerzalni jezik koji će udovoljiti današnjim zahtjevima. Pri tome je uzeo dobra svojstva niza jezika: Simula, Clu, Algol68 i Ada, a kao osnovu je uzeo jezik C.

Page 2: Seminar Ski Text

ŠTA JE PROGRAM I KAKO GA NAPISATI

Programi koje pokrećete na računaru su u izvedbenom obliku (engl. executable), razumljivom samo procesoru vašeg računara. U suštini se mašinski kod sastoji od nizova binarnih cifara: nula i jedinica. Budući da su današnji programi tipično dužine nekoliko megabajta, naravno da ih autori nisu pisali direktno u mašinskim kodu .

Skoro svi današnji programi se pišu u nekom od viših programskih jezika (FORTRAN, BASIC, Pascal, C) koji su donekle razumljivi i ljudima. Naredbe u tim jezicima se sastoje od mnemonika. Kombinovanjem tih naredbi programer slaže izvorni kod (engl. source code) programa, koji se pomoću posebnih programa prevoditelja (engl. compiler) i povezivača (engl. linker) prevodi u izvedbeni kod. Međutim, kako pisanje koda nije samo sebi svrhom, pod pisanjem programa u širem smislu podrazumijeva se i prevođenje, odnosno povezivanje programa u izvedbeni kod. Stoga možemo govoriti o četiri faze izrade programa:

1. pisanje izvornog koda 2. prevođenje izvornog koda, 3. povezivanje u izvedbeni kod 4. testiranje programa.

Prva faza programa je pisanje izvornog koda. U principu se izvorni kod može pisati u bilo kojem programu za uređivanje teksta, međutim velika većina današnjih prevoditelja i povezivača se isporučuje kao cjelina zajedno s ugrađenim programom za upis i ispravljanje izvornog koda. Te programske cjeline poznatije su pod nazivom integrisana razvojna okruženja (engl. integrated development environment, IDE). Nakon što je pisanje izvornog koda završeno, on se pohrani u datoteku izvornog koda na disku.

Slijedi prevođenje izvornog koda. U integrisanim razvojnim okruženjima program za prevođenje se pokreće pritiskom odgovarajućeg tastera na tastaturi ili iz nekog od menija. Prevoditelj tokom prevođenja provjerava sintaksu napisanog izvornog koda i u slučaju uočenih grešaka ispisuje odgovarajuće poruke o greškama, odnosno upozorenja. Greške koje prijavi prevoditelj nazivaju se greškama pri prevođenju (engl. compile-time errors). Nakon toga programer će pokušati ispraviti sve navedene greške i ponovo prevesti izvorni kod - sve dok prevođenje koda ne bude uspješno okončano, neće se moći pristupiti povezivanju koda. Prevođenjem izvornog dobiva se datoteka objektnog koda (engl. object code).

Nakon što su ispravljene sve greške uočene prilikom prevođenja i kod ispravno preveden, pristupa se povezivanju objektnih kodova u izvedbeni. U većini slučajeva objektni kod dobiven prevođenjem programerovog izvornog koda treba povezati s postojećim bibliotekama (engl. libraries). Biblioteke su datoteke u kojima se nalaze već prevedene gotove funkcije ili podaci. Prilikom povezivanja provjerava se mogu li se svi pozivi kodova realizovati u izvedbenom kodu. Uoči li povezivač neku nepravilnost tokom povezivanja, ispisat će poruku o grešci i onemogućiti generisanje izvedbenog koda. Ove greške nazivaju se greškama pri povezivanju (engl. link-time errors). Nakon što se isprave sve greške, kod treba ponovno prevesti i povezati.

Uspješnim povezivanjem dobiva se izvedbeni kod. Međutim, takav izvedbeni kod još uvijek ne jamči da će program raditi ono što ste zamislili. Na primer, može se dogoditi da

Page 3: Seminar Ski Text

program radi pravilno za neke podatke, ali da se za druge podatke ponaša nepredvidivo. U tom se slučaju radi o greškama pri izvođenju (engl. run-time errors). Da bi program bio potpuno korektan, programer treba istestirati program da bi uočio i ispravio te pogreške, što znači ponavljanje cijelog postupka.

Slijedi jedan jednostavan program:

#include <iostream> using namespace std;

int main(){ cout << "Ja sam za C++!!! A vi?" << endl;

system(“pause”); return 0; }

Ukucate li ovaj program u svoj računar, pokrenete odgovarajući prevoditelj, te nakon uspješnog prevođenja pokrenete program, na ekranu računara će te dobiti ispisano “Ja sam za C++!!! A vi?”.

Sada ćemo razmotriti ovaj program, red po red. U prvom redu nalazi se naredba #include <iostream> kojom se od prevoditelja zahtijeva da u naš program uključi biblioteku iostream. U toj biblioteci nalazi se izlazni tok (engl. output stream) te funkcije koje omogućavaju ispis podataka na ekranu. Ta biblioteka nam je neophodna da bismo ispisali tekst poruke. Iostream je primjer datoteke zaglavlja (engl. header file). U takvim datotekama se nalaze deklaracije funkcija sadržanih u odgovarajućim bibliotekama.

U drugom redu koda napisana je naredba using namespace std. using i namespace su ključne riječi jezika C++ kojima se "aktivira" određeno područje imena (imenik, engl. namespace), a std je naziv imenika u kojem su obuhvaćane sve standardne funkcije, uključujući i funkcije iz gore opisane iostream biblioteke.

U sledećem redu je napisano int main(). main je naziv za glavnu funkciju u svakom C++ programu. Izvođenje svakog programa počinje naredbama koje se nalaze u njoj. Svaki program napisan u C++ jeziku mora imati tačno jednu main() funkciju.

Riječ int ispred oznake glavne funkcije ukazuje na to da će main() po završetku izvođenja naredbi i funkcija sadržanih u njoj kao rezultat tog izvođenja vratiti cijeli broj. Budući da se glavni program pokreće iz operativnog sistema (DOS, UNIX, MS Windows), rezultat glavnog programa se vraća operativnom sistemu. Najčešće je to kod koji signalizira grešku nastalu tokom izvođenja programa ili obavijest o uspješnom izvođenju.

Iza riječi main slijedi par otvorena-zatvorena zagrada (). Unutar te zagrade trebali bi doći opisi podataka koji se iz operativnog sistema prenose u main(). Ti podaci nazivaju se argumenti ili parametri funkcije. Slijedi otvorena vitičasta zagrada {. Ona označava početak bloka naredbi u kojem će se nalaziti naredbe glavne funkcije, dok zatvorena vitičasta zagrada } u zadnjem redu označava kraj tog bloka .

Page 4: Seminar Ski Text

Zatim ide naredba cout. cout je ime izlaznog toka definisanog u biblioteci iostream, pridruženog ekranu računara. Operatorom << (dva znaka "manje od") podatak koji slijedi upućuje se na izlazni tok, tj. na ekran računara. U gornjem primjeru to je kratka poruka:

Ja sam za C++!!! A vi?

Ona je u programu napisana unutar znakova navodnika, koji upućuju na to da se radi o tekstu koji treba ispisati bukvalno. endl je konstanta u biblioteci iostream koja prebacuje ispis u novi red, to jest vraća kursor na početak sljedećeg reda na ekranu.

Na kraju svake naredbe piše se znak ; (tačka-zarez). On označava kraj naredbe te služi kao poruka prevoditelju da sve znakove koji slijede interpretira kao novu naredbu.

Nakon toga lsijedi naredba system(“pause”) koja govori procesoru da pokrenuti program ostane aktivan, to jest da ne zatvara prozor odmah po završetku izvršenja programa. Bez te naredbe, računar bi izvršio program i zatvorio prozor tako brzo da ga ne bi ni vidjeli.

Sledeća naredba je return 0. Tom naredbom glavni program vraća pozivnom programu broj 0, a to je poruka operativnom sistemu da je program uspješno okončan.

KOMENTARI

Veoma korisna stvar u C++ su komentari. Označavaju se sa dvije kose crte (//). Kada prevoditelj naleti na dvostruku kosu crtu, on će zanemariti sav tekst koji slijedi do kraja tog reda i prevođenje će nastaviti u sljedećem redu. Komentari dakle ne ulaze u izvedbeni kod programa i služe programerima za opis značenja pojedinih naredbi ili dijelova koda. Komentari se mogu pisati u zasebnom redu ili u produžetku reda, što se obično radi za duže opise, npr. šta određeni program ili funkcija radi:

#include <iostream>using namespace std;

int main() //main funkcija{

//ispisuje “Ja sam C++” na ekrancout << “Ja sam C++” << end;

system(“pause”);return 0;}

Uz gore navedeni oblik komentara, jezik C++ podržava i komentare unutar para znakova /* */. Takvi komentari započinju znakom /* (kosa crta i zvjezdica), a završavaju znakom */ (zvjezdica i kosa crta). Kraj reda ne znači podrazumijevani završetak komentara, pa se ovakvi komentari mogu protezati na nekoliko redova izvornog koda, a da se pritom znak za komentiranje ne mora ponavljati u svakom retku:

Page 5: Seminar Ski Text

/* Ovakav način komentara preuzet je iz programskog jezika C. */

Iako komentiranje programa iziskuje dodatno vrijeme i napor, u kompleksnijim programima ono se redovno isplati. Dogodi li se da neko drugi mora ispravljati vaš kod, ili (još gore) da nakon dugo vremena vi sami morate ispravljati svoj kod, komentari će vam olakšati da shvatite ono što je autor njime htio reći. S druge strane, s količinom komentara ne treba pretjerivati, jer će u protivnom izvorni kod postati nepregledan.

IDENTIFIKATORI I VARIJABLE

Identifikatori

Mnogim dijelovima C++ programa (varijablama, funkcijama, klasama) potrebno je dati određeno ime, tzv. identifikator. Imena koja dodjeljujemo identifikatora su proizvoljna, uz uslov da se poštuju sljedeća tri osnovna pravila:

Identifikator može biti sastavljen od kombinacije slova engleskog alfabeta (A - Z, a - z), brojeva (0 - 9) i znaka za podcrtavanje '_' .

Prvi znak mora biti slovo ili znak za podcrtavanje. Identifikator ne smije biti jednak nekoj od ključnih riječi ili nekoj od alternativnih oznaka

operatora. To ne znači da ključna riječ ne može biti dio identifikatora - mojInt je dozvoljeni identifikator iako je int ključna riječ.

Tablica Ključne riječi jezika C++

asm else new thisauto enum operator throwbool explicit private truebreak export protected trycase extern public typedefcatch false register typeidchar float reinterpret_cast typenameclass for return unionconst friend short unsignedconst_cast goto signed usingcontinue if sizeof virtualdefault inline static voiddelete int static_cast volatiledo long struct wchar_tdouble mutable switch whiledynamic_cast namespace template

Page 6: Seminar Ski Text

Jezik C++ razlikuje velika i mala slova u imenima, tako da identifikatori prviBroj, PRVIBROJ i brvibroj predstavljaju tri različita naziva. Također, ne postoji teoretsko ograničenje na dužinu imena, ali zbog razumljivosti koda nije preporučljivo pisati preduge identifikatore.

Deklarisanje varijabli i pridruživanje vrijednosti

Bez obzira na jezik u kojem je pisan, svaki program sastoji se od niza naredbi koje mijenjaju vrijednosti objekata pohranjenih u memoriji računara. Računar dijelove memorije u kojima su smješteni objekti razlikuje pomoću pripadajuće memorijske adrese. Da programer tokom pisanja programa ne bi morao pamtiti memorijske adrese, svi programski jezici omogućavaju da se vrijednosti objekata dohvaćaju preko simboličkih naziva. Gledano iz perspektive običnog računara objekt je samo dio memorije u koji je pohranjena njegova vrijednost u binarnom obliku. Tip objekta, između ostalog, određuje raspored bitova prema kojem je taj objekt pohranjen u memoriju.

Da bi prevoditelj pravilno preveo naš izvorni C++ kod u mašinski jezik, svaku varijablu treba prije njena korištenja u kodu deklarisati, odnosno odrediti njen tip. Npr:

int a, b, c;

Tim deklaracijama je prevoditelju jasno dano do znanja da će varijable a, b i c biti cjelobrojne. Takođe će znati kako treba provesti operacije na njima. Prilikom deklaracije varijable treba takođe paziti da se u istom dijelu programa(bloku) ne smiju deklarisati više puta varijable s istim imenom, čak i ako su one različitih tipova.

Varijable postaju realna stvarnost tek kada im se pokuša pristupiti, na primjer kada im se pridruži vrijednost:

a = 2; b = a; c = a + b;

Operatorom pridruživanja mijenja se vrijednost nekog objekta, pri čemu tip objekta ostaje nepromijenjen. Najčešći operator pridruživanja je znak jednakosti (=) kojim se objektu na lijevoj strani pridružuje neka vrijednost s desne strane. Prevoditelj tek tada pridružuje memorijski prostor u koji se pohranjuju podaci. Deklaracija varijable i pridruživanje vrijednosti mogu se obaviti u istom redu koda. Umjesto da pišemo poseban red s deklaracijama varijabli a, b i c i zatim im pridružujemo vrijednosti, inicijalizaciju možemo provesti ovako:

int a = 2; int b = a; int c = a + b;

Takođe, možemo varijabli pridružiti vrijednost istu tu varijablu u svrhu promjene njene vrijednosti, npr. povećavanja ili smanjivanja njene vrijednosti.

int i = 5; i = i + 3;

Jezik C++ dozvoljava više operatora pridruživanja u istoj naredbi. Pritom pridruživanje ide od krajnjeg desnog operatora prema lijevo:

a = b = c = 0;

Page 7: Seminar Ski Text

te ih je tako najsigurnije i čitati: "broj 0 pridruži varijabli c, čiju vrijednost pridruži varijabli b, čiju vrijednost pridruži varijabli a".

TIPOVI PODATAKA I OPERATORI

Brojevi

U jeziku C++ ugrađena su u suštini dva osnovna tipa brojeva: cijeli brojevi (engl. integers) i realni brojevi (tzv. brojevi s pomičnim decimalnim zarezom, engl. floating- point). Najjednostavniji tip brojeva su cijeli brojevi. Cjelobrojna varijabla deklarišese pomoću riječi int i njena će vrijednost u memoriji računara obično zauzeti dva bajta, tj. 16 bitova. Prvi bit je rezerviran za predznak, tako da preostaje 15 bitova za pohranu vrijednosti. Stoga se varijablom tipa int mogu obuhvatiti svi brojevi od -32768 do 32767.

Za većinu praktičnih primjena taj opseg vrijednosti je dovoljan. Međutim, ukaže li se potreba za većim cijelim brojevima varijablu možemo deklarirati kao long int, ili kraće samo long. Takva varijabla će zauzeti u memoriji više prostora i operacije s njom će duže trajati.

Cjelobrojne konstante se mogu u izvornom kodu prikazati u različitima brojevnim sistemima:

• dekadnom, • oktalnom, • heksadekadskom.

Oktalne konstante se pišu tako da se ispred prve cifre napiše broj 0 iza kojeg slijedi oktalni prikaz broja:

int oktalniBroj = 010; // odgovara dekadnom 8

Heksadekadske konstante započinju s 0x ili 0X:

int heksadecimalniBroj = 0x0C; // dekadno 12

Slova za heksadekadske cifre mogu biti velika ili mala.

Ako je potrebno računati s decimalnim brojevima, najčešće se koriste varijable tipa float:

float pi = 3.141593; float brzinaSvjetlosti = 2.997925e8; float nabojElektrona = -1.6E-19;

Osim što je ograničen raspon vrijednosti koje se mogu prikazati float tipom treba znati da je i broj decimalnih cifara u mantisi također ograničen na 7 decimalnih mijesta.

Usput spomenimo da su broj i ostale značajnije matematičke konstante definisane u biblioteci cmath, i to na veću tačnost. Ako tačnost na sedam decimalnih cifara ne zadovoljava ili ako se koriste brojevi veći od 1038 ili manji od 10-38, tada se umjesto float mogu

Page 8: Seminar Ski Text

koristiti brojevi s dvostrukom tačnošću tipa double koji pokrivaju opseg vrijednosti od 1.7·10-308 do 1.7·10308, ili long double koji pokrivaju još širi opseg od 3.4·10-4932 do 1.1·104932.

U tablici 2.4 dane su tipične dužine ugrađenih brojevnih tipova u bajtovima, rasponi vrijednosti koji se njima mogu obuhvatiti, a za decimalne brojeve i broj tačnih decimalnih cifara. Relevantni podaci za cjelobrojne tipove mogu se naći u datoteci climits, a za decimalne tipove podataka u cfloat. Tako, npr. su konstante INT_MIN i INT_MAX jednake najmanjoj (najvećoj negativnoj) i najvećoj vrijednosti brojeva tipa int.

Ako želite sami provjeriti veličinu pojedinog tipa, to možete učiniti i pomoću sizeof operatora:

cout << "Veličina cijelih brojeva: " << sizeof(int); cout << "Veličina realnih brojeva: " << sizeof(float); long double masaSunca = 2e30; cout << "Veličina long double: " << sizeof(masaSunca);

Tip konstante bajtova

Raspon vrijednosti tačnost

char 1 signed: -128 to 127unsigned: 0 to 255

Short int 2 signed: -32768 to 32767unsigned: 0 to 65535

int 4 signed: -2147483648 to 2147483647unsigned: 0 to 4294967295

Long int 4 signed: -2147483648 to 2147483647unsigned: 0 to 4294967295

float 4 -3,4·1038 do -3,4·10-38 7 decimalnih cifara

double 8 -1,7·10308 do -1,7·10-308 15 decimalnih cifara

Long double 10 -1,1·104932 do -3,4·10-4932 18 decimalnih cifara

Tablica 2.4. Ugrađeni brojevni tipovi, njihove tipične duljine i rasponi vrijednosti --43

Svi navedeni brojevni tipovi mogu biti deklarisani i bez predznaka, dodavanjem riječi unsigned ispred njihove deklaracije:

unsigned int i = 40000; unsigned long int li; unsigned long double BrojZvijezdaUSvemiru;

U tom slučaju će prevoditelj bit za predznak upotrijebiti kao dodatnu binarnu cigru, pa se najveća moguća vrijednost udvostručuje u odnosu na varijable s predznakom, ali se naravno ograničava samo na pozitivne vrijednosti.

Aritmetički operatori

Page 9: Seminar Ski Text

Da bi smo objekte u programu mogli mijenjati, na njih treba primijeniti odgovarajuće operacije. Za ugrađene tipove podataka definisani su osnovni operatori, poput sabiranja, oduzimanja, množenja i dijeljenja. Ti operatori se mogu podijeliti na unarne, koji djeluju samo na jedan objekt, te na binarne za koje su neophodna dva objekta. Osim unarnog plusa i unarnog minusa koji mijenjaju predznak broja, u jeziku C++ definisani su još i unarni operatori za uvećavanje (inkrementiranje) i umanjivanje vrijednosti (dekrementiranje) broja. Operator ++ uvećat će vrijednost varijable za 1, dok će operator -- umanjiti vrijednost varijable za 1.

int i = 1;cout << i << endl; // ispisuje 1cout << (++i) << endl; // prvo poveća pa ispisuje 2cout << i << endl; // ispisuje opet i, za svaki slučajcout << (i++) << endl; // prvo ispisuje, a tek onda povećacout << i << endl; //ispisuje i

Pritom valja uočiti razliku između operatora kada je on napisan ispred varijable i operatora kada je on napisan iza nje. U prvom slučaju (prefiks operator), vrijednost varijable će se prvo uvećati ili umanjiti, a potom će biti dohvaćena njena vrijednost. U drugom slučaju (postfiks operator) je obrnuto: prvo se dohvati vrijednost varijable, a tek onda slijedi promjena.

Na raspolaganju imamo pet binarnih aritmetičkih operatora: za sabiranje, oduzimanje, množenje, dijeljenje i modulo operator:

float a =3, b = 2;cout << (a + b) << end; // ispisuje 5cout << (a - b) << end; // ispisuje 1cout << (a * b) << end; // ispisuje 6cout << (a / b) << end; // ispisuje 1.5cout << (a % b) << end; // ispisuje 1

Operator modulo kao rezultat vraća ostatak dijeljenja dva cijela broja.

Za ugrađene tipove tačno su određena pravila uobičajenog aritmetičkog pretvaranja koja određuju kakvog će biti tipa rezultat binarne operacije na dva broja. Ako su oba operanda istog tipa, tada je i rezultat tog tipa, a ako su operandi različitih tipova, tada se oni prije operacije svode na zajednički tip (to je obično složeniji tip), prema sljedećim pravilima [ISO/IEC1998]:

Ako je jedan od operanada tipa long double, tada se i drugi operand pretvara u long double.

Inače, ako je jedan od operanada tipa double, tada se i drugi operand pretvara u double. Inače, ako je jedan od operanada tipa float, tada se i drugi operand pretvara u float. Potom, ako je jedan od operanada unsigned long, tada se i drugi operand pretvara u

unsigned long. U protivnom, ako je jedan od operanada tipa long int, a drugi operand tipa unsigned

int, ako long int može obuhvatiti sve vrijednosti unsigned int, unsigned int se pretvara u long int; inače se oba operanda pretvaraju u unsigned long int.

Inače, ako je jedan od operanada tipa long, tada se i drugi operand pretvara u long.

Page 10: Seminar Ski Text

Inače, ako je jedan od operanada unsigned, tada se i drugi operand pretvara u unsigned.

Npr. Izvođenje koda:

int i = 3; float a = 0.5; cout << (a * i) << endl;

uzrokovat će ispis broja 1.5 na ekranu, jer je od tipova int i float složeniji tip float. Cjelobrojnu varijablu i prevoditelj prije množenja pretvara u float, tako da se provodi množenje dva broja s pomičnom tačkom, pa je i rezultat tipa float.

Konstante

U programima se redovno koriste simboličke veličine čija se vrijednost tokom izvođenja ne želi mijenjati. Da bismo to uradili, na raspolaganju nam je kvalifikator const kojim se prevoditelju daje na znanje da varijabla mora biti nepromjenjiva. Na svaki pokušaj promjene vrijednosti takve varijable, prevoditelj će javiti pogrešku:

const double pi = 3.14159265359; pi = 2 * pi; // prevodilac će prijaviti grešku

Drugi često korišteni način zasniva se na pretprocesorskoj naredbi #define:

#define PI 3.14159265359

Ona daje uputstvo prevoditelju da, prije nego što započne prevođenje izvornog koda, sve pojave prvog niza (PI) zamijeni drugim nizom znakova (3.14159265359).

Pobrojenja

Ponekad su varijable u programu elementi pojmovnih skupova, tako da je takvim skupovima i njihovim elementima zgodno pridijeliti lakopamtiva imena. Za takve slučajeve obično se koriste pobrojani tipovi (engl. enumerated types, enumeration):

enum dani {ponedjeljak, utorak, srijeda, četvrtak, petak, subota, nedjelja};

Ovom deklaracijom uvodi se novi tip podataka dani, te sedam nepromjenjivih identifikatora (ponedjeljak, utorak,...) toga tipa. Prvom identifikatoru prevoditelj pridjeljuje vrijednost 0, drugom 1, itd. Sada možemo definisati varijablu tipa dani, te joj pridružiti neku od vrijednosti iz niza:

dani dan1 = petak; dani dan2 = ponedjeljak;

Naredbom

Page 11: Seminar Ski Text

cout << dan1 << endl;

na ekranu se ispisuje cjelobrojni ekvivalent za petak, tj. broj 4.

U pobrojanim nizovima podrazumijevana vrijednost prve varijable je 0, itd. Želimo li da niz ima neke druge vrijednosti, treba eksplicitno pridijeliti željene vrijednosti:

enum likovi {kruznica = 0, trougao = 3, pravougaonik = 4, kvadrat = 4, cetverougao = 4, peterougao, sedmerougao = cetverougao + 3};

cout << kruznica << endl; // ispisuje 0cout << trougao << endl; // ispisuje 3cout << kvadrat << endl; // ispisuje 4cout << peterougao << endl; // ispisuje 5cout << sedmerougao << endl; // ispisuje 7

Identifikator kružnica poprima vrijednost 0, trokut 3, itd. Ako nekom članu nismo definisali vrijednost, on će dobiti vrijednost za 1 veću od vrijednosti prethodnog člana u nizu.

Pobrojane vrijednosti mogu se koristiti u aritmetičkim izrazima. U takvim slučajevima se prvo provodi cjelobrojna promocija pobrojane vrijednosti - ona se pretvara u prvi mogući cjelobrojni tip naveden u slijedu: int, unsigned int, long ili unsigned long.

Na primjer:

enum {DVOSTRUKI = 2, TROSTRUKI}; int i = 5; float pi = 3.14159; cout << DVOSTRUKI * i << endl; // ispisuje 10 cout << TROSTRUKI * pi << endl; // ispisuje 9.42477

Logički tipovi i operatori

Logički podaci su takvi podaci koji mogu poprimiti samo dvije vrijednosti, na primjer: da/ne, istina/laž, dan/noć. Jezik C++ za prikaz podataka logičkog tipa ima ugrađen tip bool, koji može poprimiti vrijednosti true (engl. true - tačno) ili false (engl. false - netačno):

bool jeLiDanasNedjelja = true; bool jeLiDanasSubota = false;

Pri ispisu logičkih tipova, te pri njihovom korištenju u aritmetičkim izrazima, logički tipovi se pravilima cjelobrojne promocije pretvaraju u int: true se pretvara u cjelobrojni 1, a false u 0. Isto tako, logičkim varijablama se mogu pridruživati aritmetički tipovi: u tom slučaju se vrijednosti različite od nule pretvaraju u true, a nula se pretvara u false.

Page 12: Seminar Ski Text

Gornja svojstva tipa bool omogućavaju da se za predstavljanje logičkih podataka koriste i cijeli brojevi. Broj 0 u tom slučaju odgovara logičkoj neistini, a bilo koji broj različit od nule logičkoj istini.

Za logičke podatke definisana su svega tri operatora: ! (logička negacija), &&(logički i), te || (logički ili)

!x logička negacijax && y logičko ix || y logičko ili

Logička negacija je unarni operator koji mijenja logičku vrijednost varijable: istinu pretvara u neistinu i obrnuto. Logički i daje kao rezultat istinu samo ako su oba operanda istinita. Logički ili daje istinu ako je bilo koji od operanada istinit.

Razmotrimo primjenu logičkih operatora na sljedećem primjeru:

enum Logicki{NEISTINA, ISTINA, DRUGAISTINA = 124}; Logicki a = NEISTINA; Logicki b = ISTINA; Logicki c = DRUGAISTINA;Cout << “ a = “ << a << “, b = “ << b <<", c = " << c << endl;Cout << "Suprotno od a = " << !a << endl;Cout << "Suprotno od b = " << !b << endl;Cout << "Suprotno od c = " << !c << endl;cout << "a .i. b = " << (a && b) << endl; cout << "a .ili. c = " << (a || c) << endl;

Uprkos tome što smo varijabli c pridružili vrijednost DRUGAISTINA = 124, njenom logičkom negacijom dobiva se 0, tj. logička neistina.

Poredbeni operatori

Osim aritmetičkih operacija, jezik C++ omogućava i usporedbe dva broja. Kao rezultat poređenja dobiva se tip bool: ako je uslov poređenja zadovoljen, rezultat je true, a ako nije rezultat je false. Tako će se izvođenjem koda

cout << (5 > 4) << endl; //je li 5 veće od 4? cout << (5 >= 4) << endl; //je li 5 veće ili jednako 4? cout << (5 < 4) << endl; //je li 5 manje od 4? cout << (5 <= 4) << endl; //je li 5 manje ili jednako 4?

a b a i b a ili btačno tačno tačno tačnotačno netačno netačno tačnonetačno tačno netačno tačnonetačno netačno netačno netačno

Page 13: Seminar Ski Text

cout << (5 == 4) << endl; //je li 5 jednako 4? cout << (5 != 4) << endl; //je li 5 različito od 4?

na ekranu ispisati redom brojevi 1, 1, 0, 0, 0 i 1.

x < y manje odx <= y manje ili jednakox > y veće odx >= y veće ili jednakox == y jednakox != y različito

Poredbeni operatori se koriste pretežito u naredbama za grananje toka programa, gdje se, ovisno o tome je li neki uslov zadovoljen, izvođenje programa nastavlja u različitim smijerovima.

Znakovi

Znakovne konstante tipa char pišu se uglavnom kao samo jedan znak unutar jednostrukih znakova navodnika:

char SlovoA = 'a'; cout << 'b' << endl;

Za znakove koji se ne mogu prikazati na ekranu koriste se posebne sekvence koje počinju lijevom kosom crtom. Na primer, kod

cout << '\n'; // znak za novi red

uzrokovat će pomak značke na početak sledećeg reda, tj. ekvivalentan je ispisu konstante endl.

\n novi red\t horizontalni tabulator\v vertikalni tabulator\b pomak za jedno mjesto unazad (backspace)\r povratak na pocetak reda (carriage return)\f nova stranica (form feed)\a zvucni signal (alert)\\ kosa crta ulijevo (backslash)\? upitnik\’ jednostruki navodnik\’’ dvostruki navodnik\0 zavrsetak znakovnog niza\ddd znak ciji je kod zadan oktalno s 1, 2 ili 3 cifre\xddd znak ciji je kod zadan heksadecimalno

Znakovne konstante najčešće se koriste u znakovnim nizovima (engl. strings) za ispis tekstova.

Page 14: Seminar Ski Text

Operatori obnavljajućeg pridruživanja

Osim već obrađenog operatora =, jezik C++ za aritmetičke operatore podržava i operatore obnavljajućeg pridruživanja (engl. update assignment) koji se sastoje se od znaka odgovarajućeg aritmetičkog operatora i znaka jednakosti. Operatori obnavljajućeg pridruživanja omogućavaju kraći zapis naredbi.

Na primjer, naredba a += 5; ekvivalentna je naredbi a = a + 5;

x = x + y x += yx = x - y x -= yx = x * y x *= yx = x / y x /= yx = x % y x %= y

Pri korištenju operatora obnavljajućeg pridruživanja valja znati da operator pridruživanja ima niži prioritet od svih aritmetičkih operatora.

Stoga, želimo li naredbu a = a - b - c; napisati kraće, nećemo napisati

a -= b - c; // to je zapravo a = a - (b - c) već kao a -= b + c; // a = a - (b + c)

Operator razdvajanja

Operator razdvajanja , (zarez) koristi se za razdvajanje izraza u naredbama. Izrazi razdvojeni zarezom se izvode postepeno, s lijeva na desno. Tako će nakon naredbe

i = 10, i + 5;

varijabli i biti pridružena vrijednost 15. Prilikom korištenja operatora razdvajanja u složenijim izrazima valja biti vrlo oprezan, jer on ima najniži prioritet. To se posebno odnosi na pozive funkcija u kojima se zarez koristi za razdvajanje argumenata.

Hijerarhija i redoslijed izvođenja operatora

U matematici postoji utvrđena hijerarhija operacija prema kojoj neke operacije imaju prednost pred drugima. Podrazumijevani slijed operacija je slijeva nadesno, ali ako se dvije operacije različitog prioriteta nađu jedna do druge, prvo se izvodi operacija s višim prioritetom. Na primjer u matematičkom izrazu a + b * c / d množenje broja b s brojem c ima prednost pred

Page 15: Seminar Ski Text

sabiranjem s brojem a, tako da se ono izvodi prvo. Rezultat množenja se zatim dijeli s d i tek se tada pribraja broj a.

I u programskom jeziku C++ definisana je hijerarhija operatora. Prvenstveni razlog tome je kompatibilnost s matematičkom hijerarhijom operacija, što omogućava pisanje računskih izraza na gotovo identičan način kao u matematici. Stoga gornji izraz u jeziku C++ možemo pisati kao

y = a + b * c / d;

Redoslijed izvođenja operacija će odgovarati matematički očekivanom. Operacije se izvode prema hijerarhiji operacija, počevši s operatorima najvišeg prioriteta. Ako dva susjedna operatora imaju isti prioritet, tada se operacije izvode prema slijedu izvođenja operatora. U tablici 2.16 dani su svi operatori svrstani po hijerarhiji od najvišeg do najnižeg. Operatori s istim prioritetom smješteni su u zajedničke blokove.

operator značenje primjer:: globalno područje ::ime:: područje klasaa klasa::ime:: područje imenika imenik::ime

. izbor člana objekt.član

-> izbor člana pokazivac->član[] indeksiranje varijabla[indeks]() poziv funkcije funkcija(argumenti)() stvori tip tip(argumenti)++ uvećaj nakon vrijednost++-- umanji nakon vrijednost--typeid identifikacija tipa typeid(tip)typeid identifikacija tipa tokom izvođenja typeid(izraz)

const_cast pretvaranje nepromjenjivosti tipa const_cast<tip>(izraz)dynamic_cast pretvaranje tipa tokom izvođenja dynamic_cast<tip>(izraz)static_cast pretvaranje tipa tokom prevođenja static_cast<tip>(izraz)reinterpret_cast neprovjerena pretvaranje tipa reinterpret_cast<tip>(izraz)sizeof veličina objekta sizeof izrazsizeof veličina tipa sizeof(tip)++ uvećaj prije ++vrijednost-- umanji prije --vrijednost+-!~ unarni operatori ~vrijednost* dereferenciranje *izraz& adresa objekta &vrijednostnew stvori (alociraj) objekt new tipnew stvori (i inicijaliziraj) objekt new tip(argumenti)new stvori (smjesti) objekt new(argumenti) tipnew stvori (smjesti i inicijaliziraj) objekt new(argumenti) tip(argumenti)delete uništi (dealociraj) objekt delete pokazivačdelete uništi (dealociraj) polje delete[] pokazivač() dodjela tipa (tip) izraz.* izbor člana objekt.*pokazivač_na_član

->* izbor člana pokazivac->*pokazivač_na_član

*/% množenja izraz % izraz

+- sabiranja izraz - izraz

<< >> bitovni pomaci izraz >> izraz

Page 16: Seminar Ski Text

< > <= >= poredbeni operatori izraz <= izraz== != operatori jednakosti izraz != izraz& bitovni i izraz & izraz

^ bitovno isključivo ili izraz ̂ izraz

| bitovni ili izraz | izraz

&& logički i izraz && izraz|| logički ili izraz || izraz

?: uslovni izraz izraz ? izraz : izraz

= *= /= += -= &= =̂ |= %= >>= <<=

pridruživanja vrijednost += izraz

throw baci izuzetak throw izraz

, razdvajanje izraz , izraz

Hijerarhija operatora

Kao i u matematici, okruglim zagradama se može zaobići ugrađena hijerarhija operatora, budući da one imaju viši prioritet od svih operatora. Tako će se u kodu

d = a * (b + c);

prvo sabrati varijable b i c, a tek potom će se njihov zbir množiti s varijablom a. Često je zgodno zagrade koristiti i radi koda kada one nisu neophodne, čisto zbog lakše razumljivosti koda.

ISPIS I UČITAVANJE PODATAKA POMOĆU NAREDBI COUT I CIN

Za ostvarivanje komunikacije programa s okolinom, programer mora na raspolaganju imati rutine koje će podatke pojedinog tipa pretvoriti u računaru u nizove bitova te ih poslati na vanjsku jedinicu, odnosno obrnuto, nizove bitova s vanjske jedinice pretvoriti u podatke u računaru. U jeziku C++ to se ostvaruje pomoću ulaznih i izlaznih tokova. Tokovi su zapravo klase definisane u standardnim bibliotekama koje se isporučuju sa prevoditeljem. Sadržaj tih klasa je standardizovan i omogućava skoro sve osnovne ulazno-izlazne operacije. Osim toga, zahvaljujući svojstvima jezika C++, taj se set operacija po potrebi može proširivati

Ispis pomoću cout

cout je globalni objekt klase iostream koji se automatski stvara izvođenjem programa u čiji je izvorni kod uključena datoteka iostream. On usmjerava ispis podataka na ekran računara pomoću operatora <<. Taj operator je preopterećen za sve ugrađene tipove podataka, a korisnik ga može po potrebi preopteretiti za korisnički definisane tipove.

Ispis podataka ostvaruje se pomoću izlaznog operatora <<. On se obično zove operatorom umetanja (engl. insertion operator), jer se njime podatak umeće na izlazni tok. Sa desne strane operatora << se može nači bilo koji tip podataka: char, short, int, long int, float, double, pa čak i string...

Page 17: Seminar Ski Text

cout << 9.3 << endl; // floatcout << ‘C’ << endl; // charcout << “My name is C++” << endl; // string

Učitavanje pomoću cin

Učitavanje podataka je slično ispisu podataka. Pokretanjem programa u koji je uključena datoteka zaglavlja iostream automatski se stvara globalni objekt cin klase iostream. Učitavanje podataka se ostvaruje pomoću ulaznog operatora >>. On se obično zove operatorom izlučivanja (engl. extraction operator), jer se njime podatak izlučuje s izlaznog toka. Sa desne strane se može naći bilo koji tip podataka za koji je ulazni tok definisan: char, short, int, float, double…

int i;long l;float f;double d;

cin >> i; // intcin >> l; // long intcin >> f; // floatcin >> d; // double

Naredbe za učitavanje se mogu ulančavati, pa smo gornja učitavanja mogli napisati i u jednoj naredbi:

cin >> i >> l >> f >> d;

Učitavanje se nastavlja od mjesta gdje je prethodno završilo. Pritom se praznine (znakovi za razmak, tabulator, novi red) standardno ignorišu i one služe za odvajanje pojedinih podataka. To znači da smo sve ulazne podatke za gornji primjer mogli napisati u jednom redu, razmaknute prazninama:

24 102345 34.56 4.56783

a tek potom pritisnuti taster za unos (Enter).

POLJA

Često se u programima koriste skupovi podataka istog tipa. Za označavanje i rukovanje takvim podacima bilo bi vrlo nespretno koristiti za svaki pojedini podatak zasebnu varijablu, npr. x1, x2, x3, x4, x5, itd. Neefikasnost ovakvog pristupa je više nego očita. Daleko efikasnije je sve podatke smjestiti pod isto nazivlje, a pojedini rezultat mjerenja dohvaćati pomoću brojčanog indeksa. Ovakvu obradu podataka omogućavaju polja (nizovi) podataka.

Polje podataka je niz konačnog broja istovrsnih podataka – članova polja. Ti podaci mogu biti bilo kojeg tipa, ugrađenog ili korisnički definisanog. Pojedini članovi polja mogu se dohvaćati pomoću cjelobrojnih indeksa te mijenjati nezavisno o ostalim članovima polja.

Page 18: Seminar Ski Text

Jednodimenzionalna polja

Najjednostavniji oblik polja su jednodimenzionalna polja kod kojih se članovi dohvaćaju preko samo jednog indeksa. Članovi polja složeni su u linearnom poretku, a indeks pojedinog člana odgovara njegovoj udaljenosti od početnog člana.

Želimo li deklarisati jednodimenzionalno polje x koje će sadržavati pet cijelih brojeva tipa int, napisaćemo

int x[5];

Prevoditelj će ovom deklaracijom osigurati kontinuirani prostor u memoriji za pet podataka tipa int. Ovakvom deklaracijom članovi polja nisu inicijalizovani.

Članovi polja se mogu inicijalizovati prilikom deklaracije:

int x[] = {10, 6, 14, 21, 43};

Ovom naredbom se deklariše jednodimenzionalno polje x ,te se članovima tog polja pridjeljuju početne vrijednosti. Dužina polje ne mora biti eksplicitno navedena, ali ako je navedemo onda moramo paziti da ona bude veća ili jednaka broju inicijalizovanih članova.

Pojedini članovi polaj se dalje u kodu dohvaćaju pomoću cjelobrojnog indeksa koji se navodi u uglatoj zagradi [] iza imena polja. Pri tome moramo znati da prvi član niza ima indeks 0, a zadnji član ima indeks za 1 manji od dužine polja.

int x[] = {10, 6, 14, 21, 43};x[1] = 9; //drugi član polja više nije 6 nego 9int a = x[0]; //varijabli a pridružujemo vrijednost prvog

člana polja, odnosno 10int b = a + x[1]; //varijabli b pridružujemo zbir vrijednosti

varijable a I vrijednosti drugog //člana polja xcout << b << endl; //na ekranu se ispisuje broj 19

Dvodimenzionalna polja

Jednodimenzionalna polja su veoma korisna stvar, međutim često se javlja potreba za pohranjivanjem podataka u dvodimenzionalne ili višedimenzionalne strukture. Želimo li pohraniti podatke iz neke tablice sa 3 reda i 5 lokona, najprikladnije ih je pohraniti u dvodimenzionalno polje.

int Tablica[3][5];

1. kolona 2. kolona 3. kolona 4. kolona 5. kolona1. red 2142. red3. red 101

Page 19: Seminar Ski Text

Članove ovog dvodimenzionalnog polja dohvaćamo preko dva indeksa: prvi je određen redom, a drugi kolonom u kojoj se podatak u tablici nalazi. Ne zaboravimo pritom da je početni indeks 0:

Tablica[0][0] = 214; //1. red, 1. kolonaTablica[2][1] = 101; //3. red, 2. kolona

Pravila koja veže za jednodimentionalna polja vrijede i za višedimenzionalna polja. Članovi višedimenzionalnog polja mogu se takođe inicijalizovati prilikom deklaracije:

int Tablica[3][5] = { {11, 12, 13, 14, 15}, {21, 22, 23, 24, 25} };

Sve operacije koje se rade sa jednodimenzionalnim poljima mogu se raditi i sa dvodimenzionalnim poljima na isti način.

ZNAKOVNI NIZOVI I STRINGOVI

Za pohranjivanje teksta koriste se znakovni nizovi (en. character strings, kraće strings). U suštini su to jednodimenzionalna polja čije članove čine znakovi (char). Prilikom inicijalizacije znakovnog niza, njegov sadržaj se navodi unutar para znakova “ (dvostruki navodnici):

char ime[] = “Marko”;char prezime[] = “Marković”;

U standardnoj biblioteci jezika C++ definisana je klasa string koji omogućava daleko jednostavnije baratanje znakovnim nizovima. Ta klasa sama vodi računa o osiguravanju dovoljnog prostora za znakovni niz te podržava niz mnoge funkcije i operacije. Na primer:

string ime = “Branimir”; //deklariše string ime i dodjeljuje

//mu vrijednost “Branimir”

string prezime = “Teodorovic”; //deklariše string ime i dodjeljuje mu //vrijednost “Teodorovic”

cout << ime + “, “ + prezime << endl; //sabira stringove ime i prezime

//i ispisuje na ekran Branimir, Teodorovic

cout << ime.substr(1, 4) << endl; //vraća podstring stringa ime od mjesta 1

//i dužine 4

cout << ime.empty() << endl; //vraća 0 ako je string prazan, odnosno 1 //ako nije prazan

cout<< prezime.insert(0, “007”) << endl; // umeće string “007” u string //prezime

// počevši od pozicije 0 u stringu prezime

cout<< prezime.erase(0, 3) << endl; //uklanja iz stringa prezime podstring dužine //3, počevši od mjesta 0

cout<< prezime.find(“o”) << endl; //pronalazi poziciju prvog pojavljivanja //stringa “o” unutar stringa prezime. Ako ne nađe vraća broj -1

Page 20: Seminar Ski Text

cout<< prezime.find(“o”, 3) << endl; //pronalazi poziciju prvog pojavljivanje //stringa “o” unutar stringa prezime počevši //od pozicije 3

cout << ime.length() << endl; //vraća dužinu stringa ime, odnosno u ovom //slučaju 8

NAREDBE ZA KONTROLU TOKA PROGRAMA

U većini realnih problema tok programa nije linearan i jedinstven pri svakom izvođenju. Redovno postoji potreba da se pojedini odsječci programa ponavljaju - programski odsječci koji se ponavljaju nazivaju se petljama (engl. loops). Ponavljanje može biti unaprijed određeni broj puta, npr. želimo li izračunati rezultat množenja svih cijelih brojeva od 1 do 100. Međutim, broj ponavljanja može zavisiti i od rezultata neke operacije.

Gotovo uvijek se javlja potreba za grananjem toka, tako da se ovisno o postavljenom uslovu u jednom slučaju izvodi jedan dio programa, a u drugom slučaju drugi dio.

Blokovi naredbi

Dijelovi programa koji se uslovno izvode ili čije se izvođenje ponavlja grupišu se u blokove naredbi - jednu ili više naredbi koje su omeđene parom otvorena-zatvorena vitičasta zagrada {}. Izvana se taj blok ponaša kao jedinstvena cjelina, kao da se radi samo o jednoj naredbi. Blokovi naredbi se obično pišu uvučeno. To uvlačenje radi se isključivo radi preglednosti, što je naročito važno ako imamo blokove ugniježđene jedan unutar drugog.

Važno svojstvo blokova jest da su varijable deklarisane u bloku vidljive samo unutar njega. Zbog toga će prevođenje koda

#include <iostream> using namespace std;

int main(){

{ // početak bloka naredbi int a = 1; // lokalna varijabla u bloku cout << a << endl; } // kraj bloka naredbi

return 0; }

proći uredno, ali ako naredbu za ispis lokalne varijable a prebacimo izvan bloka

#include <iostream> using namespace std;

int main() { {int a = 1; }

Page 21: Seminar Ski Text

cout << a << endl; // greška: a više ne postoji! return 0; }

dobićemo poruku o grešci da varijabla a koju pokušavamo ispisati ne postoji. Ovakvo ograničenje područja lokalne varijable (engl. scope - domet) omogućava da se unutar blokova deklarišu varijable s istim imenom kakvo je već upotrijebljeno izvan bloka.

Ako se blok u naredbama za kontrolu toka sastoji samo od jedne naredbe, tada se vitičaste zagrade mogu i izostaviti.

Grananje toka naredbom if

Naredba if omogućava uslovno grananje toka programa ovisno o tome da li je, ili nije zadovoljen uslov naveden iza ključne riječi if. Najjednostavniji oblik naredbe za uslovno grananje je:

if ( logički_izraz ) // blok_naredbi

Ako je vrijednost izraza iza riječi if logička istina (true), izvodi se blok naredbi koje slijede iza izraza. U protivnom se taj blok preskače i izvođenje nastavlja od prve naredbe iza bloka. Na primer:

if (a < 0){

cout << "Broj a je negativan!" << endl; }

U slučaju da blok sadrži samo jednu naredbu, vitičaste zagrade koje omeđuju blok mogu se i izostaviti.

Želimo li da se ovisno u rezultatu izraza u if uslovu izvode dva nezavisna programska odsječka, primijenit ćemo sledeći oblik uslovnog grananja:

if ( logički_izraz ) // prvi_blok_naredbi

else // drugi_blok_naredbi

Kod ovog oblika, ako izraz u if uslovu daje kao rezultat logičku istinu (true), izvešće se prvi blok naredbi. Po završetku bloka, izvođenje programa nastavlja se od prve naredbe iza drugog bloka. Ako izraz daje kao rezultat logičku neistinu (false), preskače se prvi blok, a izvodi samo drugi blok naredbi, nakon čega se nastavlja izvođenje naredbi koje slijede. Evo jednostavnog primjera u kojem se računa da li je određeni broj paran ili ne. Ako jeste, program ispisuje da je broj paran, ako ne odna ispisuje da je broj neparan.

int main(){

int x = 5;

Page 22: Seminar Ski Text

string rezultat;if (x%2 == 0)

rezultat = “paran”;else

rezultat = “neparan”;cout << "Broj " << x << " je " << rezultat << endl;system ("pause"); return 0;}

Blokovi if naredbi se mogu nadovezivati:

if ( logički_izraz1 ) // prvi_blok_naredbi else if ( logički_izraz2 ) // drugi_blok_naredbi else if ( logički_izraz3 ) // treći_blok_naredbi ... else // zadnji_blok_naredbi

Blokovi if naredbi mogu se ugnježđivati jedan unutar drugoga.

if ( logički_izraz ){ // blok_naredbi if ( logički_izraz ) // blok_naredbi

else // blok_naredbi

}else if ( logički_izraz ){ // blok_naredbi if ( logički_izraz )

// blok_naredbi

}else if ( logički_izraz )// blok_naredbi... else // blok_naredbi

Grananje toka naredbom switch

Kada izraz uslova daje više različitih cjelobrojnih rezultata, a za svaki od njih treba provesti različite odsječke programa, tada je umjesto if grananja često preglednije koristiti switch grananje. Kod tog grananja se prvo izračunava neki izraz koji daje cjelobrojni rezultat. Ovisno o tom rezultatu, tok programa se preusmjerava na neku od grana unutar switch bloka naredbi. Opšta sintaksa switch grananja izgleda ovako:

switch ( cjelobrojni_izraz ){

Page 23: Seminar Ski Text

case konstantan_izraz1 : // blok_naredbibreak;

case konstantan_izraz2 : // blok_naredbi break;

case konstantan_izraz3 :// blok_naredbi break;

case konstantan_izraz4 : // blok_naredbi break;

default: // blok_naredbi

}

Prvo se izračunava cjelobrojni_izraz, koji mora davati cjelobrojni rezultat. Ako je rezultat tog izraza jednak nekom od konstantnih izraza u case uslovima, tada se izvode sve naredbe koje slijede pripadajući case uslov sve do prve break naredbe. Nailaskom na break naredbu, izvođenje koda u switch bloku se prekida i nastavlja se od prve naredbe iza switch bloka. Ako izraz daje rezultat koji nije naveden niti u jednom od case uslova, tada se izvodi blok naredbi iza ključne riječi default.

Evo i konkretnog primjera switch grananja:

#include <iostream> using namespace std;

int main(){

cout << "Unesite broj od 1 do 5." << endl; int x; cin >> x;

switch(x) { case 1: cout << "Unijeli ste broj jedan" << endl; break; case 2: cout << "Unijeli ste broj dva" << endl; break; case 3: cout << "Unijeli ste broj tri" << endl; break; case 4: cout << "Unijeli ste broj četiri" << endl; break; case 5: cout << "Unijeli ste broj pet" << endl; break; default: cout << "Unijeli ste pogrešan broj" << endl; }

system ("pause"); return 0;}

Blok default može biti smješten bilo gdje unutar switch bloka, no zbog preglednosti je preporučljivo staviti ga na kraj. On se smije i izostaviti, ali ga je zgodno imati da bi

Page 24: Seminar Ski Text

kroz njega program prošao za vrijednosti koje nisu obuhvaćene case blokovima. Ovo je naročito važno tokom razvijanja programa, kada se u default blok može staviti naredba koja će ispisivati upozorenje da je cjelobrojni izraz u switch poprimio neku nepredviđenu vrijednost.

Petlja for

Često u programima treba ponavljati dijelove koda. Ako je broj ponavljanja poznat prije ulaska u petlju, najprikladnije je koristiti for petlju. Njen oblik je:

for ( početni_izraz ; uslov_izvođenja ; izraz_prirasta ) // blok_naredbi

Iza ključne riječi for, unutar okruglih zagrada () navode se tri grupe naredbi, međusobno odvojenih znakom tačka-zarez ;. Postupak izvođenja for-bloka je sledeći:

1. Izračunava se početni_izraz. Najčešće je to pridruživanje početne vrijednosti brojaču kojim će se kontrolirati ponavljanje petlje.

2. Izračunava se uslov_izvođenja, izraz čiji rezultat mora biti tipa bool. Ako je rezultat jednak logičkoj neistini, preskače se blok_naredbi i program se nastavlja prvom naredbom iza bloka.

3. Ako je uslov_izvođenja jednak logičkoj istini, izvodi se blok_naredbi. 4. Na kraju se izračunava izraz_prirasta (npr. povećavanje brojača petlje). Program se

vraća na početak petlje, te se ona ponavlja od tačke 2.

Programski odsječak se ponavlja sve dok uslov_izvođenja na početku petlje daje logičku istinu; kada rezultat tog izraza postane logička neistina, programska petlja se prekida.

Kao primjer za for petlju, napišimo program za računanje faktorijela (faktorijela od n je rezultat množenja svih brojeva od 1 do n):

n! = 1⋅ 2⋅⋅ (n - 2)⋅ (n - 1)⋅ n

Pogledajmo kod:

#include <iostream> using namespace std;

int main(){

int n;cout << "Upiši prirodni broj: "; cin >> n;

long int faktorijel = 1; for (int i = 2; i <= n; i++) fjel *= i; cout << n << "! = " << faktorijel << endl; return 0;

}

Page 25: Seminar Ski Text

Prije ulaska u petlju trebamo definisati početnu vrijednost varijable faktorijel u koju ćemo gomilati umnoške. Na ulasku u petlju deklarišemo brojač petlje, varijablu i tipa int te joj pridružujemo početnu vrijednost 2 (početni_izraz: int i = 2). Unutar same petlje množimo faktorijel s brojačem petlje, a na kraju tijela petlje uvećavamo brojač (izraz_prirasta: i++). Petlju ponavljamo sve dok je brojač manji ili jednak unesenom broju (uslov_izvođenja: i <= n).

Može se dogoditi da je uslov izvođenja uvijek zadovoljen, pa će se petlja izvesti neograničeni broj puta. Program će uletjeti u slijepu ulicu iz koje nema izlaska. Na primjer:

cout << "Beskonačna petlja"; for (int i = 5; i > 1; )

cout << "a";

Varijabla i je uvijek veća od 1, tako da ako se i usudite pokrenuti ovaj program, ekran će vam vrlo brzo biti preplavljen slovom a.

Uočimo da smo u gornjem kodu izostavili izraz_prirasta. Uglavnom se može izostaviti bilo koji od tri izraza u for naredbi - jedino su oba znaka ; obavezna.

Izostavi li se uslov_izvođenja, podrazumijevana vrijednost će biti true i petlja će biti beskonačna!

Štoviše, mogu se izostaviti i sva tri izraza:

for ( ; ; ) // opet beskonačna petlja!

for petlje mogu biti ugniježđene jedna unutar druge. Ponašanje takvih petlji razmotrit ćemo na sljedećem programu:

#include <iostream> #include <iomanip> using namespace std;

int main(){

for (int red = 1; red <= 10; red ++){

for (int kolona = 1; kolona <= 10; kolona ++) cout << setw(5) << red * kolona;

cout << endl; }return 0;

}

Nakon prevođenja i pokretanja programa, na ekranu će se ispisati tablica množenja do 10.

Kako se gornji program izvodi? Pri ulasku u vanjsku petlju, inicijalizuje se brojač redova na vrijednost 1 te se s njom ulazi u unutrašnju petlju. U unutrašnjoj petlji se brojač kolona mijenja od 1 do 10 i za svaku pojedinu vrijednost izračunava se njegov umnožak s brojačem redova. Po završenoj unutrašnjoj petlji ispisuje se znak za novi red, čime završava blok naredbi vanjske petlje. Slijedi prirast brojača redova (red = 2) i povrat na početak vanjske petlje. unutrašnja

Page 26: Seminar Ski Text

petlja se ponavlja od kolona = 1 do kolona = 10 itd. Kao što vidimo, za svaku vrijednost brojača vanjske petlje izvodi se cjelokupna unutrašnja petlja.

Da bismo dobili ispis brojeva u pravilnim kolonama, u gornjem primjeru smo koristili operator za rukovanje (manipulator) setw(). Argument tog manipulatora (tj. cijeli broj u zagradi) određuje koliki će se najmanji prostor predvidjeti za ispis podatka koji slijedi u izlaznom toku. Ako je podatak kraći od predviđenog prostora, preostala mjesta biće popunjena prazninama. Manipulator setw() definisan je u datoteci zaglavlja iomanip.

Petlja while

Druga od tri petlje kojima jezik C++ raspolaže jest while petlja. Ona se koristi uglavnom za ponavljanje segmenta koda kod kojeg broj ponavljanja nije unaprijed poznat. Sintaksa while bloka je

while ( uslov_izvođenja ) // blok_naredbi

Uslov izvođenja je izraz čiji je rezultat tipa bool. Tok izvođenja while-petlje je sledeći:

1. Izračunava se logički izraz uslov izvođenja. 2. Ako je rezultat jednak logičkoj neistini, preskače se blok naredbi i program se nastavlja od prve

naredbe iz bloka. 3. Ako je uslov izvođenja jednak logičkoj istini izvodi se blok naredbi. Potom se program vraća na

while naredbu i izvodi od tačke 1.

Konkretnu primjenu while petlje daćemo programom kojim pitamo korisnika da li po zavrsetku igre želi igrati ponovo.

#include <iostream>using namespace std;

int main(){ char again = 'y';

while (again == 'y') { cout << "\n**Played an exciting game**"; cout << "\nDo you want to play again (x/y)?"; cin >> again; } cout << "OK, bye"; system ("pause"); return 0;}

Na početku programa se stvara varijabla again i njena vrijednost se postavlja na ‘y’. Zatim program pokreće while petlju i provjerava da li je vrijednost again jednaka ‘y’. Zato što jeste, program ispisuje poruku "**Played an exciting game**". Zatim pita korisnika da li želi igrati

Page 27: Seminar Ski Text

ponovo i odgovor pridružuje varijabli again. Petlja se nastavlja sve dok korisnik unosi odgovor ‘y’.

Koji će se pristup koristiti (for-petlja ili while-petlja) prvenstveno zavisi od sklonostma programera. Ipak, zbog preglednosti i razumljivosti koda for-petlja je preporučljivo koristiti kada se broj ponavljanja petlje kontroliše cjelobrojnim brojačem. U protivnom, kada je uslov ponavljanja određen nekim logičkim uslovom, praktičnije je koristiti while naredbu.

Petlja do-while

Zajedničko for i while naredbi jest ispitivanje uslova izvođenja prije izvođenja naredbi bloka. Zbog toga se može dogoditi da se blok naredbi ne izvede ni jednom. Međutim, često je neophodno da se prvo izvede neka operacija te da se, zavisno od njenog ishoda, ta operacija eventualno ponavlja. Za ovakve slučajeve pogodnija je do-while petlja:

do // blok_naredbi while ( uslov_ponavljanja );

Svakako treba uočiti da: while uslov ponavljanja mora biti zaključen znakom tačka-zarezom ; (za razliku od naredbe while koju je neposredno slijedio blok naredbi)

Primjenu do-while bloka ilustrirat ćemo programom-igricom u kojem treba pogoditi slučajno generisani trazeni broj. Nakon svakog našeg pokušaja ispisuje se samo poruka da li je broj veći ili manji od traženog. Petlja se ponavlja sve dok je pokušaj (mojBroj) različit od traženog broja.

#include <iostream> #include <cstdlib> #include <ctime> using namespace std;

int main() {

srand(time(0)); // inicijališe generator slučajnih brojeva

// generiše slučajni broj između 1 i 10 int trazeniBroj = (rand()% 10) + 1;

cout << "Treba pogoditi broj izmedju 1 i 10" << endl; int mojBroj; int brojPokusaja = 0;

do{

cout << ++brojPokusaja << ". pokusaj: "; cin >> mojBroj;

if (mojBroj > trazeniBroj) cout << "MANJE!" << endl;

else if (mojBroj < trazeniBroj) cout << "VISE!" << endl;

} while(mojBroj != trazeniBroj);

Page 28: Seminar Ski Text

cout << "BINGO!!!" << endl;

system("pause");return 0;}

Za generisanje slučajnih brojeva upotrijebljena je funkcija rand() iz zaglavlja cstdlib. Ona kao rezultat vraća slučajni broj između 0 i RAND_MAX, pri čemu je RAND_MAX broj takođe definisan u cstdlib biblioteci. Da bismo generisali broj u rasponu između 1 i 10, broj koji vraća funkcija rand() podijelili smo s % i povećali bi ga za 1.

Uzastopni pozivi funkcije rand() uvijek generiršu isti slijed slučajnih brojeva, a prvi poziv te funkcije daje uvijek isti rezultat. Da bi se izbjegle katastrofalne posljedice takvog svojstva na neizvjesnost igre, prije poziva funkcije rand() pozvali smo funkciju srand() koja inicijališe klicu generatora slučajnog broja, tj. postavlja početni "slučajno" generirani broj što ga daje rand() na neku drugu vrijednost. Funkciji srand() treba kao argument navesti neki cijeli broj na osnovu kojeg će se izračunati vrijednost klice. Iako bismo tu vrijednost mogli sami zadavati, bolje je to uraditi pomoću funkcije time(), definisane u standardnoj biblioteci ctime, koja učitava trenutno sistemsko vrijeme (broj sekundi što ih odbrojava interni sat u računaru od referentnog trenutka) i ono se koristi kao osnovica za klicu. Budući da nema šanse da program pokrenete više puta unutar iste sekunde , tako generirani brojevi će biti stvarno slučajni.

Naredbe break i continue

Naredba break može se koristiti samo u petljama te u switch grananjima. Njenu funkciju u switch grananjima smo već upoznali, dok se u petljama njome prekida izvođenje okolne for, while ili do-while petlje. Na primer, želimo li da se pogađanje slučajnog broja u prethodnom primjeru prekine kada unesemo broj 0, to ćemo uraditi na sledeći način:

do{

cout << ++brojPokusaja << ". pokusaj:"; cin >> mojBroj;

if (mojBroj == 0){

cout << "Game over!" << endl; break;

}

if (mojBroj > trazeniBroj) cout << "MANJE!" << endl;

else if (mojBroj < trazeniBroj) cout << "VISE!" << endl;

} while(mojBroj != trazeniBroj);

if (mojBroj == trazeniBroj)cout << "BINGO!!!" << endl;

Nailaskom na znak broj 0 program iskače iz do-while-petlje te se prekida daljnje učitanjavanje brojeva.

Page 29: Seminar Ski Text

Naredba continue također uzrokuje skok programa na kraj petlje, ali se potom njeno ponavljanje nastavlja. Na primer, ako imamo jedno polje sa 10 članova, a članovi su brojevi od 1 do 10, i želimo da ispišemo na ekran samo parne elemente tog polja to ćemo uraditi na sledeći način:

int polje[10] = {1,2,3,4,5,6,7,8,9,10}; for (int i=0; i<10; ++i) { if(polje[i]%2 == 0) continue; else cout << polje[i] << "\t"; } cout << endl;

Nailaskom na član polja koji je neparan broj, izvodi se naredba continue - preskaču se sve naredbe do kraja petlje (u ovom slučaju je to naredba za ispis znaka), ali se ponavljanje petlje dalje nastavlja kao da se ništa nije dogodilo.

Ako je više petlji ugniježđeno jedna unutar druge, naredba break ili naredba continue prouzrokovaće prekid ponavljanja, odnosno nastavak okolne petlje u kojoj se naredba nalazi.

Naredba goto

Naredba goto omogućava bezuslovni skok na neku drugu naredbu unutar iste funkcije. Opšti oblik je:

goto imeOznake ;

imeOznake je simbolički naziv koji se mora nalaziti ispred naredbe na koju se želi prenijeti kontrola, odvojen znakom : (dvotačka). Na primer

if (a < 0) goto negativniBroj; //... negativniBroj: //naredba

Naredba na koju se želi skočiti može se nalaziti bilo gdje (ispred ili iza naredbe goto) unutar iste funkcije. ime_oznake mora biti jedinstveno unutar funkcije, ali može biti jednako imenu nekog objekta ili funkcije.

U pravilno strukturiranom programu naredba goto uopšte nije potrebna, te je velika većina programera uopšte ne koristi.

Page 30: Seminar Ski Text

ZAKLJUČAK

C++ jezik je danas jedan od najpopularnijih programskih jezika korišćenih za razvoj računarskih aplikacija. Razvio ga je Bjarne Stroustrup 1980. god. kao proširenje jezika C sa klasama. C++ omogućava proceduralno i objektno orjentisano programiranje. Ovaj jezik je vrlo složen i velikih mogućnosti, a namijenjen je ponajprije stručnjacima koji se profesionalno bave pisanjem programa. Temeljni razlozi njegove velike popularnosti su djelotvornost, prilagodljivost i dobra normiranost.

U ovom seminarskom sam pokušao objasniti neke osnove programiranja u jeziku C++.