Selma Krajnović - Programiranje 3, skripta
-
Upload
ahmed-sagdati -
Category
Documents
-
view
461 -
download
32
description
Transcript of Selma Krajnović - Programiranje 3, skripta
ETŠ Tuzla, Selma Krajinović
1
PROGRAMIRANJE 3
Modul 1: Dvodimenzionalni niz
ETŠ Tuzla, Selma Krajinović
2
Uvod, Matrice
U matematici, matrica je pravougaona tabela brojeva, ili općenito, tabela koja se sastoji od apstraktnih objekata koji se mogu sabirati i množiti.
Matrice se koriste za opisivanje linearnih jednačina, za praćenje koeficijenata linearnih transformacija, kao i za čuvanje podataka koji ovise od dva parametra. Matrice se mogu sabirati, množiti i razlagati na razne načine, što ih čini ključnim konceptom u linearnoj algebri i teoriji matrica.
Matrice omogućuju jednostavan zapis i rješavanje sistema linearnih jednačina.
Definicija Pravougaona tablica brojeva
zove se matrica tipa mxn. Tablica se stavlja u uglaste ili oble zagrade. Brojevi
su elementi matrice ili komponente matrice. Svaki element matrice odjeđen je indeksom reda u kojem se nalazi (i) i indeksom kolone (j). Tako je element a2,8 onaj koji se nalazi u drugom redu i 8. koloni. Brojevi
formiraju -ti red, brojevi
tvore j-tu kolonu, a brojevi
formiraju dijagonalu matrice .
Ako je kažemo da je kvadratna matrica reda . Kod kvadratne matrice brojevi A1,1, A2,2, A3,3,…. An,n,
formiraju glavnu dijagonalu matrice . Brojevi A1,n, A2,n-1, A3,n-2,…. An,1,
ETŠ Tuzla, Selma Krajinović
3
formiraju sporednu dijagonalu.
Ako je kažemo da je retčana matrica (ima samo jedan redak), a ako je
kažemo da je stupčana matrica. Retčane i stupčane matrice se još zovu vektori.
Matrice obično označavamo velikim pisanim slovima, A,B,X,Y…Koriste se i oznake
Vektore možemo označavati i s malim štampanim slovima a,b,x, ili s masnim slovima, a,b,x.
Na primjer, je matrica tipa 3x4, s označenim drugim retkom,
i su primjeri retčane odnosno stupčane matrice,
dok su i kvadratne matrice reda , a ujedno i stupčane i retčane matrice
Matrice i su jednake ako su istog tipa i ako je
za sve parove indeksa
ETŠ Tuzla, Selma Krajinović
4
C++ : Dvodimenzionalni niz
Matrica se u C++ predstavlja kao dvodimenizionalni niz. Kao i kod matrice, svaki element određen je indeksom
reda i kolone u kojoj se nalazi, s tim što je indeks prvog reda i indeks prve kolone 0.
Na primjer, dvodimenzionalni niz A formata 3x5, sadrži slijedeće elemente: Kolona 1 (indeks 0) Kolona 2 (indeks 1) Kolona 3 (indeks 2) Kolona 4 (indeks 3) Kolona 5 (indeks 4)
Red 1 (indeks 0) a00 a01 a02 a03 a04 Red 2 (indeks 1) a10 a11 a12 a13 a14 Red 3 (indeks 2) a20 a21 a22 a23 a24
Dakle, indeks prvog reda je 0, a poslednjeg 2. Indeks prve kolone je 0, a poslednje 4.
Deklaracija dvodimenzionalnog niza
Dvodimenzionalni niz deklariše se tako što ste najprije navede tip elemenata niza, zatim naziv niza, a onda, u
uglastim zagradama, broj redova i broj kolona.
Tip_elemenata naziv_niza [broj redova] [broj kolona]
Primjer:
float X [4] [3]
Ovom naredbom deklarisali smo niz koji će sadržati maksimalno 4x3 realna broja.
Učitavanje dvodimenizionalnog niza
Elemente niza učitavamo tako što najprije učitamo broj redova (N) i broj kolona (M), a zatim pomoću dva
brojača, unutar dvije for petlje, učitavamo red po red niza. Brojač i kontroliše red a brojač j vrstu (ili kolonu) u
koju će učitani element biti upisan. Kod sadrži i kontrolu dimenzija koje korisnik upiše.
ETŠ Tuzla, Selma Krajinović
5
Ispisivanje dvodimenzionalnog niza
Kao i kod učitavanja, dvodimenzionalni niz ispisujemo pomoću dva brojača.
Ako testiramo kodi zadamo dimenizije niza 3x3, dobijemo
ETŠ Tuzla, Selma Krajinović
6
Ako želimo urediti ispis niza možemo koristiti funkciju setw iz biblioteke iomanip. Modifikovani kod za ispis je
Ovaj kod daje
Manipulator setw(n) je manipulator koji služi za formatiranje izlaza . Određuje minimalni broj kolona (n) za ispis broja koji slijedi. Tako u naredbi cout <<setw(6)<<X[i][j]; određujemo da je najmanji broj kolona u kojima će se ispisati element niza. Podrazumijevano poravnanje broja koji slijedi je udesno. To se može promijeniti pomoću manipulatora left i right, koji se mogu navesti poslije manipilatora setw. Npr. ako u kodu za ispis niza modifikujemo naredba cout za ispis elementa niza na slijedeći način cout <<setw(6)<<left<<X[i][j];
onda ispis izgleda ovako
Inicijalizacija niza
Elemente niza možemo inicijalizovati prilikom deklaracije. Npr.
Ako izostavimo zadnji red u inicijalizaciji, elementima niza u zadnjem redu biće dodijeljene nule
ETŠ Tuzla, Selma Krajinović
7
Primjer 1.
Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te naći i ispisati sumu elemenata drugog reda i proizvod elemenata treće kolone. Elementi niza su cijeli brojevi, najmanji broj kolona je 3, najmanji broj redova je 2.
S
Promjenljiva suma2 se inicijalizuje na 0. Koristit će za formiranje sume elemenata reda.
Promjenljiva proizvod2 se inicijalizuje na 1. Koristit će se za formiranje proizvoda elemenata kolone.
Učitavanje M i N se ponavlja sve dok nije u dozvojenim granicama, i to:
2<=N<=10 i 3<=M<=10
Nakon učitavanja i ispisivanja elemenata niza, formiraju se tražena suma i proizvod, kako slijedi:
Indeks i elemenata drugog reda je 1, pa je u prvoj petlji fiksiran. Pomoću petlje po j dodaju se elementi reda.
Indeks j elemenata treće kolone je 2, pa je u drugoj petlji fiksiran. Pomoću petlje po i množe se elementi treće kolone.
i/j 0 1 2
0 1 2 3
1 4 5 6
2 7 8 9
Primjer izvršavanja programa
ETŠ Tuzla, Selma Krajinović
8
Množenje matrice skalarom
Matrica se množi s nekim skalarom (brojem) tako da se svaki element matrice pomnoži s tim brojem.
c*A = c*A[i, j]
Na primjer:
Primjer 2
Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), i realni broj x, te naći proizvod matrice i broja x. Novodobivenu matricu treba ispisati u obliku tabele.
Rješenje 1
Množenje elemenata matrice možemo izvršiti prilikom ispisa, kako slijedi:
ETŠ Tuzla, Selma Krajinović
9
Rješenje 2
Formira se novi dvodimenzionalni niz Y prema formuli:
Y = broj * X, tj. Y[i,j]= broj * X[i,j]
ETŠ Tuzla, Selma Krajinović
10
Sabiranje matrica
Ako su zadane matrice A i B, dimenzija mxn, njihov zbir A + B je nova matrica C, dimenzija mxn, čiji su elementi izračunati sabiranjem odgovarajućih elemenata matrica A i B, t.j.
C=A+B, C[i, j] = A[i, j] + B[i, j]
Na primjer:
Primjer 3
Učitati dva dvodimenzionalna niza sa maksimalno 10x10 elemenata i formirajte i ispišite matricu koja predstavlja
zbir učitanih matrica.
ETŠ Tuzla, Selma Krajinović
11
Množenje matrica
Matrice A i B možemo pomnožiti samo ako su ulančane, odnosno ako A ima onoliko kolona koliko B ima redova. Matrica C=A*B ima redova koliko ima matrica A i onoliko kolona koliko ima matrica B.
Neka je, dakle, A dimenzija nxk i B dimenzija kxm. Tada je matrica C dimenzija nxm i vrijedi
Anxk * Bkxm = Cnxm
Npr. neka je zadana matrica A formata 3x4 i B formata 4x5 sa elementima kao na slici
A3x4 * B4x5 = C3x5
Rezultujuća matrica C biće formata 3x5, sa elementima:
c11 c12 c13 c14 c15
c21 c22 c23 c24 c25 c31 c32 c33 c34 c35 Npr. element c23 računa se kao
Elementi prvog reda nove matrice računaju se prema formulama: c11=a11*b11 + a12*b21 + a13*b31 + a14*b41 c12=a11*b12 + a12*b22 + a13*b32 + a14*b42 c13=a11*b13 + a12*b23 + a13*b33 + a14*b43 c14=a11*b14 + a12*b24 + a13*b34 + a14*b44 c15=a11*b15 + a12*b25 + a13*b35 + a14*b45
Dakle, elementi prvog reda matrice A množe se odgovarajućim elementima pojedinih kolona u matrici B. c1,j =a11*b1j + a12*b2j + a13*b3j + a14*b4j, gdje j uzima vrijednosti od 1 do 5 i predstavlja indeks kolone sa kojom se množi.
Elementi drugog reda nove matrice računaju se prema formulama: C21=a21*b11 + a22*b22 + a23*b31 + a24*b41 C22=a21*b12 + a22*b22 + a23*b32 + a24*b42 C23=a21*b13 + a22*b23 + a23*b33 + a24*b43 C24=a21*b14 + a22*b24 + a23*b34 + a24*b44 C25=a21*b15 + a22*b25 + a23*b35 + a24*b45
Dakle, drugog reda matrice A množe se odgovarajućim elementima pojedinih kolona u matrici B. C2,j =a21*b1j + a22*b2j + a23*b3j + a24*b4j
Elementi trećeg reda nove matrice računaju se prema formulama: C31=a31*b11 + a32*b22 + a33*b31 + a34*b41 C32=a31*b12 + a32*b22 + a33*b32 + a34*b42 C33=a31*b13 + a32*b23 + a33*b33 + a34*b43 C34=a31*b14 + a32*b24 + a33*b34 + a34*b44 C35=a31*b15 + a32*b25 + a33*b35 + a34*b45
Dakle, drugog reda matrice A množe se odgovarajućim elementima pojedinih kolona u matrici B.
ETŠ Tuzla, Selma Krajinović
12
C2,j =a21*b1j + a22*b2j + a23*b3j + a24*b4j
Na primjer,
Primjer 4
Napisati program koji ucitava matricu X formata nxk i matricu Y formata kxm, te izracunava i ispisuje matricu C koja je proizvod
matrica A i B.
Formiranje elemenata rezultujućeg niza realizuje se u okviru tri petlje:
Petlja i kontroliše red u kome je element niza Z; petlja j kontroliše kolonu. Pošto se rezultujući element računa kao suma,
postavlja se početna vrijednost – netralni element za sabiranje. Zatim se množe elementi i-tog reda prve matrice sa elementima
i-te kolone druge matrice. Ima ih K, pa brojač l uzima vrijednosti od 1 do K.
ETŠ Tuzla, Selma Krajinović
13
Transponovana matrica
Transponovana matrica matrice A je matrica AT kod koje su kolone i redovi zamijenili mjesta.
Dakle, ako je A dimenzija nxm, tada je AT tipa mxn. Na primjer,
Primjer 5
Učitati matricu, a zatim ispisati transponovanu matricu.
Element transponovane matrice sa indeksom i,j dobiva vrijednost
elementa sa indeksom j,i polazne matrice.
ETŠ Tuzla, Selma Krajinović
14
Primjer 6
Učitati kvadratnu matricu i ispisati elemente na glavnoj i elemente na sporednoj dijagonali.
Kvadratna matrica ima jednak broj redova i kolona, te oba
brojača imaju isti opseg.
Za elemente na glavnoj dijagonali vrijedi i=j, tj. na glavnoj
dijagonali su oni elementi koji imaju isti indeks reda i kolone.
Sporedna dijagonala sadrži elemente kod kojih je indeks
kolone određen kao N-i-1
Primjer 7
Napisati program koji formira kvadratnu matricu formata nmax =20 čiji elementi su *. Npr. za n=5, matrica
izgleda ovako:
* * * * * * * * * * * * * * * * * * * * * * * * * Ispisati kreiranu matricu. Zatim formirati i ispisatimatrice kako slijedi
GD1
* * * * * * * * * * * * * * * GD2
* * * * * * * * * * * * * * *
ETŠ Tuzla, Selma Krajinović
15
SD1
* * * * * * * * * * * * * * *
SD2
* * * * * * * * * * * * * * *
Kreiranje matrice realizuje se u okviru slijedećeg koda:
Posmatrajmo indekse elemenata matrice formata 5x5
a00 a01 a02 a03 a04
a10 a11 a12 a13 a14
a20 a21 a22 a23 a24
a30 a31 a32 a33 a34
a40 a41 a42 a43 a44
Možemo uočiti ovisnost između indeksa elemenata kako slijedi:
GD1: ai,j =
a00 a01 a02 a03 a04
a10 a11 a12 a13 a14
a20 a21 a22 a23 a24
a30 a31 a32 a33 a34
a40 a41 a42 a43 a44
ETŠ Tuzla, Selma Krajinović
16
GD2: ai,j =
SD1: ai,j =
SD2: ai,j =
Primjer 8
Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te naći i ispisati koordinate (red i kolona) prve i zadnje pojave najmanjeg, odnosno najvećeg elementa matice.
Pretpostavimo da je učitana matrica kao na slici. Tada bi očekivani rezultati bili:
U ovoj matrici najmanji element je 0. Prva pojava ovog elementa je u redu 2 i koloni 1. Zadnja pojava je u redu 5 i koloni 4.
Najveći element je 8. Prva pojava ovog elementa je u redu 4 i koloni 5. Zadnja pojava je u redu 5 i koloni 5.
Rješenje
Obilježimo promjenljive kako slijedi:
a00 a01 a02 a03 a04
a10 a11 a12 a13 a14
a20 a21 a22 a23 a24
a30 a31 a32 a33 a34
a40 a41 a42 a43 a44
a00 a01 a02 a03 a04
a10 a11 a12 a13 a14
a20 a21 a22 a23 a24
a30 a31 a32 a33 a34
a40 a41 a42 a43 a44
a00 a01 a02 a03 a04
a10 a11 a12 a13 a14
a20 a21 a22 a23 a24
a30 a31 a32 a33 a34
a40 a41 a42 a43 a44
1 5 2 1 5
0 2 4 6 4
1 2 5 6 2
1 2 0 7 8
7 8 7 0 8
ETŠ Tuzla, Selma Krajinović
17
mini – najmanji element
minip_i – indeks reda prve pojave najmanjeg elementa
minip_j – indeks kolone prve pojave najmanjeg elementa
miniz_i – indeks reda zadnje pojave najmanjeg elementa
miniz_j – indeks kolone zadnje pojave najmanjeg elementa
maxi – najveći element
maxip_i – indeks reda prve pojave najvećeg elementa
maxip_j – indeks kolone prve pojave najvećeg elementa
maxiz_i – indeks reda zadnje pojave najvećeg elementa
maxiz_j – indeks kolone zadnje pojave najvećeg elementa
Najprije pronađemo najveći i najmanji element matrice:
Zatim, pronađimo tražene indekse:
ETŠ Tuzla, Selma Krajinović
18
Primjer 9
Učitati kvadratnu matricu (elementi matrice su cijeli brojevi, maximalan broj redova i kolona je 10).
Formirati novu matricu kod koje su u svakom redu elementi polazne matrice poredani u rastućem
redoslijedu. Ispisati obje matrice.
Npr. ako je učitana matrica x, onda matrica y treba da bude kao na slici.
x y
Rješenje
Za svaki red ulazne matrice (kontrolisan indeksom i) uradimo slijedeće:
- Prepišemo i.ti red ulazne umatrice x u i.ti red matrice y
- Sortiramo i.ti red. Za svaki element kolone (j) postavljamo najmanji element na poziciju j.
Koristimo algoritam za sortiranje niza „Bubble sort“. Treća petlja omogučava pristup elementima
j+1..n-1, s ciljem nalaženja najmanjeg elementa reda i i kolone j.
Primjer 10
Korisnik učitava n cijelih brojeva tipa long (n max =10). Prebrojati koliko puta se među učitanim
brojevima pojavljuju cifre Dekadnog brojnog sistema.
Npr. korisnik učitava 4 broja, kako slijedi:
1 5 2 1 5
0 2 4 6 4
1 2 5 6 2
1 2 0 7 8
7 8 7 0 8
1 1 2 5 5
0 2 4 4 6
1 2 2 5 6
0 1 2 7 8
0 7 7 8 8
ETŠ Tuzla, Selma Krajinović
19
123123 3455 2232 98744 Program treba da ispiše: Cifra 0 pojavljuje se 0 puta. Cifra 1 pojavljuje se 2 puta. ... Cifra 9 pojavljuje se 1 puta. Rješenje:
U programu ćemo korisiti bibilioteku „climits“, pomoću koje ćemo pročitati maksimalnu vrijednost koja
se može upisati za „long“ tip podataka.
Konstanta LONG_MAX prikazuje maksimalnu vrijednost za tip long na datom sistemu i korištenom
kompajleru.
Cilj je od ucitanih brojeva formirati dvodimenzionalnu matricu čiji elementi će biti cifre učitanih brojeva.
Nakon učitavanja broja, pomoću operatora div i mode izdvajamo cifre broja i formiramo matricu cifara u
slijedećem kodu:
U prvu kolonu svakog reda upišemo koliko broj ima cifara (x[i][0]=j-1). Promjenljivu m koristimo da
bismo zapamtili maksimalan broj cifara.
Ako su ucitani brojevi
ETŠ Tuzla, Selma Krajinović
20
123123 3455 2232 98744 Ovaj kod bi u memoriju upisao:
6 3 2 1 3 2 1
4 5 5 4 3
4 2 3 2 2
5 4 4 7 8 9
U prvoj koloni je broj cifara, a u ostalim su cifre ispisane u obrnutom poretku. Neki od elemenata niza
ostaju nedefinisani, tj. Imaju vrijednosti koje su prethodno bile dodjeljene lokacijama rezervisanim pri
deklaraciji niza. Stoga ćemo ih definisati, tako što ćemo im dodijeliti vrijednost -1. To radi slijedeći kod:
Sada u memoriji imamo
6 3 2 1 3 2 1
4 5 5 4 3 -1 -1
4 2 3 2 2 -1 -1
5 4 4 7 8 9 -1
Ispišimo učitane brojeve sa vodećim prazninama, vodeći računa o tome da je dekadni brojni sistem
pozicioni brojni sistem:
Brojeve ispisujemo u poretku kako su učitani, pa je brojač i u rastućem redoslijedu (for (i=0;i<n;i++)), ali
brojač j postavljamo da se mijenja u opdajućem redoslijedu (j=m-1;j>0;j--), s tim što ne ispisujemo prvu
kolonu koja sadrži broj cifara. Ako je u matrici -1, ispisujemo razmak.
Konačno, koristimo jednodimenzionalni niz bc, kojeg naprije inicijalizujemo na 0. Zatim za svaku cifru iz
dvodimenzionalne matrice cifara uvečavamo odgovarajući element jednodimenzionalnog niza.
ETŠ Tuzla, Selma Krajinović
21
Primjer 11
Napisati program koji učitava kvadratnu matricu sa maksimalno 10x10 cijelih brojeva, a zatim ispisuje
sve sub matrice reda n-1xn-1. Npr. neka imamo matricu formata 3x3
A00 A01 A02
A10 A11 A12
A20 A21 A22
Treba ispisati matrice
A11 A12
A21 A22
A10 A12
A20 A22
A10 A11
A20 A21
ETŠ Tuzla, Selma Krajinović
22
A01 A02
A21 A22
A00 A02
A20 A22
A00 A01
A20 A21
A01 A02
A11 A12
A00 A02
A10 A12
A00 A01
A10 A11
Za formiranje submatrica koristimo kod:
//formiranje sub matrica
for (r=0;r<n;r++)
for (k=0; k<n; k++)
{
cout << endl<<"Sub matrica ("<<r <<","<<k<<") "<<endl;
for (i=0;i<n ; i++)
{
for (j=0;j<n; j++)
if ((i!=r) && (j!=k))
cout <<setw(6)<<x[i][j];
cout <<endl;
}
}
ETŠ Tuzla, Selma Krajinović
23
ZADACI ZA VJEŽBU
1. Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te naći sumu (proizvod) svakog reda (stupca) matrice.
2. Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te naći sumu (proizvod) svakog reda matrice i ispisati red koji ima najveću (najmanju) sumu (proizvod).
3. Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te naći i ispisati najmanji (najveći) element matice.
4. Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te naći i ispisati u kojem koloni/redu se nalazi najmanji (najveći) element drugog reda/stupca matice.
5. Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te naći i ispisati koliko elemenata matrice je veće (manje) od prosjeka.
6. Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te učitati koordinate (r,s) nekog njenog elementa i ispisati koliko puta se taj element javlja u matrici. Također treba ispisati koliko elemenata matrice je veće (manje) od tog elementa.
7. Napiši program koji će učitati matricu dimenzija nxm (n,m ≤ 10), ispisati ju u obliku tabele te naći i ispisati najmanji (najveći) maksimum (minimum) redova matice. (Naći max svakog reda i onda min od tih brojeva. Analogno za najveći minimum)
8. Napiši program koji će učitati matricu reda n (n ≤ 10), ispisati ju u obliku tabele te naći i ispisati trag matrice. (Suma elemenata glavne dijagonale je trag matrice).
9. Napiši program koji će učitati matricu reda n (n ≤ 10), ispisati ju u obliku tabele te naći i ispisati sumu (proizvod) elemenata sporedne dijagonale.
10. Napiši program koji će učitati matricu reda n (n ≤ 10), ispisati ju u obliku tabele te naći i ispisati najveći (najmanji) element glavne (sporedne) dijagonale.
11. Napiši program koji će učitati matricu reda n (n ≤ 10), ispisati ju u obliku tabele te naći i ispisati najveći (najmanji) element ispod (iznad) glavne dijagonale.
12. Napiši program koji će učitati matricu reda n (n ≤ 10), ispisati ju u obliku tabele te naći i ispisati sumu (proizvod) element ispod (iznad) glavne dijagonale.
13. Napiši program koji će učitati matricu reda n (n ≤ 10), ispisati ju u obliku tabele te provjeriti i ispisati je li ona simetrična (ai,j=aj,i) / antisimetrična (ai,j=-aj,i)
14. Napiši program koji će učitati matricu reda n (n ≤ 10), ispisati ju u obliku tabele te provjeriti i ispisati je li ona gornja (svi elementi ispod glavne dijagonale su 0) / donja (svi elementi iznad glavne dijagonale su 0) trokutasta matrica.
15. Napiši program koji će učitati 2 matrice reda n (n ≤ 10), te naći njihovu sumu i proizvod. Novodobivenu matricu treba ispisati u obliku tabele.
16. Napiši program koji će učitati matricu A reda n (n ≤ 10), a zatim formirati drugu matricu B tako da je bi,j = proizvodu suma i-tog reda i j-tog stupca
17. Napisati program koji računa:
A) Sumu elemenata ispod glavne dijagonale, ne računajući elemente na glavnoj dijagonali
B) Sumu elemenata iznad glavne dijagonale, ne računajući elemente na glavnoj dijagonali
ETŠ Tuzla, Selma Krajinović
24
C) Sumu elemenata ispod sporedne dijagonale, ne računajući elemente na glavnoj dijagonali
D) Sumu elemenata iznad sporedne dijagonale, ne računajući elemente na glavnoj dijagonali
18. Napiši program koji će učitati matricu reda n (n ≤ 10), ispisati ju u obliku tabele te provjeriti i ispisati je li ona simetrična / antisimetrična.
Matrica je simetrična ako važi, za svako i i j da je ai,j=aj,i.
Matrica je antsimetrična ako važi, za svako i i j da je ai,j=-aj,i.
ETŠ Tuzla, Selma Krajinović
25
Modul 2:
Primjena struktura podataka i pointera
Povezane liste
Verzija Datum Autor Napomena
1.0 01.10.2010. skr Draft
1.1 16.10.2010. Skr Modifikacije Povezane liste
1.2 04.12.2011. Skr Modifikacije pointer + niz
1.3 28.01.2012 Skr Povezane liste, pocetni primjer
ETŠ Tuzla, Selma Krajinović
26
Složeni tipovi i strukture podataka
Do sada smo koristili samo ugrađene, proste tipove podataka (int, float, char...). Svaka promjenljiva koju
smo koristili mogla je imati samo jednu vrijednost određenog tipa. U slučaju niza, svaki element niza
mogao je imati samo jednu vrijednost određenog prostog tipa podataka.
U praksi, često je potrebno obrađivati podatke čije svođenje na proste tipove podataka rješavanje
problema znatno komplikuje. U takvim situacijama, možemo sami kreirati složene, korisničke tipove
podataka.
Promjenljive koje prilikom deklaracije povezujemo sa ugrađenim ili korisničkim tipovima podataka imaju
određena ograničenja, naročito kada je u pitanju rad sa funkcijama i nizovima promjenljivih dimenzija.
U ovom modulu upoznaćemo napredne strukture podataka, a to su strukture, pokazivači, reference i
vezane liste.
Strukture
Često se javlja potreba za objedinjavanjem različitih tipova podataka u jednu cjelinu, kao što su npr.
podaci o jednom učeniku (ime, prezime, pol, razred...). U ovakvim situacijama prikladno je korištenje
složenog tipa podataka kojeg nazivamo struktura (slog ili zapis – record).
Struktura je skup jedne ili više promjenljivih koje su povezane, odnosno grupisane, zajedničkim imenom.
Razlikujemo jednostavne i složene strukture. Struktura može sadržavati bilo koji prosti tip podatka u
C++, niz, ili ugniježdene strukture (struktura u strukturi).
Definicija strukture U opštem slučaju, struktura se definiše na slijedeći način:
struct ime_strukture
{
tip_člana_1 naziv_člana_1;
tip_člana_2 naziv_člana_2;
...
tip_člana_n naziv_člana_n;
};
gdje je
struct ključna riječ koja označava početak definisanja strukture,
ime_strukture naziv strukture,
unutar vitičastih zagrada navodimo sve članove (elemente) koje želimo kreirati strukturom, tako
što navodimo tip a zatim naziv člana
ETŠ Tuzla, Selma Krajinović
27
Definicija strukture može se navesti bilo gdje u programu, ali je obično izvan funkcije main, što je čini
dostupnom svugdje unutar programa.
Npr. slijedećim kodom definišemo strukturu učenik, koja ima tri elementa: prezime i ime tipa string i broj
tipa int.
struct Ucenik
{
string prezime;
string ime;
int broj;
};
Deklaracija promjenljive tipa struktura Ako želimo koristiti promjenljivu tipa struktura, deklarišemo je na potpuno isti način kao i kada se
koristimo standardnim tipovima podataka. To znači, navedemo naziv strukture a zatim ime promjenljive.
Primjer deklaracije
Ucenik osoba;
Na ovaj način deklarisali smo promjenljivu osoba koja je tipa strukture Ucenik.
Pristup članovima strukture Članovima strukture pristupamo navođenjem imena promjenljive tipa struktura, tačke i imena člana
Npr. Ako želimo ucitati prezime osobe, navodimo:
cin >> osoba.prezime;
Primjer 1
Napisati program koji definiše strukturu Ucenik, a zatim deklariše promjenljivu osoba. Učitati i ispisati
podatke o jednoj osobi.
ETŠ Tuzla, Selma Krajinović
28
Zadatak za vježbu 1
Definisati strukturu pravougaonik, koja kao članice ima slijedeće realne podatke: a i b (stranice
pravougaonika), P (površina pravougaonika) i O (obim pravougaonika). Napraviti funkcije za računanje
površine (Povrs) i obima (Obim) pravougaonika ako im se kao argumenti proslijede stranice
pravougaonika. U glavnom programu učitati elemente strukture a i b, zatim pozvati odgovarajuće
funkcije za računanje članica strukture P i O. Ispisati sve vrijednosti članica strukture.
Primjer 2
Definišite strukturu „Vrijeme“ koja sadrži tri člana: sati, minute i sekunde i koja predstavlja tekuće
vrijeme u toku dana, izraženo u satima, minutama i sekundama. Definišite funkciju UcitajVrijeme, koja
učitava sate, minute i sekunde u strukturu Vrijeme. Zatim definišite funkciju IspisiVrijeme koja ispisuje
vrijeme, proslijeđeno kao parametar u funkciju, u obliku hh:mm:ss (tj. sati, minute i sekunde se ispisuju
kao dvocifreni brojevi sa, eventualno, vodećim nulama. Zatim definisati funkciju „SaberiVrijeme“ koja
prima dva vremena koja su proslijeđena kao parametri i vraća treće vrijeme koje nastaje sabiranjem dva
ulazna vremena (npr. sabiranjem 3h 34min 52sec i 4h 42min i 20sec treba da se dobije vrijeme 8h 17
min 12 sec).
Napraviti testni program koji testira sve funkcije
Rješenje
Najprije definišemo strukturu i sve funkcije.
ETŠ Tuzla, Selma Krajinović
29
Funkcija UcitajVrijeme provjerava unos vrijednosti i vraća strukturu Vrijeme. Funkcija IspisiVrijeme ne
vraća nikakvu vrijednost:
U funkciji main testiramo ove dvije funkcije:
ETŠ Tuzla, Selma Krajinović
30
Startovanjem programa dobijemo:
Funkcija SaberiVrijeme koristi cjelobrojno dijeljenje i operator modul za računanje sabranih sekundi,
minuta i sekundi, kako slijedi:
Za testiranje koristimo kod:
Zadaci za vježbu: 1. Ispraviti funkciju SaberiVrijeme iz prethodnog zadatka tako da vrši provjeru zbira sati kako bi
umjesto ispisa „25 sati“ ispisala vrijeme „01 sati“.
2. Napisati programi koji izračunava udaljenost između dvije tačke određene koordinatama x i y. U
programu koristiti strukturu tačka, koja sadrži članice x i y, a koje predstavljaju koordinate tačke
u ravni. Za unos koordinata tačke napraviti funkciju učitajTačku a za ispis funkciju ispisiTacku.
Napraviti i funkciju „udaljenost“ za računanje udaljenosti između dvije tačke u ravni.
ETŠ Tuzla, Selma Krajinović
31
3. Napisati program koji izvšava osnovne operacije (+,- * i /) nad kompleksnim brojevima. Koristiti
strukturu kompleksan_broj koja ima dva člana: realni_dio i imaginarni_dio. Napraviti funkcije za
unos i ispis kompleksnog broja. Za svaku operaciju napisati funkciju, te je pozvati u glavnom
programu.
Uputstvo:
Neka su z1=x1+iy1 i z2=x2+iy2 dva kompleksna broja. Računske operacije su definisane na sljedeći
način:
Struktura i niz Promjenljive tipa niz također mogu kao elemente imati strukturu podataka. Npr, ako u programu treba
obrađivati podatke o više učenika, deklarišemo niz kao
Ucenik ucenici[30];
Elementima niza/ strukture pristupamo ovako:
Ucenici [i].prezime
Primjer 3
Definisati strukturu učenik, sa članovima prezime, ime i prosjek. Napraviti program koji učitava podatke
o N ucenika a zatim ispisuje ime, prezime i prosjek svakog učenika, a zatim učenika sa najvećim
prosjekom.
Rješenje
Definisanje strukture ucenik i promjenljive razred, koja je niz promjenljivih tipa učenik
ETŠ Tuzla, Selma Krajinović
32
Struktura kao član strukture Definicja strukture može sadržati član koji je tipa struktura. Npr. definišimo strukturu datum
struct datum
{
int dan;
ETŠ Tuzla, Selma Krajinović
33
int mjesec;
int godina;
};
Zatim definišimo strukturu čija članica je tipa datum:
struct ucenik
{
char ime[15];
char prezime[15];
int maticni;
float prosjek;
struct datum rodjendan;
}
Ako je član strukture također struktura, za pristup članicama strukture koristimo tačku da odvojimo
naziv promjenljive i ime člana, sve do posljenjeg člana složene strukture. Npr.
cout<<"Datum rodjenja, dan: ";
cin>>razred[i].rodjendan.dan;
cout<<" Datum rodjenja, mjesec: ";
cin>>razred[i].rodjendan.mjesec;
cout<<" Datum rodjenja, godina: ";
cin>>razred[i].rodjendan.godina;
Zadaci za vježbu: 1. Modifikovati primjer 3, tako što se, uz ostalo, za učenika učitava i datum rođenja. Također, kod
ispisa najboljeg učenika ispisati i datum rođenja.
2. Modifikovati primjer 3, tako da uzima u obzir mogućnost da više učenika ima isti prosjek. Ispisati
sve učenike čiji prosjek je jednak maksimalnom.
3. Modifikovati primjer 3, tako što dodajemo funkcije za sortiranje učenika po rednom broju,
prosjeku i prezimenu.
4. Napraviti strukturu tacka čije članice su koordinate x i y. Zatim definisati strukturu tougao, čije
članice su tri tačke koje predstavljaju tjemena trougla, kao i članice površina i obim trougla.
Napraviti funkcije za:
- Unos tjemena trogula
- Računanje udaljenosti između dvije tačke
- Računanje obima trougla
- Računanje površine trougla
U glavnom programu korisnik učitava podatke o n trouglova, a zatim ispisati podatke o trouglu
čija površina je najveća.
ETŠ Tuzla, Selma Krajinović
34
Pokazivači (pointers)
Statičke i dinamičke promjenljive Do sada smo koristili statičke promjenljive. Npr. U naredbama koje slijede, određujemo da se u toku
prevođenja programa rezerviše memorijska lokacija za smještaj cjelobrojnog podatka sa simboličkim
imenom a, a zatim toj promjenljivoj dodjeljujemo vrijednost 10. a je statička promjenljiva
int a;
a=10;
Statička promjenljiva predstavlja imenovani prostor koji sadrži vrijednost. Memorijska lokacija na kojoj je
ta promjenljiva ostaje zauzeta svo vrijeme trajanja programa.
Za razliku od statičke, pokazivač je promjenljiva koja pokazuje na drugu promjenljivu. Pokazivač sadrži
memorijsku adresu na kojoj se nalazi vrijednost. Taj memorijski sadržaj na koji pokazuje pokazivač
predstavlja dinamičku promjenljivu.
Pokazivači Pokazivač je promjenljiva koja čuva memorijsku adresu.
Memorija računara je podijeljena na sekvencijalno označene memorijske lokacije. Svaka lokacija ima
adresu. Adresa lokacije može se čuvati u pokazivaču.
Kocka simbolički označava memorijsku lokaciju u kojoj se čuva objekat. “objekat” je
promjenljiva. Njena trenutna vrijednost je 6.
Promjenljiva koja sadrži adresu memorijske lokacije u kojoj se čuva objekat prikazana je strelicom kao na
slici (objekat_ptr). Promjenljiva objekat_ptr je pokazivač. Pokazivač sadrži adresu promjenljive.
Pokazivač „pokazuje“ na promjenljivu. Nazivamo ga i adresnom promjenljivom, jer sadrži adresu druge
promjenljive.
Deklaracija pokazivača Pokazivač deklarišemo navođenjem tipa promjenljive na koju će pokazivati i znaka asterisk (*) ispred
imena koje dodijelimo pokazivačkoj promjenljivoj. Npr.
int objekat; // objekat je promjenljiva tipa int
int *objekat_ptr; // *objekat_ptr je pokazivač na promjenljvu tipa integer
Operatori Operatori koji se koriste sa pokazivačima dati su u tabeli:
Operator Značenje
ETŠ Tuzla, Selma Krajinović
35
* Dereferenciranje - Vraća vrijednost promjenljive koja je na lokaciji na koju pokazuje
pokazivač
& Referenciranje - Vraća adresu lokacije na kojoj je promjenljiva čije ime se navodi nakon
operatora
Slijede primjeri korištenja operatora.
int objekat =5;
int *objekat_ptr;
objekat_ptr = &objekat;
„objekat“ je promjenljiva koja ima vrijednost 5. „objekat_ptr“ je pokazivač na lokaciju na kojoj je cjelobrojna promjenljiva. Pokazivaču objekat_ptr dodjeljuje se adresa na kojoj je promjenljiva objekat.
drugi_objekat = *objekat_ptr;
Promjenljiva drugi_objekat dobiva vrijednost koja se čuva na adresi koja je u pokazivaču objekat_ptr. *objekat_ptr = 6;
U promjenljivu čija je adresa u pokazivaču objekat_ptr smješta se vrijednost 6. Objekat_ptr sadrži adresu promjenljive objekat, te promjenljiva objekat poprima vrijednost 6.
Primjetimo da se operator * može imati različite funkcije:
u deklaraciji pokazivača int int *x_ptr;
kao operator dereferenciranja y = *x_ptr;
kao operator množenja z =x*z;
Primjer 1
U slijedećem primjeru ilustrujemo korištenje pokazivača i operatora * i &. Deklarišemo statičku
promjenljivu Godina i pokazivač pGodina, a zatim dodjeljujemo adrese, vrijednosti sa adresa i
vrijednosti.
ETŠ Tuzla, Selma Krajinović
36
Važno je istaknuti da postoji bitna razlika između deklaracije statičke promjenljive i deklaracije pointera.
Kada deklarišemo pointer, ne dovodimo ga u vezu ni sa jednom memorijskom lokacijom. Ako to želimo
uraditi, koristi se službena riječ new.
Ako deklarišemo pokazivač zadajemo naredbu:
int *a;
Ovom naredbom samo deklarišemo pokazivač, ali ne i lokaciju na koju on pokazuje. Pokazivač ne sadrži
nikakvu vrijednost.
Slijedećom naredbom rezervišemo memorijsku lokaciju u koju se može smjestiti cio broj a njenu adresu
dodjeljujemo pointeru. Kažemo, alociramo memoriju za pointer.
a=new int;
Ove dvije naredbe možemo objediniti naredbom:
int *a = new int;
I do sada smo statičke promjenljive istom naredbom deklarisali (najavljivali njihovo korištenje) i
inicijalizovali (dodjelivali početnu vrijednost promjenljivoj). Analogno tome, možemo reći da pointere u
jednoj naredbi deklarišemo i inicijalizujemo, pomoću new(). Dodatno, rezervišemo i memorijsku lokaciju
za promjenljivu čija adresa se smjesti u pokazivač.
U dosadšnjim primjerima, pointeru smo dodjeljivali vrijednost pomoću operatora referenciranja (&), uz
prethodnu deklaraciju statičke promjenljive. Korištenjem new izbjegavamo korištenje statičkih
promjenljivih.
Slijedi primjer koji ilustruje alokaciju memorije za pointer.
ETŠ Tuzla, Selma Krajinović
37
Ovaj kod možemo predstaviti grafički kako slijedi:
ETŠ Tuzla, Selma Krajinović
38
Pokušajmo napraviti analogiju između pokazivača i
daljinskog upravljača za neki uređaj. Daljinski uređaj
sam za sebe nema upotrebnu vrijednost ako nema i
uređaja kojim ćemo upravljati. Ako uređaj nema svoje
vlastite komande, onda ga je on neupotrebljiv ako
nemamo daljinski uređaj.
Ako je pokazivač daljinski za tv uređaj, onda naredbom
int *p;
samo „obezbjeđujemo“ daljinski. Slijedećom naredbom „obezbjeđujemo“ tv i dovodimo „ga u vezu“ sa
daljinskim:
p = new int;
Obje radnje obezbjeđujemo slijdećom naredbom:
Int *p = new int;
Ovom naredbom daljinski i tv postaju upotrebljivi!
Zadaci za vježbu Testirajte slijedeći kod i ispravite grešku
ETŠ Tuzla, Selma Krajinović
39
Ma kako komplikovano izgledalo, pravila za rad sa pokazivačima se svode na slijedeća prosta pravila:
1. Pointeri čuvaju adrese promjenljivih. Promjenljive čuvaju podatke.
2. Do vrijednosti promjenljive na koju pokazuje pointer dolazimo pomoću operatora
dereferenciranje (*). Dereferenciranje se može izvršiti samo ako je prethodno u pointer
smještena adresa memorijske lokacije. Većina bug-ova sa pointerima posljedica je nepoštivanja
ovog pravila.
3. Samom deklaracijom pointera ne dovodimo ga u vezu sa promjenljivom. To možemo uraditi
pomoću new. Na ovaj način, inicijalizujemo pointer.
4. Operatorom dodjele vrijednosti između dva pointera postižemo da oni pokazuju na istu
memorijsku lokaciju (istu promenljivu).
Pitanja za ponavljanje
1. Koji operator se koristi za određivanje adrese promjenljive?
2. Koji operator se koristi za nalaženje vrijednosti na adresi koja se čuva u pokazivaču?
3. Šta je pokazivač?
4. Koja je razlika između adrese koju čuva pokazivač i vrijednosti na toj adresi?
5. Koja je razlika izmedu operatora referencijranja i dereferenciranja?
6. Šta rade ove deklaracije?
a. int *pOne;
b. int vTwo;
c. int *pThree = &vTwo;
7. Ako imate unsigned short promjeljivu yourAge, kako biste deklarisali pokazivač za manipulisanje
ETŠ Tuzla, Selma Krajinović
40
promjenljivom yourAge?
8. Dodjelite vrijednost 50 promjenljivoj yourAge, korištenjem pokazivača, koji je deklarisan u
pitanju 7.
9. Napišite mali program koji deklariše cjelobrojnu vrijednost i pokazivač na cjelobrojnu vrijednost.
Dodjelite pokazivaču adresu cjelobrojne vrijednosti. Upotrijebite pokazivač za postavljanje
vrijednosti u cjelobrojnoj promjenljivoj.
10. Šta nije u redu sa ovim kodom:
int main()
{ int *pInt;
*pInt = 9;
cout << “Vrijednost na pInt je “<< *pInt;
return 0; }
11. Šta nije u redu sa ovim kodom:
int main()
{
int someVariable = 5;
cout <<“Some variable: “<<someVariable<<endl;
int *pVar =&someVariable;
pVar = 9;
cout << “someVariable: “<<*pVar << endl;
return 0;
}
ETŠ Tuzla, Selma Krajinović
41
Reference
Referenca je alijas – alternativno ime drugog objekta. Kada kreirate referncu, inicjalizujete je imenom drugog objekta – mete. Od tog momenta, referenca se ponaša kao drugo ime tog objekta, te sve što radimo referenci uistinu radimo meti.
Referencu kreiramo navođenjem tipa ciljanog objekta, praćeno operatorom &, poslije čega slijedi ime reference. Npr. ako imamo cjelobrojnu promjenljivu someInt, referencu na tu promjenljivu pravimo naredbom:
int &rSomeRef = someInt;
Ovo se čita kao: “rSomeRef je referenca na cjelobrojnu vrijednost koja je inicijalizovana da pokazuje na
cjelobrojnu promjenljivu someInt“.
Pogledajmo slijedeće naredbe deklaracije:
int Godina;
int &rGodina = Godina;
Šta bi bio efekat ovih naredbi?
Godina = 2000;
cout << Godina;
cout << rGodina;
Na ekranu bi bila ispisana ista vrijednost!
ETŠ Tuzla, Selma Krajinović
42
Područje primjene pokazivača i referenci
Prilikom korištenja funkcija, uočili smo da funkcije imaju dva ograničenja:
1. Argumenti se funkciji predaju po vrijednosti
2. Funkcija može vratiti samo jednu vrijednost
Zašto su to ograničenja?
Argumenti koji se predaju funkciji su lokalni za tu funkciju. Promjene koje se dešavaju nad tim
argumentima u funkciji ustvari ne mijenjaju originalne argumente u funkcije iz koje je pozvana. Ovo je
poznato kao predavanje po vrijednosti, što znaci da se u funkciji pravi lokalna kopija svakog argument.
Korištenjem pokazivača i referenci oba ova ograničenja mogu se prevazići. Korištenjem pokazivača i
referenci, funkcija neće kreirati kopiju objekta već će promjene vršiti nad orginalnim objektom.
U narednom primjeru funkciji Zamjena argumente predajemo po vrijednosti. To znači da de se pozivom
funkcije napraviti lokalne kopije. Funkcija mijenja lokalne kopije, a ne promjenljive iz pozivajuće funkcije.
ETŠ Tuzla, Selma Krajinović
43
Pošto funkcija radi sa kopijama proslijeđenih vrijednost, nakon povratka u funkciju main, vrijednosti x i y
su nepromijenjene.
Ukoliko funkciji proslijedimo adrese promjenljivih tj. pokazivače na promjenljive, onda će funkcija
manipulisati vrijednostima na toj adresi. Ovo rješenje zahtijeva određene izmjene u samoj funkciji,
obratite pažnju. Pošto se funkciji prosljeđuju adrese promjenljivih, dereferenciranjem dolazimo do
njihovih vrijednosti.
Nakon povratka u funkciju main vrijednosti x i y su zamijenjene.
Ipak, ovo rješenje ima odredene nedostatke. Potreba za dereferenciranjem pokazivača čini ga teškim za
čitanje i podložnim greškama. Ovo bismo mogli uraditi i pomoću referenci, kao u listingu koji slijedi:
ETŠ Tuzla, Selma Krajinović
44
Parametri funkcije deklarisani su kao reference, te se stoga mijenjaju i u funkciji main. Pozivajuća
funkcija “razlikuje” da li se parametar predaje po referenci ili po vrijednosti na osnovu prototipa
funkcije.
Prosljeđivanjem parametara kao pokazivača ili referenci rješavamo oba problema:
- funkcija mijenja promjenljive u onoj iz koje je pozvana, umjesto da radi sa lokanim kopijama
tih promjenljivih.
- Istovremeno, rješen je i drugi problem, jer sada funkcija može indirektno, preko
promjenjivih, vratiti više vrijednosti. Npr. U prethodnom primjeru izmjenjene su dvije
vrijednosti, x i y, što se može tumačiti kao vraćanje dvije vrijednosti.
Potvrdimo prethodno i slijedećim primjerom. Program sadrži funkciju koja izračunava kvadrat i kub
zadatog broja.
Prototip funkcije je
int Faktor (int n, int *kvadrat, int *kub);
Dakle, argumetni funkcije su:
n – cjelobrojna promjenljiva,
*kvadrat – pokazivac na cjelobrojnu promjenljivu i
ETŠ Tuzla, Selma Krajinović
45
*kub – pokazivac na cjelobrojnu promjenljivu.
U pozivu funkcije imamo:
greska = Faktor(x, &x2, &x3);
Dakle, proslijeđujemo promjenljivu x i adrese promjenljivih x2 i x3.
Implementacija funkcije je data slijedećim kodom:
Posmatrajmo naredbe:
*kvadrat = n*n; //na adresu koju cuva pokazivac *kvadrat upisujemo kvadrat vrijednosti u promjenljivoj x
*kub = n*n*n; //na adresu koju cuva pokazivac *kub upisujemo kub vrijednosti u promjenljivoj x
Na ovaj način funkcija mijenja dvije vrijednosti koje su dostupne u funkciji iz koje je pozvana. Stoga,
korištenjem pokazivača možemo prevazići problem vraćanja jedne vrijenosti u okviru naredbe return.
5.1 Vježbe 1. Deklarisati funkciju Hex, koja uzima promjenljivu p kao parameter a vraća 8 znakova (heksadecimalni
broj) koji predstavlja sadržaj pokazivača, tj adresu koju on čuva.
void Hex(void* p)
{
cout << hex << setfill('0') << setw(8) << (long) p << ends;
return;
}
Deklarišite cjelobrojne promjenljive x i y, kao i int* pokazivače p i q. Promjenljivoj x dodijelite 2,
promjenljivoj y dodijelite 8, p adresu od x i q adresu od y. Zatim ispišite slijedeće informacije:
Adresu od x i vrijednost x.
Vrijednost p i vrijednost *p.
Adresu od y i vrijednost y.
Vrijednost q i vrijednost *q.
Adresu od p (ne sadržaj!)
ETŠ Tuzla, Selma Krajinović
46
Adresu od q (ne sadržaj!)
Koristite Hex funkciju da biste ispisali vrijednost u pokazivaču.
2. Deklarišite cjelobrojne promjenljive x, y, z kao i int* pokazivače p, q, r. Postavite u x, y, z tri različite
vrijednosti. Postavite u p, q, r adrese promjenljivih x, y, z, respektivno.
Ispišite vrijednosti x, y, z, p, q, r, *p, *q, *r (svakoj vrijednosti prethodi komentar).
Ispišite: “Zamjena vrijednosti”.
Izvršite kod zamjene: z = x; x = y; y = z;
Ispišite vrijednosti x, y, z, p, q, r, *p, *q, *r (svakoj vrijednosti prethodi komentar).
Nacrtajte na papiru šta se dešava sa promjenljivim
ETŠ Tuzla, Selma Krajinović
47
Pokazivači i nizovi
Pokazivače možemo koristiti i za rad sa nizovima. Posmatrajmo primjer slijedećih deklaracija:
char array[10];
char *array_ptr = array;
Prvom naredbom deklarisali smo niz znakova sa maksimalno 10 elemenata. Drugom naredbom
deklarišemo pokazivač array_ptr i inicijalizujemo ga adresom prvog elementa niza. Zadnja naredba
mogla bi se napisati i na slijedeći način:
char *array_ptr = &array[0];
Sada elementima niza možemo pristupati pomoću pokazivača array_ptr: Npr. ovom naredbom
ispisujemo prvi element niza
cout << *array_ptr;
Drugi element niza ispisujemo naredbom
cout << *(array_ptr+1);
Slijedeće naredbe imaju isti efekat:
cout << *array_ptr; isto što i cout << array[0] ; cout << *(array_ptr + 1); isto što i cout << array[1] ;
cout << *(array_ptr + 2); isto što i cout << array[2] ;
Kada deklarišemo niz, za elemente niza rezervišemo susjedne lokacije. Ako pokazivaču dodjelimo adresu
prvog elementa niza, onda ostalim elementima možemo pristupati tako što ćemo manipulisati adresom
prvog elementa – dodavanjem (ili oduzimanjem) cjelobrojne vrijednosti. Izraz *(array_ptr + 2) znači
„uvečaj adresu prvog elemnta za 2“, a efekat je da pokazivač zapravo sadrži adresu trećeg elementa
niza.
Ovo možemo predstaviti grafički, kako slijedi:
Adresa na kojoj je prvi element niza je u pokazivaču array_ptr (0x5000). Trećem elementu niza može se
pristupiti pomoću pokazivača ako mu dodamo vrijednost 2 (array_ptr+2).
array_ptr
0x5000
0x5000
array_ptr+2
0x5002
0x5000
ETŠ Tuzla, Selma Krajinović
48
Primjer 1: Napisati program koji učitava niz od N znakova. Zatim ispisati elemente niza korištenjem
pokazivača.
Za vježbu: Modifikovati prethodni zadatak tako da omogučava da se učita rečenica (dozvoliti unos
razmaka) tako da se izvršavanjem programa može dobiti rezultat kao u drugom primjeru.
Na prvi pogled, ovo izgleda kao komplikovaniji način korištenja jednostavnih nizova. Počet ćemo sa
jednostavnom aritmetikom sa pokazivačima. Poslije ćemo koristiti složenije pokazivače za efikasan rad
sa znatno komplikovanijim strukturama.
Slijedeći program vraća broj elemenata prije prve nule u nizu, inicijalizovanom pri deklaraciji. U nizu
mora biti barem jedna nula. Program se zaustavlja kada naiđe na prvu nulu.
Slijedi rješenje bez pointera.
ETŠ Tuzla, Selma Krajinović
49
Zatim, rješenje pomoću pointera na elemente niza:
Primjer 2
Učitati liniju teksta koja sadrži prezime i ime u slijededoj formi:
Prezime/Ime
(Dakle, ime i prezime su odvojeni znakom “/”). Napisati program koji razdvaja ime i prezime.
Primjer (Izgled ekrana po startovanju programa):
Unesite prezime/ime: Krajinovic/Selma
Prezime: Krajinovic
Ime: Selma
U ovom programu koristit ćemo funkciju strchr. Funkcija vraća pokazivač na poziciju na kojoj se prvi
puta pojavljuje navedeni karakter. Karakter koji označava kraj stringa ¸\n¸ također može da se locira
pomoću ove funkcije.
Format funkcije: char * strchr ( char * str, int character );
Parametri
str je pokazivac na C string.
character je znak cija pozicija se traži. (proslijeđuje se integer vrijednost karaktera, koja se
interno konvertuje u znak)
Povratna vrijednost
Pokazivač na poziciju na kojoj se prvi puta pojavljuje karakter. Ako karakter nije pronađen,
funkcija vraća null pokazivač
ETŠ Tuzla, Selma Krajinović
50
Za rješavanje problema iz zadatka, pomoću funkcije strchr naći ćemo poziciju karaktera “/”. Koristimo
dva pokazivača:
ime_ptr – pokazuje na karakter kojim počinje ime
prezime_ptr – pokazuje na karakter kojim poćinje prezime
Karakter “/” u ulaznom stringu zamijenit ćemo karakterom “\0”. Ova Esc sekvenca označava prelazak u
novi red, što ćemo iskoristiti da ulazni niz ispišemo u dva reda. Pogledajmo grafički prikaz:
Slijedi kod:
ETŠ Tuzla, Selma Krajinović
51
Slijedi objašnjenje za pojedine linije koda
Primjer 3
Učitati prezime i ime u format: Prezime/ime. Ispisati inicijale . Izgled ekrana:
Primjer 4
Napisati program koji učitava riječ i karakter, a zatim funkciju koja ispituje koliko puta se u nekom
stringu pojavljuje neki karakter. U glavnom programu pozvati funkciju i ispisati rezultat.
ETŠ Tuzla, Selma Krajinović
52
Zadaci za vježbu
1. U ulaznoj datoteci “podaci.xls” nalaze se podaci o učenicima:
• Prezime
• Ime
• Adresa
• Grad
• Poštanski broj
Podaci su razdvojeni znakom “;”. Ispisati tekst za naljepnicu na koverti u obliku:
Prezime i ime
Adresa
Grad i postanski broj
2. Napraviti funkciju za spajanje dva stringa u jedan string, drugi se dodaje na početak prvog. Testirati
fju.
ETŠ Tuzla, Selma Krajinović
53
3. Napraviti funkciju za upoređivanje jednog znakovnog niza (stringa) s drugim, vratiti nulu ako su
jednaki, odnosno 1 ako nisu jednaki. Testirati fju.
4. Unesite tekst sa standardnog ulaza, a zatim odredite koliko ima suglasnika u zadanom tekstu.
5. Unesi tekst sa standardnog ulaza, a zatim unesi slovo čiju prvu pojavu u unešenom tekstu tražite. Ako
je slovo pronadeno ispišite njegov položaj u rijeci. Koristite pokazivače.
6. Unesite rečenicu sa standardnog ulaza, a zatim unesite riječ koju tražite u unešenom tekstu. Ako je
riječ pronađena ispišite njen položaj u rečenici. Koristite pokazivače.
ETŠ Tuzla, Selma Krajinović
54
Povezane liste
Za pohranjivanje skupa podataka istoga tipa do sada smo koristili nizove. Neka imamo slijedeće
deklaracije:
struct ucenik
{ char ime[20]; // ime do 20 karaktera
int godine; // godine starosti
float visina; // u metrima
}
ucenik razred[30];
Prethodnim naredbama smo deklarisali strukturu ucenik i niz čiji su elementi tipa strukture ucenik.
Prilikom deklaracije niza moramo navesti maksimalan broj elemenata niza, što predstavlja veliko
ograničenje ove vrste podataka. Naime, ukoliko navedemo veliki broj elemenata, rizikujemo da će
program nepotrebno zauzeti veliki memorijski prostor. Ako navedemo mali broj elemenata, rizikujemo
da program neće zadovoljavati potrebe korisnika. Stoga, potreba dimenzionisanja niza gotovo uvijek
predstavlja problem, jer je nemoguće predvidjeti koliko elemenata niz uistinu ima kada se program
pokrene.
Kao rješenje ovog problema može se koristiti povezana lista. Međutim, svako rješenje ima i
odgovarajuće mane. Jedna od mana povezane liste jeste i to što imaju loše performance kada je u
pitanju slučajan pristup. Naime, povezana lista zahtijeva sekvencijalnu obradu, koja zahtijeva mnogo
vremena za čitanje željene, slučajno odabrane vrijednosti.
Šta je povezana lista? Povezana lista je složena struktura podataka koju čine čvorovi. Čvor, kao osnovni element povezane
liste baziran je na tipu podataka struktura, koja sadrži informacioni dio (za čuvanje podataka) i bar jedan
pointer. Povezanu listu čini lanac čvorova koje međusobno povezuju pointeri.
Postoje jednostruko i dvostruko povezane liste. Jednostruko povezana lista sadrži pokazivač na slijedeći
čvor, a dvostruko povezane sadrži dva pokazivača: jedan pokazuje na slijedeći a jedan na prethodni čvor.
Jednostruko povezanu listu možemo predstaviti ovako:
Info info info info info slijedeći NULL
Dvostruko povezana lista sadrži dva pokazivača u svakom čvoru:
Info info info info info Slijedeći NULL NULL prethodni
ETŠ Tuzla, Selma Krajinović
55
Upoznat ćemo jednostruko povezanu listu. Na slici je primjer jednostruko povezane liste:
START
Ime: Edo
Godine: 34
Visina: 1.7
Ime: Damir
Godine: 27
Visina: 1.2
Ime: Davor
Godine: 48
Visina: 1.4
Ime: Marina
Godine: 30
Visina: 1.3
NULL
Povezana lista na slici sadrži 4 čvora, pri čemu svaki, osim poslednjeg, sadrži pokazivač na slijedeći čvor.
Poslednji čvor umjesto pokazivača na slijedeći čvor, sadrži vezu sa specijalnom vrijednošću NULL, što
označava kraj liste. Postoji još jedan specijalni pokazivač, Start, koji pokazuje na prvi čvor u lancu.
Kako bismo razumjeli šta je uistinu povezana lista, posmatrajmo jednostavan primjer. Učitat ćemo riječ,
a zatim znakove smjestiti u jednostruko povezanu listu, dodavajući slovo po slovo na kraj liste.
Za kreiranje ovakve liste definisat ćemo najprije strukturu podataka:
Prvi element, slovo, sadržat će „korisnu“ informaciju. U ovom primjeru, tu ćemo upisivati slova iz
učitane riječi. Drugi element, slijedeci, je pokazivač na slijedeći element liste. Zadnji čvor imat će
vrijednost NULL u elementu slijedeci.
Koristit ćemo slijedeće pokazivača na ovu strukturu:
- start_ptr, pokazivač na prvi čvor liste. U svakom trenutku, ovaj pokazivač sadržat će
adresu prvog elementa u listi. Na početku, kada je lista prazna, ovaj pokazivač sadrži
vrijednost NULL. Kasnije, kada dodamo prvi čvor u listu, ovdje sačuvamo adresu prvog
čvora. Ne smijemo izgubiti ovu vrijednost, ako se to ipak desi, izgubili smo cijelu listu!
- zadnji, pokazivač na zadnji čvor u listi. Kada dodajemo čvor u listu, koristimo pokazivač
zadnji kako bismo novi čvor uistinu povezali sa listom.
- novi, pokazivač na čvor kojeg dodajemo u listu. Kada dodajemo novi čvor, pomoću ovog
pokazivača alociramo prostor, upisujemo vrijednosti i konačno, povezujemo novi čvor sa
listom.
F
E B R U
A R NULL
ETŠ Tuzla, Selma Krajinović
56
Učitat ćemo riječ u promjenljivu tipa string. Zatim ćemo, slovo po slovo, dodavati čvorove na kraj liste.
Sada ćemo od učitane riječi formirati jednostruko povezanu listu. Najprije ćemo postaviti start_ptr na
NULL vrijednost. Koristit ćemo promjenljivu i za pristup karakterima učitanog stringa, te petlju while u
okviru koje testiramo da li je kraj stringa.
Alociramo memorijske lokacije za novi čvor. U članicu
structure slovo upišemo znak. Pošto se čvor dodaje na
kraj liste, slijedeci postaje NULL (nema više čvorova u
listi).
Provjeravamo da li je ovo prvi čvor. Ako jeste, njegovu
adresu sačuvamo u pokazivaču start_ptr. Ako nije prvi
čvor, upisujemo u zadnji čvor adresu novog. Za tu radnju
koristimo pointer zadnji. Ovim zapravo dodajemo novi
čvor u postojeću listu.
Za čvor kojeg ćemo upisati u nastavku, ovo (novi) će biti
zadnji čvor.
Da bismo provjerili prethodni kod, napisaćemo kod za ispisivanje podataka iz liste.
Pokazivač zadnji pokazivat će na element liste
kojeg ispisujemo. Polazimo od prvog čvora,
čija adresa je u pokazivaču start_ptr. Sve dok
zadnji ne sadrži vrijednost NULL, ispisujemo
slovo i pomjeramo pokazivač zadnji na
slijedeći element liste.
Kada pokrenemo program, dobijemo:
ETŠ Tuzla, Selma Krajinović
57
Zadaci za vježbu:
1. Napisati program koji u povezanu listu upisuje znakove iz učitane riječi u redoslijedu obrnutom u
odnosu na redoslijed učitavanja. Ispisati podatke iz liste. Za ispisivanje liste napraviti funkciju.
2. Napisati program koji učitava cio broj proizvoljnog broja cifara, a zatim cifre broja upisuje u
jednostruko povezanu listu. Ispisati broj iz liste.
Definisanje strukture podataka za povezanu listu Osnova povezane liste je struktura koja čuva podatke za svaki čvor liste (npr. ime, adresa, godine) kao i
pokazivač na slijedeći čvor u listi. Slijedi primjer tipične structure koja se koristi u povezanoj listi
struct cvor
{ char ime[20]; // ime do 20 karaktera
int godine; // godine starosti
float visina; // u metrima
cvor *slijedeci; // Pointer na slijedeći čvor
};
Važan dio ove structure je zadnja linija definicije structure. Ovdje definišemo članicu strukture
slijedeci koja je pointer tipa cvor, tj. strukture koju ovim definišemo. Ovo je jedini slučaj kada je
dozvoljeno da upućujemo na tip podataka kojeg još nisamo definisali (u ovom slučaju cvor).
ETŠ Tuzla, Selma Krajinović
58
cvor *start_ptr;
Prethodnom naredbom deklarišemo pointer start_ptr koji će sadržati pokazivač na prvi čvor liste. Na
početku, kada je lista prazna, tj. nema čvorova, u ovaj pointer postavljamo NULL vrijednost.
Funkcija za kreiranje čvora liste
Za kreiranje novog čvora liste možemo koristiti funkciju koja alocira memorijski prostor, upisuje podatke
i vraća pokazivač na kreirani čvor. S obzirom da funkcija vraća pokazivač, deklarišemo je ovako
cvor *kreiraj_novi_cvor….
Ova funkcija mora vratiti pokazivač, što znači da mora imati naredbu return “pokazivač”.
Funkcija može imati argumente, npr. vrijednosti koje se upisuju u informacioni dio čvora. Slijedi jedan
primjer takve funkcije:
Poziv funkcije realizuje se u naredbi dodjele vrijednosti u kojoj je lijevo od znaka jednakosti pokazivač.
Npr.
Funkcija može biti bez argumenata. U tom slučaju podatke koje upisujemo u informacioni dio čvora
učitavamo unutar funkcije, kao u zadatku na kraju poglavlja.
Dodavanje čvora u listu Prvi zadatak u vezi sa povezanom listom je kako dodati čvor u listu. Novi čvor možemo dodati na
početak, kraj ili unutar liste. Upoznaćemo najprije dodavanje čvora na kraj i početak liste.
U uvodnom primjeru pokazali smo kako formiramo listu unutar while petlje. Sada ćemo napraviti
funkciju za dodavanje čvora na kraj ili početak postojeće liste, koja se može pozivati prema potrebi.
Dodavanje čvora na kraj liste
Dodavanje čvora na kraj liste realizujemo u slijedećim koracima:
1. Deklarišemo promjenljivu tipa structure na kojoj se baziraju čvorovi liste i rezervišemo
memorijski prostor za novi čvor
2. Unosimo podatke u elemente structure čvora
ETŠ Tuzla, Selma Krajinović
59
3. Ako lista nije prazna, onda postojeći zadnji čvor u listi mijenjamo tako što u pokazivač tog čvora
upišemo adresu novog čvora. Time novi čvor uistinu postaje dio liste.
Ako je lista prazna, adresu novog čvora dodjelimo pointeru koji pokazuje na početak liste, start_ptr.
Najprije deklarišemo promjenljivu tipa struktura cvor i rezervišemo memorijski prostor za čvor,
slijedećom naredbom:
cvor *novi = new cvor;
novi
nedefinisano
Zatim, korisnik unosi podatke koje upisujemo u članice promjenljive novi:
cout << "Upisite ime: ";
cin >> novi->ime;
cout << "Upisite godine: ";
cin >> novi->godine;
cout << "Upisite visinu osobe: ";
cin >> novi->visina;
novi->slijedeci = NULL;
U zadnjoj liniji postavljamo NULL vrijednost u članicu strukuture slijedeci, čime iniciramo da će ovaj
čvor, kada ga ubacimo u listu, biti zadnji čvor.
Sada postavljamo vrijednost za pointer start_ptr. Ako je lista prazna, onda samo adresu tmp čvora
podešavamo da pokazuje na novi čvor:
if (start_ptr == NULL)
start_ptr = novi;
Ako u listi već postoje čvorovi, koristimo drugi pointer, pom, i pomjeramo ga na kraj liste:
{
pom = start_ptr;
// postavljamo pom na kraj liste
while (pom->slijedeci != NULL)
{
pom = pom->slijedeci; // pomjeranje na slijedeći čvor
}
pom->slijedeci = novi; // pokazivač zadnjeg čvora u listi
//postavljamo da pokazuje na novi čvor
}
ETŠ Tuzla, Selma Krajinović
60
Petlja će se završiti kada pom sadrži adresu zadnjeg čvora u lancu. U zadnjem čvoru liste slijedeci sadrži
null vrijednost. Kada smo pronašli zadnji čvor, postavljamo slijedeci zadnjeg čvora da pokazuje na čvor
kojeg dodajemo u listu:
pom->slijedeci = novi;
start_ptr
pom
novi
novi
čvor
dodan
NULL
Kompletan kod za dodavanje čvora u listu slijedi:
void dodaj_cvor_na_kraj ()
{ cvor *novi, *pom; // pomoćni pokazivači
// Rezervisanje prostora za novi čvor i unos podataka
novi = new cvor;
cout << "Upisite ime: ";
cin >> novi->ime;
cout << "Upisite godine: ";
cin >> novi->godine;
cout << "Upisite visinu osobe: ";
cin >> novi->visina;
novi->slijedeci = NULL;
// Ubacivanje čvora u listu
if (start_ptr == NULL)
start_ptr = novi;
else
{
pom = start_ptr;
// postavljamo pom na pocetak liste
while (pom->slijedeci != NULL)
{
pom = pom->slijedeci; // pomjeranje na slijedeći čvor
}
pom->slijedeci = novi; // pokazivač zadnjeg čvora u listi postavljamo da pokazuje na novi čvor
}
return;
}
Zadatak
Modifikovati prethodnu funkciju tako da se unutar nje poziva funkcija za kreiranje novog čvora.
ETŠ Tuzla, Selma Krajinović
61
Dodavanje čvora na početak liste
Ovaj postupak je znatno jednostavniji. Nakon kreiranja novog čvora i unosa podataka, potrebno je u novi čvor upisati adresu trenutno prvog čvora u listi (novi->slijedeci = start_ptr), a zatim postaviti u start_ptr adrsu novog čvora (start_ptr = novi). Ako je lista prazna, samo postavimo da start_ptr pokazuje na novi čvor.
void dodaj_cvor_na_pocetak ()
{ cvor *novi, *pom; // pomocni pokazivaci
// Rezervisanje prostora za novi cvor i unos podataka
novi = new cvor;
cout << "Upisite ime: ";
cin >> novi->ime;
cout << "Upisite godine: ";
cin >> novi->godine;
cout << "Upisite visinu osobe: ";
cin >> novi->visina;
novi->slijedeci = NULL;
// Ubacivanje cvora u listu
if (start_ptr == NULL)
start_ptr = novi;
else
{
novi->slijedeci = start_ptr;
start_ptr = novi;
}
return;
}
Zadatak za vježbu: 1. Modifikovati uvodni zadatak, tako da se slova iz učitane riječi upisuju na početak liste.
Na ovaj način, učitana riječ treba da bude upisana u obrnutom redoslijedu. Ispisati elemente liste.
2. Napisati program koji učitava cio broj proizvoljnog broja cifara, a zatim cifre broja upisuje u
jednostruko povezanu listu. Čvorove dodavati na početak liste.
3. Prethodni zadatak može se riješiti korištenjem funkcija. Slijedi kompletan kod.
ETŠ Tuzla, Selma Krajinović
62
ETŠ Tuzla, Selma Krajinović
63
Pristup podacima u listi Slijedeći problem kojeg treba riješiti je kako pristupati elementima liste. Pokazaćemo kako možemo
čitati podatke iz liste i ispisivati ih na ekranu.
Uradit ćemo slijedeće:
Pomoćni pointer postavljamo da pokazuje na prvi čvor, tj. dodjeljujemo mu vrijednosrt startnog
pointera (start_ptr).
Ako pomoćni pointer sadrži null vrijednost, lista je prazna pa prikazujemo poruku: "Kraj liste" i
zaustavljamo prikaz.
Ako pomoćni pointer ne sadrži null vrijednost, prikazujemo detalje iz čvora na koji pokazuje
pomoćni pointer.
Mijenjamo vrijednost pomocnog pointera, dodjeljujući mu vrijednost iz pointera “slijedeci”
čvora čiji smo sadržaj upravo ispisali.
Vraćamo se na drugi korak.
Slijedi kod za ispisvanje podataka iz liste:
void ispisi_listu()
{
cvor *pom = start_ptr;
do
{
if (pom == NULL)
cout << endl<<"Kraj liste" << endl;
else
{ // Ispis detalja iz čvora na koji pokazuje pom pointer
cout << "Ime: " << pom->ime << endl;
cout << "Godina: " << pom->godine << endl;
cout << "Visina: " << pom->visina << endl;
cout << endl;
// Pomjeranje na slijedeći čvor
pom = pom->slijedeci;
}
}
while (pom != NULL);
return;
}
Brisanje čvora Čvor može da se nalazi na početku, kraju i u sredini liste. Ovisno o njegovoj poziciji, postupak brisanja je
drugačiji.
Kada obrišemo čvor, potrebno je osloboditi memorijski prostor. Ako to ne uradimo, rizikujemo “out of
memory”! Oslobađanje memorijskog prostora realizujemo naredbom delete:
delete pom;
ETŠ Tuzla, Selma Krajinović
64
Međutim, ne možemo samo obrisati čvor iz liste, jer bismo u tom slučaju prekinuli lanac. Stoga, najprije
moramo izmjeniti vrijednost odgovarajućeg pokazivača pa onda obrisati čvor.
Evo kako bismo obrisali prvi čvor iz liste.
pom = start_ptr; // Sacuvamo startni pointer u pomocnom
start_ptr
etc.
pom
Nakon što smo sačuvali vrijednost startnog pointera u pom pointer, mijenjamo vrijednost start_ptr tako
da pokazuje na slijedeći čvor:
start_ptr = start_ptr->slijedeci; // drugi cvor u lancu
start_ptr
etc.
pom
delete pom; // obrisi pocetni start cvor
start_ptr
ETŠ Tuzla, Selma Krajinović
65
etc.
pom
Slijedi funkcija za brisanje startnog čvora:
void brisi_prvi_cvor()
{ cvor *pom;
pom = start_ptr;
start_ptr = start_ptr->slijedeci;
delete pom;
return;
}
Brisanje čvora na kraju liste je teže, jer se pomoćni pointer mora najprije pomjeriti na kraj liste (kao kod
unosa novog čvora). Potrebna su dva pomoćna pointera, pom1 i pom2. Prvi će pokazivati na zadnji čvor
u listi, a drugi na njegovo prethodnika. Potrebne su nam obje vrijednosti kako bismo zadnji obrisali, a
predzadnji modifikovali tako da on u polju slijedeći sadrži null vrijednost, pokazujući na taj način da je
zadnji čvor liste.
Prikažimo proces brisanja zadnjeg čvora crtežima. Posmatrajmo listu. Najprije ćemo postaviti oba
pomoćna pokazivača, pom1 i pom2, da pokazuju na početak liste.
start_ptr
NULL
pom1 pom2
Zatim , pom1 pomjeramo na slijedeći čvor u listi:
start_ptr
ETŠ Tuzla, Selma Krajinović
66
NULL
pom2
pom1
Pošto pom1 još uvijek ne pokazuje na zadnji čvor u listi, pomjeramo i pom2, tako da pokazuje isti čvor
kao i pom1
start_ptr
NULL
pom2 pom1
Opet pomjeramo pom1 na slijedeći:
start_ptr
NULL
pom2
pom1
Ovo ponavljamo sve dok pom1 ne pokazuje zadnji čvor u listi, a pom2 na njegovog prethodnika:
ETŠ Tuzla, Selma Krajinović
67
start_ptr
NULL
pom2
pom1
Zatim brišemo čvor na kojeg pokazuje pom1
start_ptr
pom2
pom1
Zatim u pokazivač slijedeci čvora na kojeg pokazuje pom2 upisujemo NULL vrijednost:
start_ptr
NULL
pom2
Ako lista sadrži samo jedan čvor, onda samo treba postaviti start_ptr na null vrijednost i obrisati čvor.
Slijedi kod za brisanje čvora na kraju liste:
void brisi_zadnji_cvor()
{
ETŠ Tuzla, Selma Krajinović
68
cvor *pom1, *pom2;
if (start_ptr == NULL)
cout << "Lista je prazna!" << endl;
else
{
pom1 = start_ptr;
if (pom1->slijedeci == NULL)
{
delete pom1;
start_ptr = NULL;
}
else
{
while (pom1->slijedeci != NULL)
{
pom2 = pom1;
pom1 = pom1->slijedeci;
}
delete pom1;
pom2->slijedeci = NULL;
}
}
return;
}
Navigacija kroz listu Za rad sa povezanom listom, potrebno je uspostaviti mehanizam kretanja po listi, unaprijed ili unazad.
Ovo je naročito potrebno aki želimo brisati ili upisivati čvor unutar liste.
Deklarišimo pointer tekuci. Najprije mu dodjeljujemo adresu prvog čvora u listi, koju čuvamo u pointeru
start_ptr :
cvor *tekuci;
tekuci = start_ptr;
Nakon ovih naredbi oba pointera pokazuju na isti čvor:
start tekuci
itd
Pomjeranje pointera tekuci unaprijed realizujemo naredbom u kojoj pointeru tekuci dodjeljujemo
adresu cvora koji slijedi, a koja je upisana u članicu slijedeci čvora na kojeg tekuci pokazuje:
tekuci = tekuci->slijedeci;
ETŠ Tuzla, Selma Krajinović
69
Prije prethodne naredbe dodjele, potrebno je provjeriti da tekući u polju slijedeći ne sadrži null
vrijednost. Ako je to tako, onda tekuci pokazuje na zadnji čvor u list ii nema potrebe za njegovim
pomjeranjem.
if (tekuci->slijedeci == NULL)
cout << "Pozicionirani ste na kraj liste." << endl;
else
tekuci = tekuci->slijedeci;
Pomjeranje pointera unazad je nešto teža rutina. Jedini način da nađemo prethodni čvor jeste da
krenemo od početnog i pomjeramo pokazivač do čvora kojeg tražimo. To će se desiti kada pointer
slijedeci pokazuje na tekući čvor.
Pomoć!!!
Pokušajmo sa slikama:
Najprije ćemo provjeriti da li pointer tekuci (na slici current) pokazuje na prvi čvor. Ako je tako, onda on
nema prethodnika. Ako nije, onda provjeravamo sve čvorove dok ne naiđemo na prethodnika tekućeg.
if (tekuci == start_ptr)
cout << "Pocetak liste!" << endl;
else
{ cvor *prethodni; // pointer koji pokazuje na prethodnika
prethodni = start_ptr;
while (prethodni->slijedeci != tekuci)
{
prethodni = prethodni->slijedeci;
}
tekuci = prethodni;
}
Kod koji je naveden iza else određuje slijedeće:
Najprije deklarišemo pointer koji će pokazivati na prethodni čvor – pointer prethodni.
U prethodni postavljamo adresu prvog čvora.
Sve dok ne pokazuje na čvor koji prethodi tekućem, mijenjamo adresu u pointeru prethodni tako
da pokazuje na slijedeći čvor.
Kada pronađemo prethodnika u odnosu na tekući, pointer tekuci postavljamo da pokazuje na isti
čvor kao i pointer prethodni, kojeg smo „doveli“ do njegovog prethodnika
prethodni slijedeci
ETŠ Tuzla, Selma Krajinović
70
Sada kada možemo da se “krećemo” unaprijed i unazad kroz listu, možemo uraditi još ponešto sa listom.
Naprimjer, možemo mijenjati podatke u čvoru liste na koji pokazuje tekuci:
cout << "Unesite novo ime: "; cin >> tekuci->ime; cout << "Unesite novi podatak o godinama : "; cin >> tekuci->ime; cout << "Upisite novi podatak o visini : "; cin >> tekuci->visina;
Slijedeća procedura je brisanje čvora koji se nalazi odmah iza čvora na kojeg pokazuje pokazivač tekuci.
Koristit ćemo pomoćni pokazivač koji će pokazivati na čvor kojeg želimo obrisati – pom (na slici temp).
Nabrojat ćemo šta treba uraditi da bismo obrisali čvor.
Najprije, podesimo da pomoćni pokazivač pokazuje na čvor iza tekućeg, tj. na čvor kojeg ćemo obrisati:
Zatim podešavamo da pointer u tekućem čvoru sadrži adresu čvora koji slijedi iza onog na kojeg
pokazuje pomoćni:
Zadnji korak je brisanje čvora na kojeg pokazuje pomoćni.
Slijedi kod za brisanje čvora iza tekućeg. Ovaj kod uključuje i provjeru da li je tekući zadnji u listi.
if (tekuci->slijedeci == NULL) cout << "Nema vise cvorova u listi" << endl; else { cvor *pom; pom =tekuci->slijedeci; tekuci->slijedeci = pom->slijedeci; delete pom; }
tekuci pom
tekuci pom
ETŠ Tuzla, Selma Krajinović
71
Slijedi kod za dodavanje čvora iza tekućeg.
if (tekuci->slijedeci == NULL) dodaj_cvor_na_kraj(); else { cvor *novi; new novi; upisi_podatke_u_cvor(novi); // Postavi da novi cvor pokazuje na isti cvor kao i tekuci novi->slijedeci = tekuci->slijedeci; // Tekuci pokazuje na novi tekuci->slijedeci = novi; }
Funkcija dodaj_cvor_na_kraj() je ranije deifinisana. Funkcija upisi_podatke_u_cvor(novi) omogućava unos
podataka u strukturu čvor.
U slijedećem primjeru primjenićemo ove procedure i pokazati kako se implementiraju i neke dodatne
funkcionalnosti povezane liste.
Primjer programa za rad sa jednostruko povezanom listom Napisati program koji omogučava formiranje liste koja sadrži koeficijente kvadratne jednačine. Nakon
startovanja programa, prikazati glavni meni sa slijedećim opcijama:
Za pohranjivanje podataka program koristi strukturu „cvor“, kako slijedi:
ETŠ Tuzla, Selma Krajinović
72
Opcija 5, „Sekvencijalna obrada liste“, nudi dodatni meni za pojedinačnu obradu čvorova liste.
Omogućava sekvencijalni prolazak kroz listu, gdje se za svaki čvor nude slijedeće opcije:
Svaka od opcija glavnog menija i menija za sekvencijalnu obradu podataka realizuje se kao zasebna
funkcija. I sam meni komandi je relizovan kao funkcija koja se poziva u funkciji main, kao na screenshot-
u koji slijedi.
Program je realizovan kroz slijedeće funkcije:
ETŠ Tuzla, Selma Krajinović
73
Glavni meni poziva se u funkciji main, gdje se, nakon povratka iz menija, u okviru switch naredbe poziva
odgovarajuća funkcija:
ETŠ Tuzla, Selma Krajinović
74
Glavni meni implementiran je na slijedeći način:
ETŠ Tuzla, Selma Krajinović
75
Dodavanje čvora na početak liste već je objašnjeno:
Kako bi program bio funkcionalan, samo kreiranje novog čvora realizovano je u zasebnoj, pomoćnoj
funkciji „kreiraj_novi_cvor“ koja se poziva u prethodnoj, ali i u okviru drugih funkcija programa.
ETŠ Tuzla, Selma Krajinović
76
Ova funkcija vraća pokazivač na čvor. Kao tip povratne vrijednosti navodimo strukturu „cvor“, a ispred
imena funkcije znak *, kako bismo odredili da funkcija vraća pokazivač na čvor.
Prednost ovakvog pristupa je što istu funkciju možemo koristiti na više mjesta u programu. S druge
strane, prednost je i u tome što istu metodologiju možemo koristiti i u drugim zadacima – jedino što
treba da prilagodima je struktura čvora u funkciji kreiraj_novi_cvor (isto i u ispisi_cvor).
Vec u slijedećoj funkciji opet koristimo funkciju „kreiraj_novi_cvor“
Za potrebe ispisivanja liste također koristimo pomoćnu funkciju za ispisivanje sadržaja jednog čvora.
ETŠ Tuzla, Selma Krajinović
77
Argument ove funkcije je pokazivač sa fiktivnim imenom „tekuci“. On pokazuje na čvor čiji sadržaj želimo
ispisati .
Funkciju „ispisi_cvor“ koristimo u funkciji za ispisivanje liste od prvog do zadnjeg čvora, čiji algoritam
smo već objasnili.
Funkciju „ispisi_cvor“ koristimo i u funkciji za ispisivanje liste od zadnjeg ka prvom čvoru. Ova funkcija
radi na slijedeći način. Ako lista nije prazna i ako ne sadrži samo jedan čvor, koristimo dva pomoćna
pokazivača. Pom1 na početku funkcije pomjerimo na zadnji čvor u petlji i ispišemo njegov sadržaj:
Sve dok pom1 ne bude imao istu adresu kao i start_ptr, radimo slijedeće:
- pokazivač pom2 pozicioniramo na čvor koji prethodi čvoru pom1
- pokazivač pom1 pomjerimo na prethodni čvor i ispišemo njegov sadržaj
ETŠ Tuzla, Selma Krajinović
78
Slijedi kompletan kod ove funkcije:
Brisanje čvora na početku i kraju liste također je objašnjeno ranije. Slijedi kod ovih funkcija:
ETŠ Tuzla, Selma Krajinović
79
Sekvencijalna obrada liste realizuje se pomoću funkcije „sekvencijalna_obrada“. 1 U okviru ove funkcije
prolazimo kroz listu, od prvog do zadnjeg čvora, tako što mijenjamo vrijednost pokazovača „tekuci“.
Nakon svakog pomjeranja, prikazujemo sadržaj čvora i prikazujemo pomoćni meni iz kojeg korisnik bira
odgovarajuću akciju.
Koristi se i pomoćni pokazivač „pom“ u kojeg spremimo kopiju vrijednosti polja „slijedeci“ iz tekućeg
čvora. Ova vrijednost (adresa slijedećeg čvora) nam je potrebna u slučaju da korisnik izabere brisanje
tekućeg čvora. Ako ne bismo imali kopiju adrese slijedećeg čvora, nakon brisanja tekućeg čvora lista bi
bila prekinuta i ne bismo se mogli referencirati na slijedeći čvor (koji nakon izvršene operacije postaje
tekući).
1 Sekvencijalni pristup (engl. sequential access) je način pristupa podacima pri čemu su podaci na raspolaganju u
određenom poretku, a vrijeme pristupa podacima je zavisno o količini pohranjenih podataka i fizičkom smještaju podataka. Npr. magnetna traka ima sekvencijalni pristup podacima. Da bi se došlo do podatka koji je smješten na nekom dijelu trake, potrebno je pročitati cjelokupan sadržaj trake od mjesta na kome se nalazi magnetska glava pa sve do mjesta gdje se nalazi traženi podatak (ili premotati trake uz poznato mjesto na kome se nalazi traženi podatak). U svakom slučaju ispred glave za čitanje moraju proći svi podaci između trenutnog položaja glave i mjesta na kome se nalazi podatak. Kod direktnog pristupa, podacima se pristupa direktno bez potrebe čitanja prethodnih vrijednosti. Ovo je moguće zahvaljujući uspostavljanju ključa. Kad su u pitanju magnetski mediji, hard drive je primjer medija sa direktnim pristupom.
ETŠ Tuzla, Selma Krajinović
80
Za svaki čvor iz liste prikazuje se pomoćni meni sa opcijama rasploživim nad odabranim čvorom:
Ista funkcija sadrži switch naredbu u okviru koje pozivamo odgovarajuću funkciju za sekvencijalnu
obradu:
ETŠ Tuzla, Selma Krajinović
81
Funkcija za izmjenu tekućeg čvora jednostavno mijenja upisane podatke:
Dodavanje čvora prije tekućeg realizuje se tako što se najprije provjeri dali je tekući prvi čvor liste. Ako
jeste, pozivamo funkciju za dodavanje čvora na početak liste. Ako tekući nije prvi čvor, onda:
- kreiramo novi čvor pozivom funkcije „kreiraj_novi_cvor“
- pomoćni pokazivač „prethodni“ postavimo da pokazuje na čvor prije tekućeg, a zatim
o podesimo da u prethodnom čvoru polje slijedeći pokazuje na novi čvor
o podesimo da u novom čvoru polje slijedeći pokazuje na tekući
ETŠ Tuzla, Selma Krajinović
82
Dodavanje čvora prije tekućeg realizujemo na slijedeći način.
A) Ako je lista prazna, pozivamo funkciju za dodavanje čvora na pocetak liste
B) Ako lista nije prazna:
a. Kreiramo novi čvor pozivamo funkciju kreiraj_novi_cvor(),
b. podešavamo da pokazivač u čvoru koji prethodi tekućem pokazuje na novi čvor, a
pokazivač u novom čvoru pokazuje na tekući
novi
prethodni novi
tekuci
ETŠ Tuzla, Selma Krajinović
83
Brisanje čvora poslije tekućeg realizuje se u slijedećoj funkciji:
Čvor prije tekućeg brišemo pomoću funkcije:
ETŠ Tuzla, Selma Krajinović
84
Konačno, snimanje podataka iz čvorova povezane liste realizuje se u funkciji kako slijedi:
Npr. pozivom ove funkcije kreirana je datoteka
Podaci iz jednog čvora upisuju se u jedan red sa razmacima između pojedinih vrijednosti. Osim za prvi
čvor, prije upisa podataka iz čvora, u datoteku se upisuje znak za novi red:
if (pom != start_ptr) Izlaz << endl;
Čitanje podataka iz datoteka u listu realizuje funkcija:
ETŠ Tuzla, Selma Krajinović
85
Sve dok nije kraj datoteke (!Ulaz.eof()), kreiramo novi čvor i u njega upisujemo podatke pročitane iz
datoteke:
Zadaci za vježbu 1. Napisati program koji omogućava unos podataka o proizvoljnom broju učenika. Za svakog
učenika treba upisati slijedeće podatke:
a. Redni broj, cio broj
b. Prezime i ime, string
c. Broj bodova, cio broj
d. Ocjena, cio broj (1-5)
Nakon unosa podataka o jednom učeniku, provjeriti da li je potreban nastavak unosa, tj.
Postaviti pitanje: „Nastavak? (D/N)“.
Ispisati učitane podatke, tako što podatke o jednom učeniku ispisujemo u jednoj liniji. Koristiti
povezanu listu.
2. Modifikovati zadatak 1 dodavanjem menija iz kojeg korisnik može izarbrati slijedeće opcije:
a. Unos novog čvora, sa podacima redni broj i prezime i ime
i. Na početak liste
ii. Unutar liste, sa ažuriranjem postojećih rednih brojeva
ETŠ Tuzla, Selma Krajinović
86
1. Prije zadanog rednog broja
2. Poslije zadanog rednog broja
iii. Na kraj liste
b. Unos broja bodova:
i. za sve ucenike u listi
ii. Za odabranog učenika, na osnovu rednog broja
c. Brisanje učenika sa zadanim rednim brojem
d. Unos kriterija za ocjenjivanje u formi
i. Ocjena 1: do ___ bodova
ii. Ocjena 2: od ____ do ____ bodova
iii. Ocjena 3: od ____ do ____ bodova
iv. Ocjena 4: od ____ do ____ bodova
v. Ocjena 5: od ____ do ____ bodova
e. Ispisivanje ocjena učenika
i. Svi učenici
ii. Odabrani učenik, zadavanjem rednog broja
f. Ispisivanje rang liste po broju bodova
g. Upisivanje liste u datoteku
h. Učitavanje liste iz datoteke
3. Napisati program koji omogučava unos podataka u povezanu listu. Svaki čvor sadrži prezime i
me učenika i broj osvojenih bodova. Prilikom unosa učenika, automatski se vrši sortiranje
podataka u opadajču listu pr broju osvojenih bodova. Nakon unosa ispisati listu sa kolonama:
prezime ii me, broj bodova.
4. Napisati program koji nudi iste opcije kao i primjer 1, samo što se u čvorovima liste čuvaju
podaci o vrijednostim tri otpora R1, R2 i R3. Prilikom ispisa podataka iz liste izračunava se i
ispisuje ukupan otpor ako su otpornici spojeni serijski i paralelno.
5. Napisati program koji omogućava formiranje liste (dodavanje čvora na početak i kraj) kao i
ispisivanje liste od prvog do zadnjeg čvora. Napraviti funkciju koja nalazi najveći element u
čvoru. Ova funkcija vraća vrijednost koja se traži a kao argument uzima pokazivač na prvi čvora
liste. Čvor sadrži samo dva elementa: cio broj i pokazivač.
6. Napisati program koji omogućava formiranje liste (dodavanje čvora na početak i kraj) kao i
ispisivanje liste od prvog do zadnjeg čvora. Napraviti funkciju koja od podataka u listi formira niz,
a zatim ispisuje taj niz sortiran u rastućem redoslijedu. Funkcija nema argumenata i ne vraća
nikakvu vrijednost. Čvor sadrži samo dva elementa: cio broj i pokazivač.
7. Napraviti funkciju za sortiranje liste.
ETŠ Tuzla, Selma Krajinović
87
Zadaci za ponavljanje
POVEZANE LISTE, vježba 1 (osnovni pojmovi, deklaracija, kreiranje liste)
1. Šta je povezana lista?
2. Čvor povezane liste sadrži dva dijela. Navedi ih i opiši.
3. Nacrtaj kako izgleda jednostruko povezana lista
4. Nacrtaj kako izgleda dvostruko povezana lista
5. Potrebno je formirati jednostruko povezanu listu koja u informacionom dijelu ima podatke o
pravouglom trouglu. Čuvaju se dužine dvije stranice trougla a i b kao cijeli brojevi. Deklariši
strukturu cvor koja će omogučiti rad sa ovakvom listom.
6. Šta označava konstanta NULL i kako se koristi u povezanoj listi?
7. Koji je značaj pointera koji pokazuje na početak liste? Opiši ovaj pointer i njegov značaj.
8. Ako je deklarisana struktura cvor (kao u zadatku 5) koja će se koristiti za kreiranje jednostruko
povezane liste, napiši naredbu kojom se deklariše pointer koji će pokazivati na početak liste
(start_ptr), kao i pointer novi, pomoću kojeg ćemo dodavati čvorove u listu.
9. Napiši naredbu kojom će se alocirati memorijski prostor za novi čvor liste. Koristiti pokazivač
novi.
10. Prikaži grafički efekat naredbe iz zadatka 9, pod pretpostavkom da je lista prazna. Ucrtaj
pokazivače start_ptr i novi, kao i čvor(ove) liste.
11. Prikaži grafički efekat naredbe iz zadatka 9, pod pretpostavkom da lista nije prazna. Ucrtaj
pokazivače start_ptr i novi, kao i čvor(ove) liste.
12. Napisati naredbu kojom se u informacioni dio čvora za koji je u naredbi iz zadatka 9 alociran
memorijski prostor upisuju podaci. Pretpostavka je da se podaci nalaze u cjelobrojnim
promjenljivim v_a i v_b.
13. Deklarisati pokazivač zadnji, koji će pokazivati na kraj liste.
14. Napisati if naredbu kojom se provjerava da li je lista prazna. Ako jeste, onda zadati naredbu
kojom se određuje da start_ptr pokazuje na novi cvor (pointer novi), a ako nije onda podesiti da
postojeći zadnji čvor pokazuje na novi. Prikazati grafički oba slučaja.
15. Napisati naredbu kojom se određuje da pokazivač zadnji pokazuje na isti čvor na koji pokazuje i
novi.
16. Pretpostavimo da imamo formiranu slijedeću listu
NULL
Za ispisaivanje podataka u listi koristi se slijedeći kod:
cout <<"Podaci upisani u listu su "<<endl;
zadnji = start_ptr;
while (zadnji != NULL)
42
1 2
42
22
32
ETŠ Tuzla, Selma Krajinović
88
{
cout << zadnji->a << zadnji->b;
zadnji = zadnji->slijedeci;
}
Predstaviti grafički kako će se izvršavati ovaj kod na prethodnom primjeru. Prikazati na koji čvor
pokazuju pokazivači start_ptr i zadnji, te koje vrijednosti se ispisuju.
Grafički prikaz povezane liste je grupisan u jedan grafički objekat, pa se može kopirati slijedeći
element.
Koristiti slijedeći obrazac:
1. Nakon naredbe zadnji = start_ptr, pokazivač start_ptr pokazuje na prvi čvor liste, kao na slici:
Start_ptr
2.
3.
4.
2. Prvi prolazak kroz petlju while
Start_ptr Zadnji ????
ISPIS:......
42
1 2
42
22
32
42
1 2
42
22
32
42
1 2
42
22
32
ETŠ Tuzla, Selma Krajinović
89
Vježba 2
Potrebno je napraviti program koji omogučava
praćenje prevoza putnika i tereta korištenjem
povezane liste.
Voz čine vagoni različite namjene:
- Lokomotiva
- Kupe
- Teretni
- Restoran
Za svaki vagon treba upisati slijedeće podatke, ovisno o namjeni vagona:
- Namjena (lokomotiva,kupe,teretni,restoran)
- Broj ukrcanih putnika (popunjava se ako je namjena vagona kupe)
- Težina utovarene robe (popunjava se ako je namjena vagona teretni)
- Broj stolova (popunjava se ako je namjena vagona restoran)
- Broj stolica (popunjava se ako je namjena vagona restoran)
Ako je namjena vagona lokomotiva, upisuje se samo polje namjena.
Maximalan broj putnika vagona tipa kupe je 20. Maksimalna težina tereta koji se može utovariti u
teretni vagon je 5 tona. Voz može imati samo jedan vagon-restoran.
Potrebno je napraviti program koji omogučava evidentiranje broja putnika i utovarenog tereta,
dodavanje i isključivanje vagona.
Prema potrebi, omogučiti dodavanje ili isključivanje vagona u/iz voza, na kraj voza prije ili poslije
određenog vagona.
Isključivanje vagona iz voza uraditi automatski kada se desila jedna od slijedećih promjena:
- Broj ukracanih putnika postaje nula
- Težina utovarene robe postaje nula
Dodavanje putničkog vagona uraditi automatski ako je u svim kupe vagonima maksimalan broj putnika.
Omogučiti ispisivanje podataka o putnicima i teretu koji su trentuno u vozu.
ETŠ Tuzla, Selma Krajinović
90
1. Kreirati strukturu podataka koja će se koristiti za pohranjivanje podataka o vagonu.
2. Napisati naredbu kojom se deklariše pokazivač „lokomotiva“ koji će se koristiti kao pokazivač na
prvi vagon voza – lokomotivu.
lokomotiva
3. Napisati naredbe kojima se kreiraju i povezuju čvorovi voza. Čvorove dodavati postpno, u tri
koraka: najprije dodati lokomotivu, zatim teretni vagon i na kraju putnički. Upisati kod i na slici
obilježiti na što pokazuju korišteni pokazivači
lokomotiva
4. Napisati kompletan program koji će kreirati podatke o vozu kao na slici na prethodnoj strani. Voz
čine lokomotiva, jedan putnički vagon čiji broj putnika upisuje korisnik i jedan teretni vagon bez
tereta. Ispisati podatke o ovom vozu.
5. Napisati funkciju koja ispisuje podatke o vagonu u odgovarajućoj formi. Argument funkcije je
pokazivač na čvor čiji podaci se ispisuju. Modifikovati program iz prethodnog zadatka tako što se
ispisivanje podataka o vozu vrši korištenjem ove funkcije.
6. Napisati kod koji na kraj voza dodaje novi vagon. Obilježiti na slici pokazivače koji se koriste da
bi se dodao čvor na kraj voza.
ETŠ Tuzla, Selma Krajinović
91
7. Napisati kod za dodavanje novog vagona odmah iza lokomotive. Obilježiti na slici pokazivače koji
se koriste da bi se dodao čvor na željenu poziciju.
8. Napisati kod za brisanje zadnjeg vagona . Obilježiti na slici pokazivače koji se koriste za ovu
operaciju. Nakon brisanja voz treba izgledati ovako.
9. Napisati kod za brisanje drugog vagona. Obilježiti pokazivače. Nakon brisanja voz treba izgledati
ovako.
10. Napisati funkciju koja omogučava kreiranje novog čvora u kojeg se upisuju podaci o vagonu.
Funkcija treba da vrati pokazivač na novi vagon.
11. Za svaku od operacija iz zadataka 6-9 napisati odgovarajuću funkciju i program koji je testira.
12. Napraviti kompletan program na osnovu zadanog projektnog zadatka definisanog na prvoj
strani.
Koristiti meni komandi koji treba da sadrži slijedeće opcije:
ETŠ Tuzla, Selma Krajinović
92
1. Dodavanje vagona
1.1 Lokomotiva
1.2 Putnički vagon
1.3 Teretni vagon
1.4 Restoran
A. Na kraj voza
B. Poslije lokomotive
C. Poslije restorana
D. Prije restorana
2. Ispisivanje podataka o vozu
2.1 Ispisivanje podataka o svim vagonima
2.2 Ispisivanje ukupnog broja putnika i tereta u vozu
2.3 Ispisivanje broja putnika po vagonima
2.4 Ispisivanje tereta po vagonima
3. Pretraživanje voza i izmjena podataka
3.1 Pronalaženje prvog vagona u kome ima x slobodnih mjesta; dodavanje x putnika
3.2 Pronalaženje prvog vagona u koji se može utovariti x kg robe, dodavanje x kg robe
4. Brisanje vagona
4.1 Brisanje zadnjeg vagona
4.2 Brisanje svih vagona koji imaju 0 putnika
4.3 Brisanje svih vagona koji su natovareni sa 0 kg tereta
4. 4 Brisanje restorana
5. Upisivanje podataka o vozu u datoteku
6. Učitavanje podataka o vozu iz datoteke
ETŠ Tuzla, Selma Krajinović
93
MODUL 3: KLASE i OBJEKTI
ETŠ Tuzla, Selma Krajinović
94
Uvod: Proceduralno i Objektno
Programiranje
Trip to Objectville2 U dosadašnjim programima, sav programski kod upisivali smo unutar funkcije main(). U prethodnom
modulu naučili smo kako sami možemo praviti tip podataka (strukturu), kako dinamički koristimo
memorijski prostor (pokazivači, povezane liste), ali nismo razvili ni jedan korisnički tip objekta. Sve
dosadašnje metode razvoja programa označavamo kao procedurealno programiranje.
Sada ćemo napustiti svijet proceduralnog programiranja i započeti korištenje objekata koje ćemo sami
kreirati. Upoznat ćemo pojmove klasa i objekat i naučiti ih razlikovati.
Chair Wars (ili kako objekti mogu promijeniti tvoj život)
Jednom davno, u prodavnici software-a radila su dva programera kojima
je data specifikacija i rečeno „Napravite to!“. Zaista neugodan vođa
projekta obećao je developeru koji prvi riješi problem dati „Aeron“ stolicu
koju imaju svi developeri u silikonskoj dolini. Larry, proceduralni
programer, i Brad, OO guy, oba su znala da je ovaj zadatak „mačiji kašalj“.
Larry je, sjedeći u svojoj „kutiji“ (cube), razmišljao o slijedećem: „Šta
program treba da radi? Koje procedure (funkcije) treba?“. I odgovorio je
sebi: „rotacija i emitujZvuk (rotate and playSpund)“. Onda je otišao i
počeo pisati funkcije. Na kraju, šta je program ako nije gomila procedura?
U međuvremenu, Brad se vratio u kafić i razmišljao: „Koje su stvari u ovom
programu... ko su ključni igrači?“. Najprije je razmišljao o oblicima (Shapes).
Naravno, razmišljao je i o drugim objektima, kao što su korisnici (Users),
zvukovima (Sounds) i događaju „click“. Ali već je imao bibilioteku sa kodom
za ove elemente programa, pa se fokusiorao na pravljenje objekta.
Čitajte dalje kako su Brad i Larry pravili program i ko je dobio stolicu....
Ideja za uvod i dijelovi teksta preuzeti iz knjige „Head First Java“, O Relly, Katty Sierra, Bert Bates
Upozorenje: kada jednom uđete u „Objectville“, nikada se nećete vratiti nazad. Pošalji razglednicu.
ETŠ Tuzla, Selma Krajinović
95
In Larry's cube Kao što je to uradio milion puta do sada, Larry je pravio važne procedure. Za tren je napisao kod za procedure rotate i playSound.... rotate (shapeNum)
{
// okretanje oblika ya 360 stepeni
}
playSo (shapeNum)
{
// koristiti shapeNum za izbor zvuka
kojeg treba emitovati
}
At Brad's laptop at the cafe Brad je napisao klasu za svaki od tri oblika....