Professional Documents
Culture Documents
Selma Krajnovi Programiranje 3 Skripta PDF
Selma Krajnovi Programiranje 3 Skripta PDF
PROGRAMIRANJE 3
1
ETŠ Tuzla, Selma Krajinović
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.
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
Vektore možemo označavati i s malim štampanim slovima a,b,x, ili s masnim slovima, a,b,x.
3
ETŠ Tuzla, Selma Krajinović
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.
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.
4
ETŠ Tuzla, Selma Krajinović
5
ETŠ Tuzla, Selma Krajinović
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
Ako izostavimo zadnji red u inicijalizaciji, elementima niza u zadnjem redu biće dodijeljene nule
6
ETŠ Tuzla, Selma Krajinović
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
7
ETŠ Tuzla, Selma Krajinović
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
8
ETŠ Tuzla, Selma Krajinović
Rješenje 2
9
ETŠ Tuzla, Selma Krajinović
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.
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.
10
ETŠ Tuzla, Selma Krajinović
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
Npr. neka je zadana matrica A formata 3x4 i B formata 4x5 sa elementima kao na slici
11
ETŠ Tuzla, Selma Krajinović
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.
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.
12
ETŠ Tuzla, Selma Krajinović
Transponovana matrica
Transponovana matrica matrice A je matrica AT kod koje su kolone i redovi zamijenili mjesta.
Primjer 5
13
ETŠ Tuzla, Selma Krajinović
Primjer 6
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
*
* *
* * *
* * * *
* * * * *
14
ETŠ Tuzla, Selma Krajinović
SD1
* * * * *
* * * *
* * *
* *
*
SD2
*
* *
* * *
* * * *
* * * * *
GD1: ai,j =
15
ETŠ Tuzla, Selma Krajinović
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
1 5 2 1 5 redu 2 i koloni 1. Zadnja pojava je u redu 5 i koloni 4.
0 2 4 6 4
Najveći element je 8. Prva pojava ovog elementa je u redu 4 i koloni 5.
1 2 5 6 2
Zadnja pojava je u redu 5 i koloni 5.
1 2 0 7 8
7 8 7 0 8
Rješenje
16
ETŠ Tuzla, Selma Krajinović
17
ETŠ Tuzla, Selma Krajinović
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.
1 5 2 1 5 1 1 2 5 5
0 2 4 6 4 0 2 4 4 6
1 2 5 6 2 1 2 2 5 6
1 2 0 7 8 0 1 2 7 8
7 8 7 0 8 0 7 7 8 8
x y
Rješenje
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.
18
ETŠ Tuzla, Selma Krajinović
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.
19
ETŠ Tuzla, Selma Krajinović
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:
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.
20
ETŠ Tuzla, Selma Krajinović
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
A11 A12
A21 A22
A10 A12
A20 A22
A10 A11
A20 A21
21
ETŠ Tuzla, Selma Krajinović
A01 A02
A21 A22
A00 A02
A20 A22
A00 A01
A20 A21
A01 A02
A11 A12
A00 A02
A10 A12
A00 A01
A10 A11
22
ETŠ Tuzla, Selma Krajinović
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
23
ETŠ Tuzla, Selma Krajinović
24
ETŠ Tuzla, Selma Krajinović
Modul 2:
Primjena struktura podataka i pointera
Povezane liste
25
ETŠ Tuzla, Selma Krajinović
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.
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
26
ETŠ Tuzla, Selma Krajinović
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;
};
Primjer deklaracije
Ucenik osoba;
Na ovaj način deklarisali smo promjenljivu osoba koja je tipa strukture Ucenik.
Primjer 1
Napisati program koji definiše strukturu Ucenik, a zatim deklariše promjenljivu osoba. Učitati i ispisati
podatke o jednoj osobi.
27
ETŠ Tuzla, Selma Krajinović
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).
Rješenje
28
ETŠ Tuzla, Selma Krajinović
Funkcija UcitajVrijeme provjerava unos vrijednosti i vraća strukturu Vrijeme. Funkcija IspisiVrijeme ne
vraća nikakvu vrijednost:
29
ETŠ Tuzla, Selma Krajinović
Funkcija SaberiVrijeme koristi cjelobrojno dijeljenje i operator modul za računanje sabranih sekundi,
minuta i sekundi, kako slijedi:
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.
30
ETŠ Tuzla, Selma Krajinović
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
31
ETŠ Tuzla, Selma Krajinović
struct datum
{
int dan;
32
ETŠ Tuzla, Selma Krajinović
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.
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.
33
ETŠ Tuzla, Selma Krajinović
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.
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.
Operatori
Operatori koji se koriste sa pokazivačima dati su u tabeli:
Operator Značenje
34
ETŠ Tuzla, Selma Krajinović
& Referenciranje - Vraća adresu lokacije na kojoj je promjenljiva čije ime se navodi nakon
operatora
drugi_objekat = *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.
Primjer 1
35
ETŠ Tuzla, Selma Krajinović
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.
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:
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.
36
ETŠ Tuzla, Selma Krajinović
37
ETŠ Tuzla, Selma Krajinović
int *p;
p = new int;
Zadaci za vježbu
Testirajte slijedeći kod i ispravite grešku
38
ETŠ Tuzla, Selma Krajinović
Ma kako komplikovano izgledalo, pravila za rad sa pokazivačima se svode na slijedeća prosta pravila:
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
39
ETŠ Tuzla, Selma Krajinović
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;
}
40
ETŠ Tuzla, Selma Krajinović
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“.
int Godina;
int &rGodina = Godina;
Šta bi bio efekat ovih naredbi?
Godina = 2000;
cout << Godina;
cout << rGodina;
Na ekranu bi bila ispisana ista vrijednost!
41
ETŠ Tuzla, Selma Krajinović
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.
42
ETŠ Tuzla, Selma Krajinović
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.
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:
43
ETŠ Tuzla, Selma Krajinović
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.
- 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
n – cjelobrojna promjenljiva,
44
ETŠ Tuzla, Selma Krajinović
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!)
45
ETŠ Tuzla, Selma Krajinović
46
ETŠ Tuzla, Selma Krajinović
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:
array_ptr
0x5000
0x5000
array_ptr+2
0x5002
0x5000
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).
47
ETŠ Tuzla, Selma Krajinović
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.
48
ETŠ Tuzla, Selma Krajinović
Primjer 2
Prezime/Ime
(Dakle, ime i prezime su odvojeni znakom “/”). Napisati program koji razdvaja ime i prezime.
Parametri
Povratna vrijednost
Pokazivač na poziciju na kojoj se prvi puta pojavljuje karakter. Ako karakter nije pronađen,
funkcija vraća null pokazivač
49
ETŠ Tuzla, Selma Krajinović
Za rješavanje problema iz zadatka, pomoću funkcije strchr naći ćemo poziciju karaktera “/”. Koristimo
dva pokazivača:
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:
50
ETŠ Tuzla, Selma Krajinović
Primjer 3
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.
51
ETŠ Tuzla, Selma Krajinović
Zadaci za vježbu
1. U ulaznoj datoteci “podaci.xls” nalaze se podaci o učenicima:
• Prezime
• Ime
• Adresa
• Grad
• Poštanski broj
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.
52
ETŠ Tuzla, Selma Krajinović
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.
53
ETŠ Tuzla, Selma Krajinović
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.
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.
54
ETŠ Tuzla, Selma Krajinović
Upoznat ćemo jednostruko povezanu listu. Na slici je primjer jednostruko povezane liste:
START
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.
NULL
R A R
E U
B
F
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.
- 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.
55
ETŠ Tuzla, Selma Krajinović
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.
56
ETŠ Tuzla, Selma Krajinović
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.
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).
57
ETŠ Tuzla, Selma Krajinović
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.
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.
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.
58
ETŠ Tuzla, Selma Krajinović
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:
novi
nedefinisano
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
}
59
ETŠ Tuzla, Selma Krajinović
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;
novi
čvor
dodan
NULL
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.
60
ETŠ Tuzla, Selma Krajinović
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.
61
ETŠ Tuzla, Selma Krajinović
62
ETŠ Tuzla, Selma Krajinović
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.
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;
63
ETŠ Tuzla, Selma Krajinović
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.
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
etc.
pom
start_ptr
64
ETŠ Tuzla, Selma Krajinović
etc.
pom
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
start_ptr
65
ETŠ Tuzla, Selma Krajinović
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
start_ptr
NULL
pom2 pom1
Ovo ponavljamo sve dok pom1 ne pokazuje zadnji čvor u listi, a pom2 na njegovog prethodnika:
66
ETŠ Tuzla, Selma Krajinović
start_ptr
NULL
pom2 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.
void brisi_zadnji_cvor()
{
67
ETŠ Tuzla, Selma Krajinović
Deklarišimo pointer tekuci. Najprije mu dodjeljujemo adresu prvog čvora u listi, koju čuvamo u pointeru
start_ptr :
cvor *tekuci;
tekuci = start_ptr;
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;
68
ETŠ Tuzla, Selma Krajinović
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:
prethodni slijedeci
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;
69
ETŠ Tuzla, Selma Krajinović
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:
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:
tekuci pom
Zatim podešavamo da pointer u tekućem čvoru sadrži adresu čvora koji slijedi iza onog na kojeg
pokazuje pomoćni:
tekuci pom
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;
}
70
ETŠ Tuzla, Selma Krajinović
if (tekuci->slijedeci == NULL)
dodaj_cvor_na_kraj();
else
{ cvor *novi;
new novi;
upisi_podatke_u_cvor(novi);
U slijedećem primjeru primjenićemo ove procedure i pokazati kako se implementiraju i neke dodatne
funkcionalnosti povezane liste.
71
ETŠ Tuzla, Selma Krajinović
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.
72
ETŠ Tuzla, Selma Krajinović
Glavni meni poziva se u funkciji main, gdje se, nakon povratka iz menija, u okviru switch naredbe poziva
odgovarajuća funkcija:
73
ETŠ Tuzla, Selma Krajinović
74
ETŠ Tuzla, Selma Krajinović
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.
75
ETŠ Tuzla, Selma Krajinović
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).
Za potrebe ispisivanja liste također koristimo pomoćnu funkciju za ispisivanje sadržaja jednog čvora.
76
ETŠ Tuzla, Selma Krajinović
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:
77
ETŠ Tuzla, Selma Krajinović
Brisanje čvora na početku i kraju liste također je objašnjeno ranije. Slijedi kod ovih funkcija:
78
ETŠ Tuzla, Selma Krajinović
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.
79
ETŠ Tuzla, Selma Krajinović
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:
80
ETŠ Tuzla, Selma Krajinović
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:
81
ETŠ Tuzla, Selma Krajinović
novi
prethodni novi
82
ETŠ Tuzla, Selma Krajinović
83
ETŠ Tuzla, Selma Krajinović
Konačno, snimanje podataka iz čvorova povezane liste realizuje se u funkciji kako slijedi:
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:
84
ETŠ Tuzla, Selma Krajinović
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
85
ETŠ Tuzla, Selma Krajinović
86
ETŠ Tuzla, Selma Krajinović
Zadaci za ponavljanje
POVEZANE LISTE, vježba 1 (osnovni pojmovi, deklaracija, kreiranje liste)
NULL
1 4 2 3
4 2 2 2 2
2
87
ETŠ Tuzla, Selma Krajinović
{
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.
1 4 2 3
4 2 2 2 2
2
Start_ptr
1 4
2. 2 3
4 2 2
3. 2 2
2
4.
1 4 2 3
4 2 2 2 2
2
ISPIS:......
88
ETŠ Tuzla, Selma Krajinović
Vježba 2
- Lokomotiva
- Kupe
- Teretni
- Restoran
- 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)
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:
Dodavanje putničkog vagona uraditi automatski ako je u svim kupe vagonima maksimalan broj putnika.
89
ETŠ Tuzla, Selma Krajinović
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.
90
ETŠ Tuzla, Selma Krajinović
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:
91
ETŠ Tuzla, Selma Krajinović
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
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. 4 Brisanje restorana
92
ETŠ Tuzla, Selma Krajinović
93
ETŠ Tuzla, Selma Krajinović
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.
Ideja za uvod i dijelovi teksta preuzeti iz knjige „Head First Java“, O Relly, Katty Sierra, Bert Bates
94
ETŠ Tuzla, Selma Krajinović
Kao što je to uradio milion puta do sada, Larry je Brad je napisao klasu za svaki od tri oblika....
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
}
95