programiranje u c

Upload: wolfbladem

Post on 12-Oct-2015

123 views

Category:

Documents


3 download

DESCRIPTION

Programiranje u C

TRANSCRIPT

  • Programiranje u C++ jeziku 1

    Programiranje u C++ jeziku Svaki program napisan u C++ jeziku mora imati slijedei minimum: main () { } Ovakav program nita ne radi, ali moemo analizirati obvezni kostur svakog programa: - main je slubena rije koja oznaava glavni dio programa odakle e se on poeti

    izvravati kada ga pokrenemo. - ( ) prazne zagrade omoguavaju dodavanje argumenata koji e biti proslijeeni

    programu prilikom pokretanja (najee to nije potrebno, pa zagrade ostaju prazne).

    - { otvorena vitiasta zagrada oznaava poetak glavnog izvrnog bloka programa. Unutar glavnog bloka mogu biti drugi programski blokovi, to emo kasnije nauiti kroz primjere.

    - } zatvorena vitiasta zagrada oznaava kraj programa. Napiimo sada program koji neto radi: Zadatak: napiite program koji mnoi dva broja. main() { int a,b,c; a=5; b=7; c=a*b; } Prva novost koju ovdje vidimo je rije int iza koje su pobrojana tri slova a,b,c. Na taj nain deklariramo tri varijable: a, b, c tipa cijeli broj (int je skraeno od integer cijeli broj). Definicija: varijabla je imenovani dio memorije. Sve podatke koje trebamo obraivati moramo na neki nain staviti u memoriju raunala. Mogli bismo to i direktno uiniti (o tome kasnije) tako da u odreenu memorisku lokaciju1 upiemo potrebne brojeve, ali je ovako jednostavnije: Kada u izvravanju programa raunalo naie na red: int a,b,c; ono rezervira tri mjesta u memoriji (i to dovoljne duine da u njih moe stati cijeli broj) i oznai ih redom s: a, b i c. Na kraju reda je ; (toka zarez) to je separator programskog reda. Program moe biti fiziki napisan u jednom redu npr.: main(){ int a,b,c; a=5;b=7;c=a*b;}, a toka zarez oznaava kraj instrukcije ili programskog reda. Ali programe ipak piemo u vie redova zbog preglednosti.

    1 memorijske lokacije su oznaene brojevima od 0 do koliko imate memorije u raunalu. Ti redni brojevi memoriskih lokacija zovu se adrese.

  • Programiranje u C++ jeziku 2

    Slijedea dva reda su slina: a=5; i b=7; . To su primjeri dodjele vrijednosti varijablama. Nakon izvrenja ovoga u memoriji na mjestu (adresi) koje je rezervirano za varijablu a upisan je broj 5, a na mjestu rezerviranom za varijablu b upisno je 7. Posljednji red je takoe dodjela vrijednosti varijabli, ali u ovom sluaju s desne strane znaka jednakosti nalazi se izraz: a*b. Taj izraz se prvo izrauna, to znai da se ona vrijednost koja je upisana u varijablu a pomnoi s onom vrijednou koja je upisana u varijablu b i tako dobiveni rezultat upie u varijablu c. U ovom sluaju pomnoe se 5 i 7 pa se rezultat (35) upie u c. Tako, sada se u varijabli c nalazi rezultat, ali mi bi htjeli jo i vidjet taj rezultat na ekranu. Zanimljivo je, ali programski jezik C++ nema u svojoj osnovi naredbe za ispis na ekran. To je napravljeno zbog kompaktnosti programa tj. da se u izvrni kod ne ukljuuje nita to nije potrebno2. U ovom sluaju treba nam ispis rezultata pa tu dodatnu mogunost moramo ukljuiti. To radimo na slijedei nain: u prvom redu programa, prije main() piemo: #include a poslije zadnjeg reda (prije zagrade }): cout

  • Programiranje u C++ jeziku 3

    #include main() { int r=17; float pi =3.14, p; p=r*r*pi; cout

  • Programiranje u C++ jeziku 4

    Radi se o sposobnosti C++ jezika da dodijeljuje vrijednosti iz jednog tipa varijable u drugi. U ovom sluaju iz tipa int (varijable a, b i konstanta 2) u tip float (varijabla p). Drugi programski jezici (npr. Pascal) bi na tom mjestu prijavili greku. C++ ne prijavljuje greku nego rezultat izraza a*b/2 (jer su svi brojevi cijeli) izrauna kao tip int i kao takav ga postavi u varijablu p. Ako elimo eksplicitno naglasiti kako nam treba tip float, iz izraza s cijelim brojevima, to moramo pisati na slijedei nain: p=(float) a*b/2; Ovako promijenjeni izraz daje toan rezultat 13.5 . Ova osobina nas tjera na pisanje programa s malo veom pozornou u praenju tipova varijabli s desne strane znaka jednakosti i oekivanog rezultata s lijeve strane prema tipu varijable u koju se izraunata vrijednost sprema. To ima i svoju dobru stranu: u veini drugih programskih jezika postoji poseban operator za cjelobrojno dijeljenje (npr. div u Pascalu, \ u BASICU) dok u C++ potreban oblik rezultata moemo regulirat kljunim rijeima ( float, int itd.) ili odgovarajuim izborom tipova varijabli koje sudjeluju u izrazu (pogledajte 2. zadatak). Zadatak: napiite program koji za uneseni n izraunava drugi korijen iz n. #include #include main() { int n;float k; cin>>n; k=sqrt(n); cout

  • Programiranje u C++ jeziku 5

    Zadaci za vjebu: Napiite program koji izraunava treu potenciju unesenog broja x. Napiite program koji za unesene katete a i b izraunava hipotenuzu pravokutnog trokuta. Napiite program za izraunavanje vrijedosti sinusa za uneseni x. Ako x hoete unijeti u stupnjevima onda ga prvo treba pretvoriti u radijane: xr=xs*pi/180. Unose se koordinate dviju toaka: x1,y1 i x2,y2. Napiite program koji izraunava njihovu udaljenost. Program od korisnika trai da upie godinu roenja, a zatim izraunava koliko ima godina. Brzina koja je potrebna za uzlet nekog tijela na visinu h moe se izraunati iz formule v2=2g h . Srednja brzina molekula zraka na 0o C je 500 m/s. Do koje visine moe doi molekula u tim uvjetima. Matematike funkcije sadrane u abs(x) - apsulutna vrijednost int x4 fabs(x) - apsulutna vrijednost float x cabs(x) - apsulutna vrijednost kompleksnog broja (x mora biti tipa complex) labs(x) - apsulutna vrijednost kao tip long sin(x) -sinus x5 cos(x) - kosinus x tan(x) - tangens x asin(x) - arkus sinus x acos(x) - arkus kosinus x atan(x) - arkus tangens x atan2(x,y) - atan(x/y) sinh(x) - hiperbolini sinus x cosh(x) - hiperbolini kosinus x tanh(x) -hiperbolini tangens x ceil(x) - zaokruuje na vie ili jednako floor(x) - zaokruuje na manje fmod(x,y) - ostatak pri dijeljenju decimanih brojeva frexp(x,*e) - dijeli decimalni broj na mantisu i eksponent modf(x,*i) - dijeli decimalni broj na cijeli i decimalni dio exp(x) - e na x pow(x,y) - x na y pow10(x) - 10 na x sqrt(x) - korijen x ldexp(x,e) - x*2 na eksponent, npr. ldexp(3,10) izraunava 3*210 hypot(a,b) - izraunava hipotenuzu pravokutnog trokuta ako su a i b katete log(x) - prirodni logaritam log10(x) - dekadski logaritam poly(x,n,k[]) - izraunava polinom n-tog stupnja za zadani x i koeficijente zadane u nizu k[] atof(x) - konvertira string u broj

    3. tablica: matematike funkcije sadrane u 4 x,y,a itd. u zagradi funkcije simboliziraju: varijablu, konstantu, izraz ili drugu funkciju. Naravno moramo paziti na uobiajena pravila koja vrijede za matematike funkcije: raunalo ne moe izraunati korijen iz negativnog broja i slino. 5 argument trigonometrijskih funkcija zadaju se u radijanima.

  • Programiranje u C++ jeziku 6

    Tipovi varijabli:

    Tip: Vrsta podatka: Primjer: broj bitova

    int cijeli broj od -32768 do +32767 int a=156; 16 unsigned int neoznaeni cijeli broj od 0 do 65535 unsigned int=50000; 16 long cijeli broj od - 2147483648 do

    2147483647 long a=100000; 32

    unsigned long

    neoznaeni cijeli broj od 0 do 4294967295

    unsigned long a=10000000;

    32

    float realni broj od 3.4*10-38 do 3.4*10+38 float a=5e-7; 32 double realni broj od 1.7*10-308

    do 1.7*10-308 double a=5e+100; 64

    long double realni broj od 3.4*10-4932 do 1.1*10+4932

    long double a=2e-1000;

    80

    char slovo ili cijeli broj od -128 do 128

    char a='A'; char a=65;

    8

    unsigned char

    slovo ili cijeli broj od 0 do 255

    char a='A'; char a=255;

    8

    4. tablica: popis tipova varijabli Saetak: Programi poinju rijeju main i zagradama (): main() Programski blok je oznaen otvorenom i zatvorenom vitiastom zagradom:

    {...program...} koje oznaavaju poetak { i kraj programa }. Podatke smjetamo u varijable koje su odreene svojim imenom i tipom. Tip varijable ovisi o vrsti podatka koji elimo smjestiti u varijablu (memoriju). Ime varijable je jedno slovo ili rije ili kombinacija slova i broja s time da broj ne

    smije biti na prvom mjestu. Npr: a, aa, br, n3, proba2. U imenu varijable moemo koristiti donju crtu: prvi_n U imenu varijable ne moemo koristiti nikakve druge znakove ili razmak. Velika i mala slova se razlikuju u C++ jeziku. Prije uporabe varijable moramo deklarirati: tip_varijable ime_varijable; Svaka instrukcija (logiki programski red) mora zavravati toka zarezom (;). Varijabli se moe dodijeliti vrijednost odmah u deklaraciji: int a=0; ili kasnije u

    programu. Sa desne strane znaka jednakost moe biti konstanta: a=5; izraz a=2+2; varijabla:

    a=b; funkcija: a=pow(2,10); ili neka kombinacija pobrojanog a=3*x+sin(n);. Predprocesorskom instrukcijom #include ukljuuju se biblioteke preddefiniranih

    funkcija. Funkcije za unos i ispis vrijednosti definirane su u #include Vrijednost varijable korisnik moe unijeti za vrijeme izvoenja programa s

    instrukcijom npr: cin>>n; Ispisujemo s instrukcijom npr. cout

  • Petlje 7

    Petlje Petlje su naredbe koje omoguavaju da se dijelovi programa izvravaju vie puta. Moemo ih podijeliti na petlje s kontroliranim brojem ponavljanja (for), kontroliranim ulazom (while) i kontroliranim izlazom (do while).

    For petlja Ovo je petlja s kontroliranim brojem ponavljanja. Opi oblik je: for (varijabla=poetak; logiki uvjet; promjena varijable) {programski blok;} npr.

    for ( i=1; i

  • Petlje 8

    || logiki ili (OR) a10 -tono za sve vrijednosti osim onih izmeu 5 i 10

    ! logiki ne (NOT) !(a==5) isto to i a!=5 5. tablica: tablica logikih operatora

    2. Zadatak: napiite program koji izraunava sumu prvih 100 prirodnih

    brojeva. #include main(){int i,s; s=0; for (i=1;i

  • Petlje 9

    U for petlji se izvravaju 3 naredbe pa one moraju biti u progrmskom bloku { }. Programski red: cout

  • Petlje 10

    6. Zadatak: napiite program koji izraunava sumu znamenki unesenog broja. Varijabla p e biti uneseni broj, s e biti suma. Cjelobrojna varijabla tipa int se u memoriji sprema u dva bayta tj. 16 bita. Najvei broj koji se moe na taj nain napisati je: 2broj_bita -1, u ovom sluaju to bi bilo 216-1= 65535. Meutim jedan bit se mora rezervirati za predznak broja pa ostaje samo 15 bita, a to znai da je najvei broj tipa int 215-1= 32767. Na to treba paziti kada unosimo varijable tipa int. Ako nam je to malo int moemo zamijeniti s tipom long koji se upisuje u 4 byta pa je onda najvei broj koji moemo upisati: 231-1=2147483647 #include main() {int p,s=0; cin>>p; while (p>0){ s+=p%10;p/=10;} cout

  • Petlje 11

    se odmah prelazi na drugu unutarnju petlju koja od b oduzima a. Kad se brojevi izjednae vanjska petlja prekida i ispisuje se jedan od njih (isti su).

    DO WHILE petlja Opi oblik ove petlje je: do {programski blok;} while(logiki uvjet); Na primjer: do cin>>p; while (p5); I ovdje vrijedi pravilo: ako je u programskom bloku upisana samo jedna naredba ne trebaju vitiaste zagrade. Primjer bi se mogao koristiti za upis ocjena jer e petlja ponavljati ako se unese broj manji od jedan ili vei od 5, tj. ako se unese regularna ocjena petlja se prekida inae se vraa na unos. 8. Zadatak: napiite program koji izraunava prosjek unesenih brojeva, unos se

    prekida kada upiemo nulu. Za vrijeme unosa potrebno je zbrajati unesene brojeve i brojati koliko ih unosimo: Varijabla n e brojati koliko smo brojeva unijeli, s e biti suma, a p broj koji unosimo #include main() {int n=0,s=0,p; do {cin>>p; s+=p;n++;} while(p!=0); n--; cout

  • Petlje 12

    a=3

    a1=(a+b)/2=2 b=a/a1=1.5 a1=2

    a1=(a1+b)/2=1.75 b=a/a1= 1.714 a1=1.75

    b=1

    b=1.5

    b=1.714

    I tako nastavljamo s aproksimacijama dok ne izjednaimo stranice ili dok ne postignemo zadovoljavajuu tonost. #include main() { const double t=0.00001; // tocnost double a,a1,b; cout

  • Petlje 13

    Petlja se ponavlja dok je razlika u stranicama vea od traene tonosti. Teorijski mogli smo postaviti uvjet da se petlja prekine kada je a1==b ali zbog netonosti raunala (i tip float i tip double imaju ogranien broj bitova) moglo bi se dogoditi da se petlja nikada ne prekine. Saetak: Petlje izvravaju dijelove programa vie puta. Moemo ih podijeliti na petlje s kontroliranim brojem ponavljanja (for),

    kontroliranim ulazom (while) i kontroliranim izlazom (do while). Sve tri petlje se izvravaju dok je logiki uvjet zadovoljen. For petlja ima opi oblik:

    for (x=poetna_vrijednost; logiki_uvjet; promjena_vrijednosti) instrukcija; ili for (x=poetna_vrijednost; logiki_uvjet; promjena_vrijednosti) instrukcija1; else instrukcija2;

    U for petlji ne moraju biti sve tri kategorije, minimum je: for(;;) - beskonana petlja.

    Petlja se moe prekinuti naredbom break. While petlja ima opi oblik:

    while(logiki_uvjet) instrukcija; Logiki uvjet se provjerava na ulasku u petlju, pa ako nije zadovoljen petlja se

    nee izvriti nijendnom. Do while petlja ima opi oblik:

    do instrukcija while(logiki_uvjet); Instrukcija u ovoj petlji izvrit e se najmanje jedanput jer se uvjet provjerava tek

    na izlasku iz petlje.

  • Funkcije 14

    Funkcije Funkcije su dijelovi programa izdvojeni iz glavnog - main - dijela programa. U nekim drugim programskim jezicima takvi dijelovi programa se zovu podprogrami ili procedure. Njih moemo pozivati iz glavnog programa po imenu tj. navodei njihovo ime i argumente. Funkcije u pravilu vraaju neku vrijednost pa ih dodjeljujemo nekoj varijabli, koristimo ih u izrazu ili tu vraenu vrijednost direktno ispisujemo. Neke funkcije su ve definirane u C++, odnosno u bibliotekama koje ukljuujemo s #include na poetku programa. Takva je na primjer funkcija kvadratnog korijena s kojom smo se ve susreli u ranijim primjerima: a=sqrt (x); Ovo je primjer poziva funkciji: prosljeujemo joj argument x, ona izraunava korijen tog broja i tu izraunatu vrijednost vraa, a mi ju dodjeljujemo varijabli a. Moemo zakljuiti kako je opi oblik poziva funkciji: varijabla=ime_funkcije (argument); Argumenata moe biti i vie, na primjer funkcija za izraunavanje potencije nekog broja, definirana u ima dva argumenta: broj koji se potencira i potenciju: a=pow (5,3); U ovom primjeru funkcija pow e izraunati 53 tj. pet na treu potenciju. Izraunatu vrijednost moemo direktno ispisati, odnosno ne moramo je dodjeljivati nekoj varijabli: cout

  • Funkcije 15

    Na primjer: #include int kvadrat (int x) {int y; y=x*x; return y;} main() {int a =5; cout

  • Funkcije 16

    Funkcije ne moraju vraati nikakve vrijednosti, takve funkcije oznaavamo rijeju void. Na primjer: 12. Zadatak: napiite program koji ispisuje tablicu mnoenja koristei se

    funkcijom. #include void mnozi(int x, int y) {cout

  • Funkcije 17

    #include void fibo(int n) {int a=1,b=1,s,i; cout

  • Funkcije 18

    Ako je godina prestupna onda veljaa ima 29 dana inae ima 28. Vidimo da je iz samog koda programa jasno itljivo to se dogaa. Bez funkcije prestupna to bi izgledalo ovako: if ((g%4==0 && g%100!=0) || g%400==0) veljaca=29 else veljaca=28; to je daleko manje pregledno. Trei razlog pisanja funkcija je to se jedanput napisana funkcija moe vie puta pozvati iz glavnog programa ili drugih funkcija. Pogledajmo to u slijedeem primjeru: 15. Zadatak: napiite program za izraunavanje binomnog koeficijenta.

    Binomni koeficijent, pie se

    kn

    (ita se n iznad k) moe se izraziti faktorijelima:

    kn

    =)!(!

    !knk

    n

    Za uneseni n i k binomnog koeficijenta treba tri puta pozvati funkciju za raunanje faktorijela: za samo n, za k i za (n-k). Moemo se koristiti funkcijom fakt iz prethodnog zadatka: #include long fakt(int n) {long f=1; for (int i=2;i

  • Funkcije 19

    To se moe napisati koritenjem binomnih koeficijenata:

    01

    11

    02

    12

    22

    03

    13

    23

    33

    itd.

    Vidimo kako se gornji brojevi u binomnim koeficijentima mijenjaju s promjenom reda, a donji u svakom redu poinju od nule i rastu s lijeva u desno. Broj elemenata u svakom redu je za jedan vei od prethodnog. To nas asocira na dvostruku for petlju: vanjska petlja odreuje gornje, a unutarnja donje brojeve. Prethodni program je izraunavao binomne koeficijente i moemo ga upotrijebiti uz promjenu: glavni dio programa postat e funkcija binom, a ona e pozivati funkciju fakt. Sada jo treba smisliti kako e se ponaati petlje u glavnom programu: vanjska (s varijablom i) jednostavno broji 1,2,3... do koliko hoemo redova (to unosimo kao varijablu p). Unutarnja (s varijablom j) u prvom prolazu broji od 0 do 1, zatim od 0 do 2 itd. (vidi donje lanove binomnog koeficijenta u trokutu). Znai od nula do nekog broja koji se u svakom slijedeem prolazu vanjske petlje poveava za 1, a to radi i vanjska petlja. Ona je u prvom redu 1 (nama trebaju dva lana), u drugom 2 (nama trebaju 3 lana), dakle vanjska petlja plus 1. Ali budui da ona poinje od nule treba brojati jednostavno do i (pogledajte gornji i donji lan zadnjih binomnih koeficijenata u svakom redu). #include long fakt(int n) {long f=1; for (int i=2;i

  • Funkcije 20

    return(f);} int binom(int n,int k) {return (fakt(n)/(fakt(k)*fakt(n-k)));} void prazno(int m) {for(int i=0;i

  • Funkcije 21

    Datoteka8 proba.h: long double fakt(int n) {long double f=1; for (int i=2;i

  • Funkcije 22

    #include #include "proba.h" main() {cout

  • Funkcije 23

    cin>>a;cin>>b;} if (a>b) {p=a;a=b;b=p;} cout

  • Funkcije 24

    nalazi sadraj varijable y. On pokazuje na sadraj varijable y pa ga zato zovemo pokaziva. *x=5; zapravo stavlja broj 5 na adresu na koju pokazuje x, a to je adresa varijable y, isto kao kada napiemo y=5;. Zbog toga ispis *x i ispis y ispisuju istu vrijednost. Nakon ovog podueg uvoda moemo prijei na temu, a to je prijenos podataka u funkciju po adresi. Ranije smo rekli kako svaka funkcija i glavni program imaju svoje interne varijable kojima samo one mogu pristupati. Ponekad je meutim potrebno da neka funkcija mijenja lokalnu varijablu glavnog programa ili druge funkcije. To moemo ostvariti tako to emo u pozivu funkciji umjesto vrijednosti proslijediti adresu varijable. Tada funkcija moe promijeniti sadraj na toj adresi, a time i lokalnu varijablu npr. glavnog programa: #include void kvadrat(int *x) {*x=*x * *x;} main() {int y=5; kvadrat(&y); cout

  • Rekurzije 25

    Rekurzije Do sada smo vidjeli kako glavni program ili druga funkcija moe pozvati neku funkciju. Meutim funkcija moe pozvati i samu sebe. To zovemo rekurzija. Pogledajmo primjer: #include void proba(int i) {i++;cout

  • Rekurzije 26

    dolazi na kraj funkcije i skida se prva adresa (yyyy) i podatak (4) sa stoga (isto kao kada bi izvrili i=4). Adresa yyyy je unutar funkcije neposredno nakon mjesta gdje se u funkciji ona sama poziva. Prva instrukcija nakon toga je cout

  • Rekurzije 27

    Tada, kada je i postao 1, instrukcija iza if se ne izvrava ve se ide na return(f). Koliki je f u tom trenutku? Naravno 1 jer je toliko i postavljeno na poetku funkcije, a rekli smo kako se izraz f=fakt(i-1)*i jo nije ni jednput izraunao nego se unutar izraza samo izvravao dio ...fakt(i-1)... Meutim kada se prvi puta izvri return(f) skida se sa stoga vrijednost i (ona je 2, tj. zadnja ostavljena) i skida se adresa povratka. Adresa je usred izraza pa se tamo kontrola izvrenja prebacuje i sada se moe izraz izraunati do kraja. Budui da se vraa 1 (vrijednost f) ta jedinica u izrazu praktino zamjenjuje ime funkcije pa sada moemo izraz zamisliti ovako: f= 1 * i Kako je i=2 (skinuto sa stoga) pa je f =1*2. Slijedei red je opet return(f), i sada se sa stoga skida slijedea vrijednost za i, a to je 3. Ponovo se vraamo usred izraza i sada ga moemo zamisliti: f=2 * i tj. f e postati 6. Dakle slijedea povratna vrijednost f je 6, a sa stoga se skida 4, a izraz sada izgleda: f=6 * i tj. f=6*4 znai sada je f=24 ta vrijednost se vraa s return(f) usred izraza pa on izgleda: f=24*5 (5 je slijedei i koji je skinut sa stoga) i vrijednost f je 120. I na kraju sa stoga se skida zadnja povratna adresa (kada return(f) vraa 120), a ta adresa je prva stavljena tj. adresa u glavnom programu i to na mjestu ispisa: cout

  • Rekurzije 28

    I sada se sa stoga skine f=1 ali mu se onda dodijeli povratna vrijednost pa f postaje onoliko koliko funkcija vraa. Ako dodamo prvom primjeru ispis moemo pratiti izvrenje rekurzije: #include long fakt(int i) {long f=1; cout

  • Rekurzije 29

    Na kraju treba obratiti pozornost kako funkcija bakt vraa vrijednost i u glavni program ali je mi tu ne koristimo, to je doputeno, a u naem sluaju i korisno jer se ispis obavlja u funkciji, pa bi ispis u glavnom programu samo ponovo ispisao zadnju izraunatu vrijednost. 22. Zadatak: napiite rekurzivnu funkciju za pretvaranje desetinog broja u

    binarni. Desetini broj se pretvara u binarni tako da ga cjelobrojno dijelimo sa dva i zapisujemo ostatke, dijeljenje prekidamo kada doemo do nule. Ostatke proitamo u obrnutom redoslijedu. Kada se spomene u obrnutom redoslijedu treba pomisliti na rekurziju - skidanje sa stoga ide u obrnutom redoslijedu od punjenja. Ideja programa je: broj cjelobrojno dijelimo sa 2 i rezultate ostavljamo na stogu dok ne doemo do nule. Tada, u fazi povratka, izraunavamo i ispisujemo ostatke pri dijeljenju sa dva, koristei se rezultatima skinutim sa stoga. Pogledajmo program: #include void binar(int d) {if (d>0) binar(d/2); cout

  • Rekurzije 30

    Prvo: kako smo izbjegli ispis vodee nule? Postavili smo uvjet koji u opem sluaju glasi: if (d>najvee_znamenke_sustava). Za binarni bi to bilo if (d>1). Ostali dio programa je gotovo isti kao u sluaju binarnog pretvaranja, samo to dijelimo s bazom sustava, a to je 8. Iz glavnog programa koristimo petlju kako bi funkciju pozvali odgovarajui broj puta. Moemo li slian princip koristiti i za heksadekadske brojeve? 24. Zadatak: napiite program koji pretvara prva 32 prirodna desetina broja u

    heksadekadske. Znamo kako se za heksadekadske znamenke rabe slova od A do F. Zato moramo koristiti slovni tip char. Za sada ne kao tip varijable nego samo kao tip ispisa. Brojane vrijednosti vee od 9 moramo pretvoriti u slova. To emo napraviti izrazom: (char)(n-10+'A') pri emu je n broj izmeu 10 i 15. Ako je n=10 izraz n-10 daje 0 i to plus A daje slovo A. Za n=11 izraz n-10 daje 1 pa je 1+A prvo slovo poslije A tj B. Ovdje koristimo openito svojstvo raunala da slova u memoriji zapisuju u obliku brojanog koda (ASCII) pri emu npr. slovo A ima kod 65, B 66 itd. Drugo, koristimo lakou s kojom C++ pretvara iz jednog tipa varijable u drugi. Zapravo ako je n=12 izraz: n-10+A se rauna u obliku: 12-10+65 pa je rezultat 67 i ako traimo ispis u slovnom obliku (char) ispisu je se slovo koje ima taj kod tj. C. Konano pogledajmo program koji ispisuje 32 heksadekadska broja: #include void hexa(int d) {int n; if (d>15) hexa(d/16); n=d%16; if (n

  • Rekurzije 31

    if (n>0) p=pot(a,n-1)*a; return p;} main() {int x,y; coutx; couty; cout

  • Rekurzije 32

    cout

  • Rekurzije 33

    Sada jo samo to treba napisati kao rekurziju: #include long binom(int n,int k) {long b=1; if (k>0 && k

  • Polja 34

    Polja Polje je niz varijabli istog imena koja se razlikuju po indeksu. Deklariramo ih npr: int a[100]; Ovom deklaracijom stvorili smo u memoriji sto varijabli i to: a[0], a[1], a[2], a[3], ... , a[99]. Brojevi u uglatim zagradama su indeksi koji zapravo odreuju pojedinanu varijablu u polju. Viestruka je prednost ovakvih varijabli: prvo u samoj deklaraciji, zamislite kako bi deklarirali sto ili tisuu varijabli klasinim nainom, drugo, ovom nizu varijabli je lako pristupiti for petljom. Pogledajmo to na slijedeem primjeru: 28. Zadatak: napiite program koji 5 unesenih brojeva ispisuje u obrnutom

    redoslijedu. #include main() {int a[5],i; cout

  • Polja 35

    for (i=0;i

  • Polja 36

    Ovo me podsjea na jednu od estih pogreaka kod poetnika, naime javlja se pomisao kako polje moemo ispisati kao i svaku drugu varijablu s cout

  • Polja 37

    podatke, na ovaj nain je to mogue jer se preko adrese zapravo cijelo vrijeme radi s istim globalnim poljem. Koristimo prethodni program uz odgovarajue izmjene koje su naznaene tamnijim slovima: #include #include int a[50],b[50]; void unos() {randomize(); for (int i=0;i

  • Polja 38

    Prva for petlja unosi u sve regularne lanove niza nule, a druga ispisuje, ali 20 lanova. Prvih deset se ispisuju normalno tj nule, a ostalih 10 ovisi o trenutnom stanju u memoriji vaeg raunala. Greke ovog tipa obino nisu ovako uoljive kao u naem primjeru, a najee nastaju kao posljedica loe postavljenog uvjeta u petlji. 30. Zadatak: napiite program koji uneseni niz prirodnih brojeva razvrstava u

    dva polja i to tako da u prvi stavi sve parne, a u drugi neparne brojeve. Prirodni brojevi su cijeli brojevi vei od nule. Parni brojevi su oni koji pri dijeljenju s 2 imaju ostatak 0. Trebaju nam tri polja: za unos, neka bude u, niz parnih p i neparnih n. Sva tri polja neka budu iste duine jer ne znamo unaprijed koliko e biti parnih, a koliko neparnih. Ako polja p i n prvo napunimo nulama moemo identificirati kraj ispisa kada doemo do podatka 0 (ili do kraja niza). Do sada nismo koristili konstante, meutim budui da imamo tri niza iste duine i petlje koje broje do iste duine uveemo konstantu za duinu. Konstante je zgodno definirati na poetku programa, pogotovo ako elimo mijenjati npr. duine polja jer na taj nain na jednom mjestu moemo promijeniti i veliine polja i do koliko for petlje broje. Konstante ne moemo, naravno, mijenjati za vrijeme izvrenja programa. #include #include const d=10; int u[d],p[d],n[d]; void unos() {randomize(); for (int i=0;i

  • Polja 39

    Obratite pozornost da se prvo izvri dodjela iz polja u u polje p pa tek onda poveanje varijable a (isto je i u slijedeem paru). Inae varijable a i b u funkciji razvrstraj imaju ulogu pokazivati dokle je doao unos u poljima parnih odnosno neparnih. Zato se one poveavaju za svaku novu dodjelu u parno ili neparno polje. - U for petlji funkcije ispis koristimo malo sloeniji logiki izraz, petlja broji dok je ispunjen uvjet da je i

  • Polja 40

    x=y ? a : b Ako y nije nula onda se x-u dodijeljuje prva vrijednost (a), a ako je y jednak 0 onda druga vrijednost (ona iza dvotoke tj. b). U naem sluaju ako bp nije nula dodijeljuje se vrijednost izraza iza upitnika inae (ako je bp=0) dodijeljuje se druga vrijednost tj. nula. Isto bi bilo da smo napisali: if (bp!=0) *p=(float)sp/bp; else *p=0; ili krae if (bp) *p=(float)sp/bp; else *p=0; ili jo krae onako kako smo napisali u programu! 32. Zadatak: napiite program koji ispisuje Pascalov trokut. Zadatak s ispisom Pascalovog trokuta smo ve radilikoristei se izrainavanjem binomnog koeficijenta po formuli:

    kn

    =)!(!

    !knk

    n meutim Pascalov trokut se moe i jednostavnije rijeiti.

    Potsjetimo se kako je svaki lan jednak zbroju lanova lijevo i desno od njega u prethodnom redu ili ako trokut piemo s poravnatom lijevom stranom: k

    1, 1 1, 2, 1 1, 3, 3, 1 1, 4, 6, 4, 1

    n ... svaki k lan u n redu jednak je zbroju k-tog i (k-1) lana iz prethodnog reda, tj. iz reda n-1. U programu koristimo dva polja, jedno je prethodno (a) i drugo je ono koje upravo generiramo (b). U (a) nizu postavljamo prvog i zadnjeg lana na nulu. Petlja for(i...) broji redove trokuta, zatim postavljamo prvog izadnjeg iz (b) niza na jedan (pogledajte trokut, u svakom redu prvi i zadnji lan je jedan). U for(j...) petlji lan (b) niza postaje zbroj lanova iz (a) niza i to istobrojnog i prethodnog: b[j]=a[j-1]+a[j]; Petlja for(k...) ispisuje lanove (b) niza na ekran i prepisuje (b) niz u (a) niz. Na taj nain se pripremamo za generiranje slijedeeg reda tj. lanovi (b) niza postaju prethodni red (prebacivanjem u a-polje). #include const d=20; long a[d],b[d] ; void trokut(int n) {int i, j,k; a[0]=a[1]=1; for (i=0;i

  • Polja 41

    main() {int p; coutp; trokut(p); } Prednost ovakvog naina je u tome to ne moramo raditi s velikim brojevima kao kod faktorijela, nego se sve rjeava obinom zbrajanjem. Posebna vrsta polja su polja slova. Polje ili niz slova obino zovemo string. U principu ta polja su ista kao i polja brojeva uz dvije razlike: kraj polja je oznaen s oznakom /0 (odnosno u memoriji praktino nulom). Druga razlika je to polje moemo unijeti jednom naredbom: cin>>a; pri emu je (a) polje slova, dok to kod polja brojeva nije mogue. Isto tako polje slova moemo i ispisati jednom naredbom: couta; cout

  • Polja 42

    for (j=i-1;j>=0;j--)cout

  • Polja 43

    Moda ste ve primjetili kako cin>>a unosi samo jednu rije, naime unos se prekida na razmaku pa ako upiete reenicu samo prva rije e biti prihvaena u varijablu (a) dok e ostatak reenice biti izgubljen. Svrha takvog unosa je upis vie vrijednost varijabli s razmakom izmeu umjesto entera. Na primjer: #include main() {int a,b,c; cin>>a>>b>>c; cout

  • Polja 44

    {while (*s) {if (*s>='A' && *s

  • Polja 45

    Pogledajmo slian primjer u slijedeem zadatku: 37. Zadatak: napiite program za ifriranje teksta. Naravno, postoji cijeli niz naina ifriranja, ali za poetak pogledajmo najjednostavniji primjer. Svako slovo iz teksta koji se unosi (kod slova) poveajmo za 1, tako e npr. slovo A postati B itd. Moemo se posluiti prethodnim programom za prepisivanje niza slova u drugo polje. #include void sifriraj(char *a, char *b) {while (*b=*a){++*b;b++;a++;}} main() {char x[50],y[50]; cin.getline(x,50); sifriraj(x,y);cout

  • Polja 46

    For petlja broji od kraja prema poetku smanjujui broja (i) za 2 jer uz slovo dodajemo i razmak. U izrazu r[i]=r[d] indeks (i) pokazuje na novo mjesto, a (d) na staro mjesto slova. 39. Zadatak: napiite program za konkatanaciju (spajanje) stringova. #include main(){ char r1[50],r2[50];int d=0,i=0; cin>>r1; cin>>r2; while(r1[d]!=0) d++; // nadji prvu duzinu while(r2[i]!=0){r1[d]=r2[i];i++;d++; }// na to dodaj drugi string r1[d]=0; cout

  • Polja 47

    strrev(s); cout

  • Operacije s bitovima 48

    Operacije s bitovima Svi podaci su u memoriji raunala zapisani u binarnom obliku, dakle kao binarni brojevi. Zbog toga su operacije s bitovima operacije niskog nivoa pa se prema tome brzo izvravaju. Imamo 4 logike operacije s bitovima i dvije operacije pomaka bita. Operator Znaenje Primjer Objanjenje & AND (i) 101

    &110 100

    Rezultat je 1 samo ako su obadva bita 1.

    | OR (ili) 101 | 110 111

    Rezultat je 1 ako je ili jedan ili drugi bit operana 1.

    ^ XOR(iskljuivo ili) 101 ^110 011

    Rezultat je 1 samo na mjestima gdje su bitovi razliiti.

    ~ NOT (ne) ~101=010 Svi bitovi se postavljaju na suprotno (to je bilo jedan to je nula i obrnuto).

    >3=1 Isto kao gore, ali udesno.

    6. tablica: pregled operatora s bitovima Pogledajmo to na primjeru: 41. Zadatak: napiite program koji pretvara uneseni broj u binarni. Uzmimo da se unosi broj tipa int. On u memoriji zauzima 32 bita (2 bayta). Napisat emo funkciju koja provjerava je li neki bit broja 1 ili 0, a zatim tu funkciju pozvati 32 puta koristei se for petljom. #include int jelibit(int b,int pos) {return (b & (1a; for (i=15;i>=0;i--) cout

  • Operacije s bitovima 49

    Operator ?: daje kao rezultat ono to je prije dvotoke ako je vrijednost prije upitnika vea od nule, a ako je vrijednos prije upitnika nula, rezultat je vrijednost iza dvotoke. U naem sluaju ako je rezultat izraza b & (1pos))?1:0;} char postavibit(char bit,int pos){return (bit | (128>>pos));} void izbaci (long n) {for(long i=n*2;i

  • Sortiranje 50

    Sortiranje Sortiranje je ureivanje nekog niza podataka po odreenom kriteriju. Moemo sortirati brojane podatke po veliini (od manjih ka veim i obrnuto), slovne podatke po abecedi ili suprotno, datumske podatke itd. Najjednostavniji nain sortiranja (ujedno i najsporiji) je slijedei: Dvostrukom petljom (npr. (for i) i (for j) prolazimo kroz niz (polje) podataka. Vanjska petlja ide od prvoga do predzadnjega, a unutarnja od vanjske+1 do zadnjega. Usporeujemo podatak na koji pokazuje vanjska petlja s onima na koji pokazuje unutarnja. Ako je prvi vei zamjenjujemo ih. Na primjer neka je n duina polja a[n]: for (i=0;i2 vri se zamjena. Sada je 2 na prvom mjestu, j petlja prolazi do kraja ali nema vie zamjena. U drugom prolazu imamo dvije zamjene, prvo se zamjenjuju 7 i 5, (5 dolazi na drugo mjesto), a na kraju 5 i 3 koje dolazi na drugo mjesto dok 5 odlazi na njegovo tj. zadnje mjesto. U treem prolazu zamjenjuju se 7 i 5 tako da 5 dolazi na tree mjesto, i na kraju se zamjenjuju 8 i 7 ime je niz sortiran. Pogledajmo program: #include #include const n=10; int niz[n]; void unos() { int i;randomize(); for (i=0;i

  • Sortiranje 51

    } main() {unos(); ispis(); sort(); ispis(); } Kako ne bi morali sami unositi brojeve u niz sluimo se funkcijom za unos koja unosi niz sluajnih brojeva koristei funkciju random(10) koja generira sluajne brojeve do 10. Ona je definirana u biblioteci stdlib.h. Generator sluajnih brojeva iniciramo funkcijom randomize(), izbjegavajui na taj nain da uvijek dobijemo iste brojeve. Obratite pozornost i na nain zamjene: p=niz[i];niz[i]=niz[j];niz[j]=p; Prvu vrijednost (niz[i]) stavimo u pomonu varijablu p, zatim u niz[i] stavimo niz[j], a onda iz pomone varijable u niz[j]. Kada bi direktno napisali niz[i]=niz[j]; ranija vrijednost iz niz[i] bila bi izgubljena i obje varijable bi sadravale istu vrijednost. Nedostatak ovog naina sortiranja je to se, bez obzira na poetni poredak, ove dvije for petlje uvijek izvre isti broj puta, ak i ako je na poetku niz ve sortiran. Drugi nain sortiranja poznat je pod nazivom bubble sort (bubble - eng. mjehurii). Ideja je provjeravati svaka dva lana niza, pa ako je prvi vei od drugoga, zamijeniti ih. Izvrenje zamjene registrira se u posebnu varijablu, ako u prolazu nije dolo do zamjene znai da je niz sortiran pa se petlja prekida. prvi prolaz drugi prolaz trei prolaz etvrti prolaz 7 2 2 2 2 2 2 2 2 2 2 7 5 5 5 5 5 5 5 3 5 5 7 7 7 7 7 3 3 5 8 8 8 8 3 3 3 7 7 7 3 3 3 3 8 8 8 8 8 8 Obratite pozornost kako vei brojevi padaju na dno, a manji isplivavaju kao mjehurii. Brojevi u sivim poljima se usporeuju i ako je potrebno zamjenjuju. Nakon prvog prolaza sigurni smo da je najvei broj na dnu, pa u drugom prolazu idemo do predzadnjeg, u treem do pred-predzadnjeg itd. #include #include const n=10; int niz[n]; void unos() { int i;randomize(); for (i=0;i

  • Sortiranje 52

    {p=niz[j];niz[j]=niz[j+1];niz[j+1]=p;z=1;}} } main() {unos(); ispis(); sort(); ispis(); } Funkciju za sortiranje moemo napisati i koritenjem while petlje: void sort() {int i=n-1,j,p,z=1; while (i>0 && z) {z=0; for (j=0;jniz[j+1]) {p=niz[j];niz[j]=niz[j+1];niz[j+1]=p;z=1;} i--;} } Petlja (for j) broji od poetka niza do element[nutarnja] zamijeni ih.

    Zamjena: pomoni=prvi; prvi=drugi; drugi=pomoni;

    14 u logikim uvjetima 0 znai ne tono, a 1 ili openito bilo to razliito od 0 - tono.

  • Martice 53

    Martice Do sada smo radili s jednodimenzionalnim poljima, meutim polja mogu biti i viedimenzionalna. Najee koristimo s dvodimenzionalna polja, a deklariramo ih na slijedei nain: int a[10][5]; Ovako definirano polje, ili da upotrijebimo izraz matrica, ima 10 redova, sa pet lanova u svakom redu ili to moemo zamisliti kao 10 polja od po 5 elemenata. Pogledajmo primjer: #include main() {int a[10][5],i, j; for (i=0;i

  • Martice 54

    cout

  • Martice 55

    U unosu se koristimo sluajnim brojevima kako ne bi gubili vrijeme na unos. Zatim slijedi ispis koji je isti kao i u prethodnom zadatku. I na kraju funkcija koja izraunava sumu na glavnoj dijagonali. Ona zapravo zbraja s=mat[0][0]+mat[1][1]+ ...+ mat[5][5] Kako bi izgledala funkcija koja zbraja lanove na pomonoj dijagonali matrice? Posluit emo se istom tablicom s indeksima, a oznait emo pomonu dijagonalu: 0,0 0,1 0,2 1,0 1,1 1,2 2,0 2,1 2,2 Prvi indeks (nazovimo ga i-indeks, prema tome kako smo do sada postavljali vanjsku petlju) mijenja se 0,1,2. Drugi, j-indeks mijenja se 2,1,0. Znai: kada je i=0 j treba biti 2, ako to napiemo u obliku: j=x-i odnosno 2=x-0 Koliko treba biti x? Naravno 2. Zato izraz za izraunavanje j-indeksa moemo pisati: j=2-i Odnosno u opem sluaju j=(visina_matrice-1)-i . Na primjer ako je visina matrice 6 kao u prolom zadatku onda je j=(6-1)-i tj. [n-1-i] int pomocnad() { int i,s=0; for (i=0;i

  • Martice 56

    mat[0][j]=mat[0][n-1-j]; mat[0][n-1-j]=p; a zatim tu vrijednost stavimo u drugu varijablu (desni element matrice). U primjeru smo kao prvi indeks koristili nulu, jer smo razmiljali samo o prvom redu, dok u programu na tom mjestu koristimo broja (i) iz vanjske for petlje. #include #include #include const n=6; int mat[n][n]; void unos() { int i,j; randomize(); for (i=0;i

  • Martice 57

    U nekoliko zadnjih zadataka koristimo stalno iste funkcije za unos sluajnih brojeva u matricu i za ispis matrice. Ako hoemo smanjiti posao oko pisanja istih funkcija u svakom novom programu moemo ove dvije funkcije spremiti u posebnu datoteku zaglavlja (header) pa ju s #include ukluivati u nove programe koje piemo. Predprocesorska direktiva #include jednostavno doda na poetak naeg programa ono to se nalazi u datoteci koju ukluujemo. Slino kao kada bi sami, s copy i paste dodali tekst iz druge datoteke na poetak programa. Izvojimo sve to nam se stalno ponavlja, u vjebama s matricama, i to snimimo pod imenom iomat.h (input output matrica). Ime header datoteke je proizvoljno, kao i ime programa, a natavak h je od rijei header - zaglavlje. Kako bi mogli unositi i ispisivati razliite matrice koristimo se pokazivakom (adresnom) varijablom *p kao argumentom funkcije (prijenos argumenta po adresi - call by reference). U pozivanju tih funkcija poslat emo im adresu prvog elementa matrice i irinu matrice, npr: unos(&mat[0][0], n). Funkcije e jednostavno poveavajui tu adresu s p++ pristupati svim elementima matrice. Datoteka iomat.h: #include #include #include void unos(int *p,int n) { for (int i=0;i

  • Martice 58

    {const d=6;randomize(); int mat[d][d],sk; unos(&mat[0][0],d);ispis(&mat[0][0],d); coutsk; mnozi(&mat[0][0],d,sk); ispis(&mat[0][0],d); cout

  • Martice 59

    Produkt matrica (m1) i (m2) se rauna: -prvi element rezultirajue matrice je suma umnoaka elemenata prvog reda matrice (m1) s elementima prvog stupca matrice (m2). m[0][0]=m1[0][0]*m2[0][0]+ m1[0][1]*m2[1][0]+...+ m1[0][n]*m2[n][0] -drugi element rezultirajue matrice je suma umnoaka elemenata prvog reda matrice (m1) s elementima drugog stupca matrice (m2). m[0][1]=m1[0][0]*m2[0][1]+ m1[0][1]*m2[1][1]+...+ m1[0][n]*m2[n][1] Ovo izgleda strano komplicirano ali zapravo nije, pogledajmo na crteu: Prvi red puta prvi stupac i sve se stavi u 0,0 rezultirajue martice. 0,0 0,1 0,2 0,0 0,1 0,2 0,0 0,1 0,2 1,0 1,1 1,2 1,0 1,1 1,2 1,0 1,1 1,2 2,0 2,1 2,2 2,0 2,1 2,2 2,0 2,1 2,2 Prvi red puta drugi stupac i sve se stavi u 0,1 rezultirajue martice. 0,0 0,1 0,2 0,0 0,1 0,2 0,0 0,1 0,2 1,0 1,1 1,2 1,0 1,1 1,2 1,0 1,1 1,2 2,0 2,1 2,2 2,0 2,1 2,2 2,0 2,1 2,2 itd. Trebaju nam, klasino, dvije for petlje za indekse matrice i jo jedna koja e proi kroz pojedine elemente stupca i reda za izraun sume umnoaka: for (i=0;i

  • Martice 60

    Polja matrica smo deklarirali globalno tako da pojednostavimo stvari, jer bi inae morali dodatno komplicirati s prijenosom polja iz glavnog programa u funkciju produkt. 50. Zadatak: napiite program za transponiranje matrice. Opet jedan kompliciran zadatak! Zapravo, upe nije: u transponiranoj matrici su redovi ono to su stupci u izvornoj. Ovaj problem moemo rijeiti na vie naina. Na primjer moemo nakon unosa jednostavno ispisati matricu s time da zamijenimo mjesta indeksima (i) i (j). Ako ipak elimo da i transponirana matrica bude u memoriji moemo se koristiti s dvije matrice - izvornom i transpniranom. Redove izvorne matrice jednostavno prepiemo u stupce transponirane. #include "iomat.h" const n=3; int m1[n][n],m2[n][n]; void transponiraj() {for(int i=0;i

  • Martice 61

    Deklariramo tri pokazivaa, n1 i n2 koji pokazuju na matrice m1 i m2, i jedan pomoni pokaziva p. Sve dalje u programu radimo s tim pokazivaima. Kada im zamijenimo adrese koje sadre, praktino kao da smo zamijenili mjesta matricama. Naravno, fiziki, matrice ostaju na svojim mjestima. Ovo moe biti osobito korisno kod velikih matrica. Zamislite zamjenu dviju slika veliine 600x400. For petlja koja bi vrila takvu zamjenu morala bi se izveiti 240000 puta, dok se zamjena preko adresa izvri trenutno (i ne ovisi o veliini matrica). 52. Zadatak: napiite program koji ispisuje kvadratnu matricu zarotiranu za 450 izvorna: zarotirana: 1 2 3 1 4 5 6 4 2 7 8 9 7 5 3

    8 6 9

    Napiimo indekse zarotirane matrice: Sada pogledajmo gornju polovicu trokuta i prve indekse: 0 1 0 2 1 0 Oni opadaju do nule, ali tako da je poetak prvo 0, zatim 1, pa 2. Znai postoji vanjska for petlja koja broji 0,1,2 i unutarnja koja

    broji od vanjske petlje unazad do 0. for (i=0;i=0;j--) (j) broja daje prvi indeks. to je s drugim? On je suprotan od prvog, tj raste dok prvi opada, pa je (i-j). U donjem dijelu trokuta unutarnja petlja opet broji unazad ali od 2 do koliko je vanjska nabrojala. Vanjska, koja sada regulira, ne vie poetak, nego kraj unutarnje broji od 1 do 2. Prvi indeks je opet (j), a drugi (3-j+i) ili u opem sluaju (n-j+i). #include const n=3; int m[n][n]; void napuni(int *a) {for (int i=1;i

  • Martice 62

    Obratite pozornost kako u funkciju napuni aljemo matricu preko adrese, jer bi inae u funkciji morali koristiti dvostruku petlju za pristup preko indeksa polja. Suprotna je situacija kod funkcije rotiraj gdje nam je jednostavnije raditi s indeksima. Saetak: Matrica je viedimenzionalno polje. Najea je dvodimenzionalna matrica. To je polje polja ili niz nizova. Matrica deklarirana npr. int x[2][5].

    moemo zamisliti ovako: { { 0, 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 } } - dva reda od po pet elemenata.

    Kada je matricu potrebno prenijeti u funkciju najee aljemo kao argument samo adresu prvog elementa matrice i u funkciji radimo s adresama.

  • Strukture 63

    Strukture Struktura je skup podataka (razliitog tipa) koji ima zajedniko ime. Ona je zapravo novi tip podataka koje moemo sami definirati, a onda ih koristiti za deklariranje varijabli kao i ostale tipove. Opi oblik definicije je: struct [] { [tip_varijable ime_varijable] ; ... } [varijabla_strukture] ; Uglate zagrade u ovom sluaju znae da moemo, ali i ne moramo koristiti odreenu komponentu deklaracije. Na primjer definiramo tip varijable toka: struct tocka { int x,y;} Nakon ove definicije moemo deklarirati novi tip varijable: tocka a,b; Sada smo deklarirali dvije toke (a i b), a njihovim komponentama pristupamo na slijedei nain: a.x=5; a.y=7; Varijable strukture moemo deklarirati i odmah u definiciji strukture: struct tocka { int x,y;} a,b; Ili ako neemo kasnije deklarirati nove varijable tog tipa moemo izbaciti ime tipa strukture: struct { int x,y;} a,b; 53. Zadatak: napiite program koji izraunava udaljenost izmeu dvije toke. Udaljenost dvije toke se rauna: 22 )1()1( yyxxd += Za korijen koristimo funkciju sqrt(varijabla), a za potenciju, u ovom sluaju na kvadrat, funkciju pow(varijabla, potencija). Obje funkcije su definirane u math.h i naravno umjesto varijable moemo koristiti izraz ili drugu funkciju. #include #include main() {struct{int x,y;}a,b; couta.x; couta.y; coutb.x; coutb.y;

  • Strukture 64

    cout

  • Strukture 65

    Naravno, ovakav program ne radi nita korisno, ali nam moe posluiti kao temelj za razvoj cijelog niza programa zasnovanih na poljima struktura. 55. Zadatak: napiite program za kreiranje koarkake momadi. Uvjet ulaska u

    momad je prosjek vei od 3. Unose se slijedei podaci: ime, prosjek i vrsta sporta kojim se bavi: k-koarka, n-nogomet, r-rukomet itd.

    Jedan od problema u ovom zadatku je koliko studenata se unosi. Naravno, to moemo rjeiti tako to emo prije unosa podataka upisati potreban broj: coutn; Nakon toga unos vrimo u for petlji: for (int i=0;i> student od i ... itd. Drugi nain bi bio da postavimo uvjet prekida unosa kada se umjesto imena upie rije kraj. U tom sluaju moramo upotrijebiti funkciju za komparaciju stringova: strcmp(prvi_string , drugi_string). Podsjetimo se kako su stringovi zapravo polja slova, a polja ne moemo direktno komparirati. Na primjer, ne moemo pisati: if (polje1==polje2) ... Funkcija strcmp18(prvi_string , drugi_string) daje slijedee vrijednosti: 0 ako je prvi_string jednak drugom_stringu 1 ako je prvi_string vei od drugog_stringa -1 ako je prvi_string manji od drugog_stringa Ako napravimo ovakav izraz: strcmp(unos,kraj) rezultat e biti 0 ako varijabla unos sadri rije kraj. Znamo da nula u logikim izrazima ima znaenje netono, pa zbog toga moramo pisati: if (!strcmp(unos,"kraj")) break; Operator not (!) pretvara dobijenu nulu u jedinicu, pa se u sluaju jednakosti izvrava instrukcija break. Uloga instrukcije break je prekid izvoenja while, do i for petlji, ili switch instrukcije odluke. U naem sluaju to je while petlja unosa. #include #include struct {char ime[15]; char sp; float pr;}s[50]; int n; void unos() {while(n

  • Strukture 66

    cout

  • Strukture 67

    ispis();} 57. Zadatak: u program se unose imena autora i naziv djela. Napiite program

    koji sortira ispis po autoru ili po djelu, to se bira iz izbornika. U ovom zadatku imamo primjer sortiranja po abecedi tj. sortiranje stringova. Ve smo ranije rekli kako stringove poredimo funkcijom strcmp(s1,s2). Ako je s1>s2 rezultat je vei od nule, ako su isti - jednak nuli i ako je s1

  • Strukture 68

    a inae (else) uzima se b[i].d (po djelu). if (k==1) {if (strcmp(b[i].a,b[j].a)>0) zamijeni(i, j);} else if (strcmp(b[i].d,b[j].d)>0) zamijeni(i, j); Kako se else ne bi vezao uz najblii if (nego uz onaj prethodni) cijela konstrukcija tog if-a je stavljena u programski blok tj. u vitiaste zagrade. Zamjena je napisana u posebnoj funkciji, ime se program skrauje i ne moramo dva puta pisati isto za zamjenu elemenata u polju struktura.

    Funkcije u strukturi, konstruktori i destruktori Do sada smo koristili strukture koje sadre samo varijable, meutim one mogu sadravati i funkcije. Poseban tip funkcije u strukturi su funkcija konstruktor i funkcija destruktor. Funkcija konstruktor ima isto ime kao struktura i aktivira se u trenutku svake deklaracije varijable tipa struktura. Funkcija destruktor ima isto ime kao konstruktor, dakle i kao struktura s tim da ispred imena ima znak ~. Ona se aktivira u trenutku brisanja strukture iz memorije, tj. na kraju programskog bloka u kojem je strukturna varijabla deklarirana. Obino je to na kraju programa ili funkcije, na zadnjoj zatvorenoj vitiastoj zagradi }. Pogledajmo primjer: #include struct student{ int i; void proba(){cout

  • Strukture 69

    Saetak: Struktura je objekt koji je deklariran kao novi tip varijable. Ona moe sadravati deklaracije vie razliitih varijabli. Opi oblik deklaracije strukture je: struct [] { [tip_var ime_varijable];... } [varijabla_strukture] ; npr.: struct {int x,y;} a; (ime strukture nije obavezno ako odmah deklariramo varijablu strukture) Tako deklariranim varijablama pristupamo: a.x =7; Moemo deklarirati polje (niz) struktura. struct {int x,y;} a[10]; Pojedinim elementima pristupamo: a[2].x =132; U strukturi moe biti funkcija: struct {int x,y; void f(){...}} a; Takvu fukciju pozivamo s : a.f(); Posebne funkcije u strukturi su konstruktor i destruktor. One imaju isto ime kao i sruktura, a destruktor ispred imena ima znak ~. Konstruktor s pokree u trenutku deklaracije varijable tipa struktura, a destruktor

    u trenutku naputanja programskog bloka u kojem je deklarirana varijabla strukture (npr. kraj programa}.

  • Dinamike strukture podataka 70

    Dinamike strukture podataka Pokazivae smo ve koristili u ranijim programima, ali sada emo se poblie upoznati s mogunostima njihovog koritenja u kreiranju dinamikih struktura podataka. Meutim, prvo da se podsjetimo to je zapravo pokaziva. Najjednostavnije reeno pokaziva je varijabla tipa adresa. Kao to je int cjelobrojna varijabla i u sebi sadri cijele brojeve, char slovna varijabla koja sadri slovo, tako je pokaziva varijabla koja u sebi sadri adresu. Naravno, adresa sama po sebi nema mnogo smisla, nama obino treba adresa nekog podatka iz memorije. Sadravajui adresu nekog mjesta u memoriji (adrese), ova varijabla kao da pokazuje na to mjesto tj. podatak upisan na tu adresu. Zato takve adresne varijable zovemo pokazivai. Podaci u memoriji mogu biti zapisani kao cijeli brojevi, racionalni brojevi, slova itd. Svi ti tipovi varijabli zauzimaju razliite duine i brojevi u njima se interpretiraju na razliite naine. Na primjer ako u varijablu tipa int stavimo broj 65 on e zauzeti dva bajta u memoriji i niterpretirat e se kao 65 (npr. u ispisu). Ali ako u varijablu tipa char stavimo slovo A ono e se u memoriji zapisati u jedan bajt i to kao broj 65 (ASCII kod). Prilikom ispisa te varijable vrijednost 65 iz memorije ispisuje se kao slovo A. Vidimo kako se iste vrijednosti mogu interpretirati na razliite naine i zato je potrebno da raunalo zna kojem tipu varijable pripada memoriski podatak. Zato u deklaraciji pokazivaa moramo navesti tip varijable na koji on pokazuje. Osim pravilne interpretacije podataka iz memorije, postoji i drugi razlog za navoenje tipa varijable kod pokazivaa, a to je aritmetika pokazivaa. Ako vrijednost nekog pokazivaa poveamo za jedan, adresa koju on sadri nee se poveati za jedan bajt nego za onoliko bajta koliko je dugaak odreeni tip varijable. Pogledajmo to na primjeru: #include main() {int *p; p=0; cout

  • Dinamike strukture podataka 71

    Uoite kako je samo c pokaziva na tip int, dok je b pokaziva na pokaziva. Prema tome a je pokaziva na pokaziva na pokaziva. Ovo se zove viestruka indirekcija. Pogledajmo sada program koji to ilustrira: #include main() {int ***a, **b, *c,p; p=13; c=&p; b=&c; a=&b; cout

  • Dinamike strukture podataka 72

    (*n).a=t; t=n;} Budui da su dinamike strukture znaajne, a esto predstavljaju problem za razumijevanje, analizirat emo program red po red. Prvo definiramo strukturu koja u sebi sadri pokaziva na tu strukturu: struct proba{int p; proba *a;}*n,*t; Ovo se zove samoreferentna ili rekurzivna definicija. Varijabla p e sadravati podatak, a varijabla a adresu druge strukture. Deklariramo dvije varijable tipa struktura proba i to kao pokazivake varijable *n i *t (n - kao nova i t - kao tekua). n=new proba; Kao to smo ve rekli funkcija new rezervira mjesto u memoriji za strukturu proba, dodjelju je joj adresu i tu adresu stavljamo u adresnu varijablu n. Sada kada imamo adresu strukture u memoriji moemo pristupiti pojedinim elementima preko njene adrese tj. preko varijable n. (*n).p=1; U varijablu p (podatak) stavljamo neku vrijednost, u nae primjeru 1. Meutim potrebno je malo objasniti ovo sa zagradama. Operator toka ima vei prioritet od operatora zvjezdica, pa bi se bez zagrada izvrilo *(n.p)=1 to bi izazvalo greku jer je samo n zapravo adresa, a ona naravno nema nikakav element p (adresa npr. izgleda ovako 0x8f9b012320). Za razliku od toga *n je struktura, a ona, razumljivo, ima svoj element p. U slijedeem redu adresnoj varijabli u strukturi dodijeljujemo vrijednost konstante NULL. (*n).a=NULL; Rekli smo kako je to oznaka kojom se sluimo da oznaimo kako pokaziva ne pokazuje ninato. Kasnije, u prolasku kroz ovako kreirani niz podataka u memoriji to e nam sluiti kao oznaka kraja niza. t=n; Pokazivaka varijabla t preuzima adresu n. S ovim oslobaamo dunosti varijablu n da uva podatak o adresi prve strukture i u slijedeem redu dodjeljujemo joj adresu novonapravljene strukture: n=new proba; Dakle stara adresa je sauvana u t, a nova se nalazi u n. U podatkovni dio nove strukture stavljamo brojanu vrijednost: (*n).p=2;

    20 adrese se zapisuju kao heksadekadski brojevi.

  • Dinamike strukture podataka 73

    a u adresni dio, adresu prve strukture koju smo zato i sauvali u t: (*n).a=t; Na kraju, opet, adresu nove strukture prebacimo u t kako bi omoguili kreiranje slijedee nove strukture. Nakon svega situacija u memoriji je slijedea: n t

    p=2 a= p=1 a=NULL Vidimo u memoriji dvije strukture, a n i t pokazuju na zadnju stvorenu, pa je, prema tome jedan od njih slobodan za kreiranje slijedee itd. Ovakva dinamika struktura podataka naziva se stog21. Sa pojmom stoga susreli smo se kod funkcija i naroito rekurzija. Na stog e funkcionirati na istim principima kao i pravi stog u raunalu. Prvi podatak koji unesemo biti e na kraju niza, a zadnji e biti prvi koji moemo pokupiti (proitati ili skinuti) sa stoga. Proirimo na program tako da u for petlji stvorimo jo nekoliko elemenata, a zatim ih pokupimo sa naeg stoga i ispiemo. #include #include main() //stog {struct proba{int p; proba *a;}*n,*t; n=new proba; (*n).p=1; (*n).a=NULL; t=n; for (int i=2;i

  • Dinamike strukture podataka 74

    58. Zadatak: napiite program s funkcijama za dodavanje i skidanje elemenata sa stoga.

    Moemo se koristiti slinim nainom kao u prethodnom zadatku, samo to emo strukturu nazvati element. Tako program postaje itljiviji, jer kada piemo: n=new element; s time dodajemo novi element na stog. Za poetak postavimo n i t na NULL, pa ako se pozove funkcija dodaj, n e postati novi element, a njegov pokaziva e dobiti vrijednost t tj NULL. Meutim, ako se odmah na poetku pozove funkcija skini, if nee dopustiti skidanje sa stoga jer je n=NULL i samo e se ispisati stog je prazan. Nakon prvog dodavanja t pamti adresu strukture koja je dodana i u slijedeem dodavanju ta adresa se upisuje u pokaziva u strukturi a. #include #include struct element{int p; element *a;}*t,*n; void dodaj() {n=new element; (*n).a=t; cout(*n).p; t=n;} void skini() {if (n==NULL) cout

  • Dinamike strukture podataka 75

    Da nas ne zbunjuje, kada deklariramo funkciju s: element *dodaj(element *k) to nije adresa (ili pokaziva) funkcije, nego jednostavno znai da e funkcija vratiti adresu na podatak tipa element kada upotrijebimo return. U deklaracijama novog programa vie ne koristimo varijablu *t kao u prethodnom primjeru, ve umjesto nje u funkciji dodaj koristimo argument funkcije *k i lokalnu varijablu *r. Kod druge funkcije (skini) jo je jednostavnije: vraajui pokaziva na slijedei element s return (*k).a; varijabli n dodjeljujemo adresu slijedeeg elementa i tako se pomiemo kroz niz. #include #include struct element{int p; element *a;}; element *dodaj(element *k) {element *r; r=new element; (*r).a=k; cout(*r).p; return r;} element *skini(element *k) {if (k==NULL) {cout

  • Dinamike strukture podataka 76

    Grafiki, listu od tri elementa moemo prikazati ovako: g t n p=0 a= p=1 a= p=3 a=NULL Za poetak napiimo program koji kreira listu od deset elemenata: #include #include struct element{int p; element *a;}; main() {element *t,*n,*g; n=new element; (*n).a=NULL; (*n).p=0; g=t=n; for (int i=1;i

  • Dinamike strukture podataka 77

    Razlika od pravljenja prvog elementa je u tome to pokazivau u prethodnoj strukturi (t jo uvijek pokazuje na prethodnu strukturu) dodjeljujemo adresu novonapravljenog elementa n: (*t).a=n; i tek nakon toga t postaje n kako bi se pripremili za pravljenje slijedeeg elementa. Prije poetka ispisa n postavljamo na vrijednost g tj. na adresu na koju pokazuje glava, odnosno adresu poetka liste. Nakon ispisa podatka p n postavljamo na adresu na koju pokazuje pokaziva a, tj na slijedei element liste i tako napredujemo kroz listu sve dok na zadnjem elementu n postane NULL, nakon ega se while petlja prekida. 59. Zadatak: napiite program za rad s listom koji e imati slijedee mogunosti: a) dodavanje elemenata u listu b) kretanje kroz listu c) ubacivanje elemenata d) brisanje elemenata. e) ispis liste Ponimo od deklaracije: struct element{int p; element *a;}*t,*n,*g; Ona je ista kao u prethodnom primjeru, samo emo sve varijable pokazivae na strukturu deklarirati globalno zbog jednostavnosti. Podsjetimo se *t je tekui, *n je novi element, a *g e biti glava, tj. pokaziva na poetak liste. Prolazei kroz listu tekui pokaziva *t moe pokazivat na bilo koji element koji smo prethodno ubacivali ili ispisivali, zato je zgodno imati funkciju koja e postaviti tekui pokaziva na kraj liste: void na_kraj() { while((*t).a!=NULL) t=(*t).a;} While petlja ponavlja dok pokaziva od t ne postane NULL, to je znak kraja liste. Obratite pozornost kako se t pomijera kroz listu: on dobija vrijednost svog pokazivaa t = (*t).a; t slijedei u listi (*t).a (* ).a Budui da njegov pokaziva ima adresu slijedeeg u listi nakon izvrenja t = (*t).a; t postaje taj slijedei. Slijedea vana funkcija je dodavanje na kraj liste novog elementa: void dodaj() {na_kraj(); // postavi tekui na kraj liste n=new element; // napravi novi element (*n).a=NULL; // neka on pokazuje na NULL cout(*n).p; if (g==NULL) g=t=n; else (*t).a=n;}

  • Dinamike strukture podataka 78

    Prvo se s tekuim pokazivaem t premjetamo na kraj koristei ranje napisanu funkciju na_kraj(). Zatim pravimo novi element: n=new element; Kako e on biti na kraju njegov pokaziva treba pokazivati na NULL. (*n).a=NULL; Nakon toga u njegov dio za podatke unosimo neku vrijednost: cin>>(*n).p; I na kraju moramo jo pripaziti je li to prvi element koji smo upisali u listu. Ako jeste onda glava jo uvijek pokazuje na NULL, pa je moramo postaviti da pokazuje na na tek stvoreni element, a kad smo ve tu postavimo i tekui na istu adresu: g=t=n; Ako to nije sluaj, dakle ako glava nije NULL, znai da ima elemenata u listi, a prije smo funkcijom na_kraj() postavili t kao zadnji, i moemo postaviti da taj zadnji (sada je on ve predzadnji) pokazuje na novoga: (*t).a=n; Odlazak do odreenog elementa u listi emo rjeiti funkcijom idi_do(). void idi_do() {int i;if (g==NULL) return; t=g; couti; while((*t).a!=NULL && i>1) {t=(*t).a;i--;} if (i>1) cout

  • Dinamike strukture podataka 79

    U ovom sluaju t ostane na odreenom zapisu, pa to moemo upotrijebiti za pozicioniranje na element gdje elimo ubaciti ili brisati element iz liste. Ubacivanje elementa je relativno jednostavno. Napravimo novi element, a onda on pokazuje na ono na to je pokazivao tekui (dakle na slijedei), a tekui pokazuje na njega. Pogledajmo to grafiki: n n=new element;

    (*n).a t (*t).a n

    (*n).a t (*n).a=(*t).a; (*t).a (*t).a=n; Naravno moramo unijeti i podatak u (*n).p. void ubaci() {n=new element; cout(*n).p; (*n).a=(*t).a; (*t).a=n;} I funkcija za brisanje tj. izbacivanje elementa iz liste je jednostavna, ali moramo pripaziti na neke pojedinosti: void obrisi() {if (g==t) {g=t=(*t).a;return;} n=g;while((*n).a!=t) n=(*n).a; (*n).a=(*t).a;t=n;} Ako je tekui pozicioniran na prvi element (g==t) onda ga briemo tako da glava pokazuje na drugi tj. na onaj na koji je on do tada pokazivao: g=t=(*t).a; Zatim moramo pronai prethodnik onoga kojeg briemo: n postavimo na poetak i pomjeramo se s njim kroz niz dok njegov pokaziva ne pokae na tekui. n=g;while((*n).a!=t) n=(*n).a; Sada jo samo preostaje da taj prethodnik pokazuje na ono na to je do tada pokazivao tekui i tekui je praktino izbaen:

  • Dinamike strukture podataka 80

    n t (*n).a (*t).a (*n).a=(*t).a; I jo samo jedna sitnica, tekui postaje svoj prethodnik tj. t=n; Zadnja naa funkcija je ispis, a ona radi na istom principu kao i prva tj na_kraj() s time da jo i ispisuje podatke iz struktura kroz koje prolazi. Pogledajmo na kraju cijeli program: #include #include struct element{int p; element *a;}*t,*n,*g; void na_kraj() { while((*t).a!=NULL) t=(*t).a;} void dodaj() {na_kraj(); n=new element; (*n).a=NULL; cout(*n).p; if (g==NULL) g=t=n; else (*t).a=n;} void idi_do() {int i;if (g==NULL) return; t=g; couti; while((*t).a!=NULL && i>1) {t=(*t).a;i--;} if (i>1) cout

  • Dinamike strukture podataka 81

    {couti; if (i==1) dodaj(); if (i==2) ispis(); if (i==3) idi_do(); if (i==4) if (t==NULL) dodaj(); else ubaci(); if (i==5) if (t!=NULL) obrisi(); if (i==6) break; }} Kako bi to vie pojednostavnili program u funkciji brisi() mi samo izbacujemo element iz liste, dok on ostaje i dalje u memoriji. Ako elimo ne samo izbaciti element nego i osloboditi memoriju moramo dopuniti funkciju za brisanje: void obrisi() {if (g==t) {g=t=(*t).a;return;} n=g;while((*n).a!=t) n=(*n).a; (*n).a=(*t).a; delete t; t=n;} Instrukcija delete t, brie onaj dio memorije na koji pokazuje pokaziva t i to u veliini koja ovisi o tipu pokazivaa. Na primjer za pokaziva na int briu se dva bajta dok naa struktura na koju je t pokaziva ima naravno vie bajta. 60. Zadatak: napiite program za sortiranje listom. Ovo je zapravo sortiranje umetanjem unesenog podatka na njegovo mjesto u poretku. Nakon svakog unosa program prolazi listu do mjesta gdje podatak treba ubaciti. Sortiranje listom je jedan od brih naina sortiranja jer se podaci sortiraju za vrijeme unosa. Kako se podaci obino unose s nekog ulaznog ureaja, na primjer tipkovnice, vrijeme prolaska kroz listu je daleko krae od nae sposobnosti da upiemo slijedei podatak. Praktino kada zavrimo unos, podaci su ve sortirani. #include struct element{int p; element *a;}*t,*n,*g; void unos(int m) {int u;t=n=g; cout

  • Dinamike strukture podataka 82

    coutj; n=new element; g=n; cout(*n).p; (*n).a=NULL; for (i=1;i(*n).p && (*t).a!=NULL) {t=n;n=(*n).a;} U while petlji prolazimo kroz listu koristei dva pokazivaa: n koji pokazuje na slijedei element i t koji kasni za njim: ako je u>(*n).p idi dalje (n=(*n).a) t n (*t).a (*n).p (*n).a Ako u nije vee od podatka u n elementu petlja se prekida i vri se umetanje: Prvo se napravi novi element: n=new element; zatim mu se dodijeli unesena vrijednost: (*n).p=u; Tu imamo i jednu posebnu situaciju kada treba ubaciti element na poetak liste, a to je kada je t==g i uneseni podatak u manji od prvog elementa (*t).p if (t==g && u

  • Dinamike strukture podataka 83

    Rekli smo kako je ovo prilino brz algoritam za sortiranje, ali moemo ga jo ubrzati tako da ne prolazimo listu od poetka do traenog elementa, nego od sredine. Tako odreujemo u koju polovicu liste pripada element (lista je sortirana). Ako je manji od srednjeg elementa pripada u prvu polovicu inae u drugu. Zatim gledamo sredinu od te polovice. Tu vidimo u koju etvrtinu pripada, zatim nju dijelimo na pola i tako dalje dok ne doemo do mjesta gdje element treba ubaciti. Problem je, naravno, u tome to program ne vidi sredinu liste, ve samo g-glavu, n-novi i t-tekui. Dakle lista je prolazna samo od poetka prema kraju i nema jednostavnog naina da pronaemo sredinu, a da ne proemo listu od poetka do stredine. Ali zato moemo drugaije organizirati podatke, tako da ne moramo prolaziti cijelu listu do traenog podatka. Ta drugaija organizacija dinamikih podataka zove se ureeno binarno stablo.

    Ureeno binarno stablo Binarno stablo je struktura podataka u kojoj svaki element ima dva pokazivaa i to pokaziva lijevo i pokaziva desno. Stablo gradimo od prvog elementa koji zovemo korijen. U ureenom binarnom stablu, ako je uneseni podatak manji idemo lijevo, inae idemo desno. L 15 D L 13 D L 16 D L 11 D L 14 D L 18 D L 10 D L 12 D L 17 D L 19 D Na primjer poinjemo unos s 15, zatim unosimo 13, on je manji i ide lijevo, zatim unosimo 11, on je manji od 15 ->lijevo, manji je i od 13 ->lijevo. Kada doemo do pokazivaa koji pokazuje na NULL napravimo novi vor binarnog stabla. #include struct cvor{int p;cvor *l,*d;}*k,*t,*n; void smjesti() {t=k; while((*t).l!=n && (*t).d!=n) if((*n).p

  • Dinamike strukture podataka 84

    cout

  • Dinamike strukture podataka 85

    znai povratak iz rekurzije, skida se sa stoga predzadnji lijevi pa se ispisuje i opet se pokua otii desno. Ako ovaj puta uspije odlazak desno njegova adresa se ostavlja na stogu i ponovo se pokuava lijevo do kraja te grane. U sluaju da sada nema lijevo vraamo se iz rekurzije pa se sada ispisuje desni (on je zadnji ostavljen na stogu) itd. Ovakav prolaz kroz binarno stablo zove se infiksni (ispis je izmeu rekurzivnih poziva), a osim njega postoje jo prefiksni (ispis prije poziva) i postfiksni (ispis poslije rekurzivnih poziva). Saetak: Dinamika struktura je niz elemenata (struktura) koji su povezani pokazivaima. Npr. prvi element pokazuje na drugi, a ovaj na trei itd. Pokazivaka varijabla moe sadravati adresu neke varijable i to znai da

    pokazuje na tu varijablu. Stog je dinamika struktura u kojoj zadnji element pokazuje na prethodni. Lista je dinamika struktura u kojoj prvi element pokazuje na slijedeeg. U binarnom stablu svaki element (vor) ima dva pokazivaa: lijevo i desno. U ureenom binarnom stablu element lijevo je manji od elementa desno.

  • Grafika 86

    Grafika Kako bi mogli koristiti grafiku22 potrebno ju je ukljuiti s #include , a u samom programu inicirati s: int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); Grafiki nain rada se prekida, i vraa na tekstualni nain s closegraph(). Koordinantni sustav grafikog ekrana je prvi kvadrant zarotiran oko x ose u etvrti kvadrant. Ili jednostavnije reeno toka 0,0 je u gornjem lijevom kutu, x ide normalno s lijeva u desno, a +y ide obrnuto odozgo prema dolje: +x 0,0 +y Veliinu (broj tokica) po x i y moemo saznati koritenjem funkcija: x=getmaxx(); y=getmaxy(); Najee koritene grafike funkcije su: line(x1,y1,x2,y2); i putpixel(x,y,boja); Boje koje moete koristiti su: BLACK DARKGRAY BLUE LIGHTBLUE GREEN LIGHTGREEN CYAN LIGHTCYAN RED LIGHTRED MAGENTA LIGHTMAGENTA BROWN YELLOW LIGHTGRAY WHITE Ovo su zapravo konstante definirane u graphics.h. Pogledajmo sada primjer programa: #include #include main() { int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); for (int y=0;yLinker ukljuena opcija: [X] Graphics library

  • Grafika 87

    Biblioteku conio.h smo ukljuili samo kako bi mogli koristiti funkciju getch(). Ona eka na pritisak bilo koje tipke kako bi nastavili s izvoenjem programa, tako da nam se grafiki ekran ne zatvori ( s closegraph() ) prije nego to vidimo to smo nacrtali. 61. Zadatak: napiite program koji crta koordinantni sustav sa ishoditem u

    sredini ekrana. #include #include main() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); int mx,my; mx=getmaxx(); my=getmaxy(); line(0,my/2,mx,my/2); line(mx/2,0,mx/2,my); getch(); //cekaj na enter closegraph();} 62. Zadatak: napiite program koji crta linearnu funkciju f(x)=3x+5. Budui da se radi o linearnoj funkciji trebaju nam samo dvije toke: mjesto gdje ulazi i toka gdje izlazi s ekrana. Ako za x uzmemo nulu onda je y=3*0+5 tj. za x=0 y=5 i to je prva toka. Izlaznu toku emo odrediti ako za y uzmemo getmaxy(). Dakle getmaxy()=3x+5 odnosno x=(getmaxy()-5)/3, a y=getmaxy(). #include #include main() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); line(0,5,(getmaxy()-5)/3,getmaxy()); getch(); //cekaj na enter closegraph();} Postoj dva problema s ovim programom: prvo, sve stoji naopake (u odnosu na matemetiki nain crtanja). A drugi problem je to smo navikli da koordinantni sustav stoji u sredini tj. da vidimo sva etiri kvadranta. Ovo moemo rjeiti na dva naina: prvi nain je da se naviknemo na situaciju (uostalom i u matematici je stvar dogovora kamo ide +y, gore ili dolje). Drugi nai bi bio pisanje funkcija za transformaciju iz kompjutorskog u matematiki koordinantni sustav. Postoji, na alost, jo jedan, trei problem, a to su razmjere. Kod linearne funkcije on nije izraen, ali kod, na primjer sinusne, bi i te kako postao vidljiv. Maksimum sinusa je 1, a minimum -1. To znai ako nacrtamo sinusnu funkciju direktno, ona e oscilirati oko x ose samo za jednu tokicu gore ili dolje.

  • Grafika 88

    Pokuajmo rjeiti slijedei zadatak, ali tako da napravimo posebne funkcije za crtanje koordinata, iniciranje grafike i crtanje s odgovarajuim transformacijama. 63. Zadatak: napiite program za crtanje sinusne funkcije za vrijednosti x od -

    do . #include #include #include const p=100; int mx,my; void grafika() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); mx=getmaxx();my=getmaxy();} void sustav() {line (0,my/2,mx,my/2); line (mx/2,0,mx/2,my);} void nacrtaj(float a,float b) {putpixel(a*p+mx/2,my/2-b*p,WHITE);} main() {float x,y; grafika();sustav(); for (x=-3.14;x

  • Grafika 89

    Isti program moemo upotrijebiti i u slijedeem zadatku: 64. Zadatak: napiite program koju crta funkciju f(x)=sin x2-cos x Kao to smo ve rekli koristimo isti program uz izmjenu u koraku for petlje (kako bi graf bio ljepi) i naravno u izrazu same funkcije: for (x=-3.14;x

  • Grafika 90

    U prethodnim primjerima vidjeli smo kako crtati krunicu sluei se sinusom i kosinusom. To emo primijeniti i u ovom zadatku, ali emo crtati crtu - kao kazaljku. Funkciju nactaj() smo promijenili tako da crta crtu od sredita ekrana (mx2,my2) do trenutnog poloaja kazaljke. void nacrtaj(float y,float x,int r) {line(mx2,my2,x*r+mx2,y*r+my2);} Argumenti funkcije su y, x i r, pri emu su x i y koordinate kraja crte-kazaljke (kada bi ona bila dugaka 1 i imala sredite u koordinantnom ishoditu), a r radijus odnosno duina kazaljke. Mnoenjem npr. x-a s r i dodavanjem pola irine ekrana (+mx2), postavljamo kazaljku na sredinu i odreujemo joj duinu. Crtamo dvije kazaljke pozivajui funkciju nactaj() iz glavnog programa: setcolor(WHITE);nacrtaj(sin(a),cos(a),100); nacrtaj(sin(a/60),cos(a/60),80); U drugom pozivu kut a dijelimo sa 60 kako bi se druga kazaljka okretala 60 puta sporije od prve. Prije ova dva poziva za crtanje kazaljki postavili smo boju na bijelo i nacrtali kazaljke, a zatim pravimo pauzu od jedne sekunde (delay(1000)23 milisekundi) i postavljamo boju na crno pa crtamo iste kazaljke i time ih zapravo briemo. Kako se sve odvija u petlji, odmah slijedi poveanje kuta a+=0.1 boja se postavlja na bijelo izraunava se novi poloaj i crtaju kazaljke. Obratite pozornost kako je pauza nakon crtanja, a izmeu brisanja i ponovnog crtanja nema pauze inae bi slika treperila na ekranu. #include #include #include #include int mx2,my2; void grafika() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); mx2=getmaxx()/2;my2=getmaxy()/2;} void nacrtaj(float y,float x,int r) {line(mx2,my2,x*r+mx2,y*r+my2);} main() {float a=0; grafika(); while(!kbhit()) {a+=0.1; setcolor(WHITE);nacrtaj(sin(a),cos(a),100); nacrtaj(sin(a/60),cos(a/60),80); delay(1000); setcolor(BLACK);nacrtaj(sin(a),cos(a),100);

    23 zbog ove instrukcije smo ukljuili dos.h

  • Grafika 91

    nacrtaj(sin(a/60),cos(a/60),80);} closegraph();} Naravno, ovaj program samo vrti kazaljke, ali pogledajmo kako bi izgledao program koji pokazuje tono vrijeme: #include #include #include #include #include int mx2,my2; void grafika() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); mx2=getmaxx()/2;my2=getmaxy()/2;} void nacrtaj(float y,float x,int r) {y=sin(y);x=cos(x); line(mx2,my2,x*r+mx2,y*r+my2);} main() {grafika();time t;float p2=3.14/2,p30=3.14/30,h=0,m=0,s=0; char sc;int i; while(!kbhit()) {gettime(&t);gotoxy(1,1); cout

  • Grafika 92

    Vidimo iz primjera kako kao argument funkcije aljemo adresu strukture t. Kao rezultat funkcija gettime() postavi vrijednosti tonog vremena u strukturu i mi ga moemo ispisati. Meutim tipovi varijabli u strukturi su unsigned char tj. slovni tip. Ovo je zapravo primjer kako moemo manje brojeve (do 255) zapisati u jedan bayt i tako tediti memoriju. Tip char je slovni tip, ali u memoriji se zapravo zapisuje ASCII kod slova, tj broj. Unsigned ispred char znai neoznaeni broj, odnosno broj bez predznaka. Prvi bit (s lijeva) binarnog broja slui za predznak + ili -, s unsigned to iskljuujemo ime dobijamo jo jedan bit za prikaz broja (inae bi brojevi u jednom bajtu bili od -128 do +127, a ovako imamo od 0 do 255). U ispisu jednostavno navodei (int) naglaavamo kako elimo ispis cijelog broja, a ne slova (znaka). cout

  • Grafika 93

    Ovakav zadatak moemo rijeiti na vie naina, a evo jednog od moguih rjeenja: #include #include #include #include void grafika() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi");} main() {grafika();time t;int i,j,x,y,kx=7,ky=15; while(!kbhit()) {gettime(&t);gotoxy(1,1); cout

  • Grafika 94

    setfillstyle(SOLID_FILL, GREEN); bar(x1, y1, x2,y2); U prethodnim primjerima vidjeli smo zapravo razliite primjere animacije koji se u biti svode na princip obrii ono od ranije pa nacrtaj novo. U slijedeem primjeru imamo zapravo isti princip ali uz koritenje druge tehnike.

    #include #include #include #include const float pi=3.14; int mx2,my2; void grafika() {int graphdriver = EGA, graphmode=EGAHI; initgraph(&graphdriver, &graphmode, "..\\bgi"); mx2=getmaxx()/2;my2=getmaxy()/2;} main() {grafika();float x,x1,y,y1,a,b,i, j,kx=10,ky=5;int n=0; while(!kbhit()) {for (b=0;b

  • Grafika 95

    a=sin(sin(i)*sin(j)*sin(b/2)*13)*15*sin(b); Broj 13 u ovom primjeru odreuje broj valova24, a 15 njihovu amplitudu. Obadva broja se mnoe s sin(b) odnosno sin(b/2), pa prema tome vidimo da razlike izmeu pojedinanih slika ovise o vanjskoj for-b petlji. Odmah na poetku te petlje koristimo mogunost rada s dvije grafike stranice. One su odreene kao nulta i prva. Sa setvisualpage(0) postavljamo nultu kao vidljivu, a sa setactivepage(1), prvu kao aktivnu, tj onu po kojoj se crta (ili brie - cleardevice() ). Na taj nain dok crtamo po jednoj, druga je vidljiva, a zatim im zamijenimo mjesta. Zamjena je rjeena varijablom n koja je u deklaraciji postavljena na 0. Izraz n=!n je postavlja na suprotno tj na 1, a slijedei puta ponovo vraa na nulu. n=!n; setactivepage(n); cleardevice(); setvisualpage(!n); U programima se ponekad pojavljuje potreba za ovakvim paljenjem i gaenjem neega pa je zgodno zapamtiti ovaj nain: #include main() {int n=0; for (int i=0;i

  • Klase 96

    Klase U C++ jeziku klase su zapravo sline strukturama, pa sve ono to smo rekli za strukture vrijedi i za klase. Osnovna razlika je u tome to su u strukturama sve varijable dostupne, dok su u klasama privatne, tj dostupne samo unutar klase, a javne varijable ili funkcije moramo deklarirati kao takve slubenom rjeju public. Pogledajmo primjer: #include class krug {public: int r; // varijabla u klasi (javna, public) float p() // funkcija u klasi {const float pi=3.14; return (r*r*pi);} }; main() {krug a,b; a.r=14; b.r=17; cout

  • Klase 97

    Uoite prednost funkcije u klasi: aljemo joj samo koordinate druge toke, a svoje koodinate ona zna. Pogledajmo slijedei primjer. Kako bi bolje razumjeli klase, koristit emo grafiku (bolje se vidi kada se vidi). #include #include #include const br=300; int mx,my,mc; class zvijezda{ float x,y,xk,yk;int boja; public: void postavi(){x=0;y=random(my); xk=random(10)+1; boja=random(mc); } zvijezda(){postavi();} ~zvijezda(){} void pokret(){ putpixel(x-xk,y,BLACK); if (x>mx) postavi(); x+=xk; putpixel(x,y,boja); } }; main() { randomize(); int gdriver = DETECT, gmode; initgraph(&gdriver,&gmode,"..\\bgi"); mx=getmaxx();my=getmaxy();mc=getmaxcolor(); zvijezda a[br]; while (!kbhit()) for (int i=0;i

  • Klase 98

    Nakon toga slijedi rije public: .Od tog mjesta pa dalje funkcije ( i varijable ako smo ih deklarirali) su javne tj. dostupne u naem primjeru iz glavnog programa. Mi, kao public, imamo samo funkciju pokret() (i naravno konstruktor i destruktor) koja izraunava novi poloaj i crta zvijezdu (prethodno brie na starom poloaju). Iz glavnog programa jednostavno u for-petlji za svaku zvijezdu pozivamo funkciju pokret(), i to ponavljamo dok nije stisnuta bilo koja tipka: while (!kbhit). Funkcija klase moe biti definirana i izvan klase, tj kasnije u programu, samo onda moramo naznaiti kojoj klasi pripada ta funkcija. To radimo operatorom :: U naem primjeru: void proba::print() to moemo proitati funkcija print pripada klasi proba. #include class proba{ public: void print(); //definirano kasnije proba(){cout

  • Klase 99

    {proba a[10]; // tu se deset puta poziva konstruktor, } // na kraju isto toliko puta destruktor, ali u obrnutom redoslijedu Konstruktor klase zapravo najee koristimo za postavljanje inicijalnih vrijednosti u varijable klase. To mogu biti konstantne vrijednosti (varijable u svim deklariranim klasama e imati istu vrijednost) ili mogu biti razliite. Pogledajmo to u slijedeem primjeru: 70. Zadatak: napiite program koji stvara pil karata. #include const char z[4]={3,4,5,6}; int n=1,zn; class karta{public: int br;char znak; karta(){br=n++; znak=z[zn]; if (n==14) {n=1;zn++;}} }; void ispis(karta *k) {for (int i=0;i

  • Klase 100

    Obratite pozornost na k++. Ovo je primjer aritmetike pokazivaa. Izraz k++ poveava adresu, ne za jedan, nego za onoliko koliko je dugaka klasa karta u memoriji. Sve ostalo je obian ispis, uz uvjet ako je broj karte = 13 prelazi se u novi red. 71. Zadatak: napiite program koji na ekranu prikazuje padanje snijega. Ovakve zadatke je zgodno rjeavati s klasama jer svaka pahulja moe biti jedna klasa, koja ima svoj poloaj i svoju funkciju koja joj regulira padanje. #include #include #include #include const bp=1000; int mx2,my2;float b; class pahuljica{float x,y,a; public: pahuljica() {x=random(mx2*2); y=my2-random(my2*2); a=b+=0.01;} void nacrtaj() {putpixel(x,y,BLACK); x+=sin(a+=0.1);y+=2; if (y>my2*2) y=0; putpixel(x,y,WHITE);} }; void grafika() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); mx2=getmaxx()/2;my2=getmaxy()/2;} main() {grafika(); char ch; pahuljica p[bp]; while (!kbhit()) for (int i=0;i

  • Klase 101

    72. Zadatak: napiite program koji prikazuje valno gibanje. Ovaj program bi morao biti slian prethodnom, jer i pahuljice se zapravo gibaju valno lijevo-desno (osim to padaju). Kako emo rjeiti zadatak? Uzmimo odreeni broj toaka i rasporedimo ih po irini ekrana i neka svaka toka oscilira gore-dolje po sinusnoj funkciji. Kako ne bi sve istovremeno ile gore ili dolje, neka izmeu kuta po kojem se izraunava njihov poloaj bude neka razlika. Dodajmo jo i mogunost da s tipkama ubrzamo ili usporimo njihovo kretanje. #include #include #include #include const bt=100; int mx2,my2,i;float k; class tocka{int x,y;float a; public: tocka(){x=i+=(mx2*2)/bt;a=k+=6.28/bt;} void nacrtaj() {putpixel(x,y,BLACK); y=sin(a)*my2+my2;a+=k; putpixel(x,y,WHITE);} }; void grafika() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); mx2=getmaxx()/2;my2=getmaxy()/2;} main() {grafika(); char ch;tocka b[bt];k=0.01; for (;;){if (kbhit()){ch=getch(); if (ch==27) break; switch (getch()){ case 75:k+=0.01;break; case 77:k-=0.01;break;} } for (int i=0;i

  • Klase 102

    Neke elemente glavnog programa treba palivije objasniti. Prvo beskonana petlja: for (;;), znai, ako u for petlji nemamo uvjet (u naem primjeru i nita drugo) to je beskonana petlja. U nastavku imamo: if (kbhit()){ch=getch(); // ako je stisnuta tipka - proitaj koja je to tipka if (ch==27) break; // ako je ESC prekini petlju Dalje koristimo instrukciju switch(...) koja omoguava izbor ovisno o vrijednosti u zagradama. switch (getch()){case 75:k+=0.01;break; case 77:k -=0.01;break;} Ovdje treba neto objasniti. Tipke strelice (funkcijske, End, Home...) prvo alju kod 0, a tek onda broj po kojem ih moemo razlikovati. To praktino znai da njih treba itati dva puta i mi to i radimo: prvi puta s ch=getch() i drugi puta u instrukciji switch(getch()) . Strelice lijevo-desno imaju kodove 75 i 77, pa ovisno o tome koja je stisnuta smanjujemo ili poveavamo varijablu k. Ovu varijablu k koristimo za poveavanje kuta a u funkciji nacrtaj() unutar klase. 73. Zadatak: napiite program koji u tekstualnom nainu crta val, ali tako da mu

    se amplituda mijenja s udaljenou. #include #include #include const max=50; int n; class val{float k;int x,y,a; //k je kut, a je amplituda public: val(){ x=++n;a=x/5+1;k=(float)n/10;y=1;} ~val(){cout

  • Klase 103

    Glavni program prvo brie ekran instrukcijom clrscr(), zatim deklariramo niz objekata a tipa val. While petlja e ponavljati dok ne stisnemo neku tipku (!kbhit()), a u njoj for petlja poziva funkciju gibanje() redom za cijeli niz deklariranih klasa. Svaka od njih ima drugaiju vrijednost x-a, kuta k i amplitude a, pa e se i zvjezdice ispisivati na razliitim mjestima. 74. Zadatak: napiite program koji ispisuje kalendar za odreenu godinu. Ovaj se zadatak moe moda i jednostavnije rjeiti bez klase, ali pogledajmo kako bi to uinili s klasom. #include #include const char dt[7]={'P','U','S','C','P','S','N'}; int bd[12]={31,28,31,30,31,30,31,31,30,31,30,31}; int prestup(int g) {return(((g%4==0) && (g%100!=0)) || (g%400==0));} class datum {public: int d,m,g,t; void novi() //povecava dan za 1 {d++;t++;if (t>6) t=0; if (d>bd[m-1]) {m++;d=1;} if (m>12) {d=m=1;g++;bd[1]=28+prestup(g);}} }; main() {datum dan;int i,j,x,y,k;clrscr(); dan.d=1;dan.m=1;dan.g=2000;dan.t=5; bd[1]=28+prestup(dan.g); for (i=1;i

  • Klase 104

    Klasa datum jednostavno poveava dan za jedan: class datum {public: int d,m,g,t; void novi() //povecava dan za 1 {d++;t++;if (t>6) t=0; if (d>bd[m-1]) {m++;d=1;} if (m>12) {d=m=1;g++;bd[1]=28+prestup(g);}} }; Varijable d, m, g, su dan, mjesec i godina, a varijabla t - dan u tjednu. Prvo poveamo d i t za jedan, pa ako je t > 6 vratimo ga na nulu25 (dane u tjednu smo oznaili brojevima od 0 do 6). Ako je dan vei od broja dana u tom mjesecu, mjesec poveavamo za jedan i dan vraamo na prvi (tj na 1). Ako je mjesec vei od 12, dan i mjesec postavljamo na 1 i poveavamo godinu za jedan. Tada postavljamo i broj dana drugog mjeseca: bd[1]=28+prestup(g); U stvari, ovu mogunost za prijelaz u slijedeu godinu i ne koristimo u naem programu, ali je zgodno pisati klase koje bi se mogle koristiti i u nekom drugom programu ili u proirenju ovog: 75. Zadatak: koristei se elementima ovog programa napiite program koji

    odreuje koliko je dana prolo izmeu dva datuma. Ali, vratimo se kalendaru. U glavnom dijelu, nakon deklaracije varijabli, naredbom clrscr() briemo ekran. Zatim postavljamo dan, mjesec, godinu i dan u tjednu. Odreujemo broj dana u drugom mjesecu i onda slijedi for petlja koja broji dane u godini: for (i=1;i

  • Klase 105

    Uoite da svaka zvijezda klasa zadrava svoje varijable. #include #include #include #include const br=1000; int mx2,my2; void grafika() {int graphdriver = DETECT, graphmode; initgraph(&graphdriver, &graphmode, "..\\bgi"); mx2=getmaxx()/2;my2=getmaxy()/2;} class zvijezda{int x,y,r;float a; zvijezda() {r=random(mx2)+5;a=(float)random(628)/100;} public: void okret() {putpixel(x,y,BLACK); x=cos(a)*r+mx2;y=sin(a)*r+my2; putpixel(x,y,WHITE); a+=0.01;} }; main() {randomize(); grafika(); zvijezda a[br]; while(!kbhit()) for (int i=0;i

  • Klase 106

    int kojoj zadajemo vrijednost generatorom sluajnih brojeva i to na osnovi maksimalnog broja boja koje su podrane u grafici, a koje dobijemo funkcijom getmaxcolor(). Evo konano i programa: #include #include #include const br=300; int mx,my,mc; class zvijezda{ float x,y,xk,yk;int boja; public: void postavi(){x=mx/2;y=my/2; xk=(float)random(100)/50-1; yk=(float)random(100)/50-1; boja=random(mc); } zvijezda(){postavi();} ~zvijezda(){} void pokret(){ setcolor(BLACK); line(x-xk,y-yk,x,y); if ((xmx)||(ymy)) postavi(); setcolor(boja); x+=xk;y+=yk; line(x-xk,y-yk,x,y); } }; main() { randomize(); int gdriver = DETECT, gmode; initgraph(&gdriver,&gmode,"..\\bgi"); mx=getmaxx();my=getmaxy();mc=getmaxcolor(); zvijezda a[br]; while (!kbhit()) for (int i=0;i

  • Klase 107

    Ako elimo vee vrijednosti jednostavno promijenimo ta dva izraza: xk=(float)random(100)/5-10; yk=(float)random(100)/5-10; Sada e maksimalna vrijednost biti 10 (100/5-10), a minimalna -10, pa e se zvijezde bre kretati. Drugo pitanje je kako zvijezde pretvoriti vidljive crtice? Najjednostavnije je uvesti novu varijablu kojom emo mnoiti xk i yk za vrijeme crtanja: line (x,y,x+xk*r,y+yk*r), a onda taj r pomalo poveavati, recimo za 0.05. Pokuajte sami! 78. Zadatak: napiite program koji simulira padanje pjeska preko prepreka. Svako zrno pjeska je jedan objekt koji ima odreene vrijednosti (varijable) napr. x i y koji odreuju poloaj i odreeni nain ponaanja koji je definiran funkcijom (ili funkcijama). Koja su to pravila ponaanja? Prvo obriemo prethodni poloaj zrna: putpixel(x,y,BLACK); Zatim provjeravamo imali ita ravno ispod: if (getpixel(x,y+k)==BLACK) y+=k; ako nema nita (BLACK) zrno pada (y+=k) ravno dolje. Ako ima neto (nije BLACK) onda proba ukoso, prvo na jednu stranu, pa na drugu. I tako dalje, ispituju se razliite pozicije ispod moe li se pasti. Ako nita nije slobodno onda zrno odskoi malo nazad (smanjimo y sluajnim brojem). Kada zrno doe do dna ekrana (y>my) poziva se funkcija za ponovno postavljanje na vrh. if (y>my) postavi(); Konstanta k odreuje pomak kod padanja (brzinu), a konstanta br broj zrna pjeska. Program izgleda kompliciran, ali zapravo nije - najvei dio je niz if-ova koji kontroliraju ima li to ispod zrna kako bi se odredio pravac pada. Naravno tu je i funkcija prepreke koja samo crta niz debelih crta na ekranu i nita vie. Zadaci za razmiljanje: - Varijabla my koja definira visinu ekrana deklarirana je u klasi, jesmo li je mogli

    deklarirati na drugom mjestu? Kako? - Sve varijable i funkcije u klasi zrno su javne (public). Koje nisu morale biti javne? - Zato nismo sadraj funkcije postavi jednostavno napisali u konstruktoru? - Analizirajt