Programiranje 1 (vjeˇzbe

)
Vedran
ˇ
Sego
2. rujna 2010.
Sadrˇzaj
1 Brojevni sustavi 1
1.1 Pretvaranje brojeva medu bazama . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Raˇcunske operacije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3 Traˇzenje baze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2 Raˇcun sudova 19
2.1 Tablice istinitosti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2 Normalne forme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.3 Pojednostavljivanje logiˇckih izraza . . . . . . . . . . . . . . . . . . . . . . . 27
2.4 Osnovni sklopovi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.5 Poluzbrajalo i potpuno zbrajalo . . . . . . . . . . . . . . . . . . . . . . . . 31
2.6 Dodatni zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3 Konaˇcni automati i regularni izrazi 39
3.1 Konaˇcni automati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
3.2 Regularni izrazi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4 Uvod u algoritme i osnovni program 59
4.1 Tko “programira”? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.2 Osnovni program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.3 Ispis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5 Varijable 65
5.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5.2 Joˇs o formatima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
6 Osnovne raˇcunske operacije 71
6.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
i
ii SADR
ˇ
ZAJ
6.2 Pridruˇzivanje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
7 Grananje 75
7.1 Obiˇcno grananje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
7.2 Uvjetni operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
8 Petlje 79
8.1 while()-petlja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
8.2 for()-petlja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
8.3 do...while()-petlja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
8.4 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
8.5 Malo o sloˇzenosti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
8.6 Promjena toka petlje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
9 Viˇsestruko grananje 103
9.1 Naredba switch() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
10 Funkcije 107
10.1 Jednostavne funkcije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
10.2 Varijabilni argumenti funkcija . . . . . . . . . . . . . . . . . . . . . . . . . 114
11 Nizovi (polja) 121
11.1 Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
11.2 Nizovi kao funkcijski argumenti . . . . . . . . . . . . . . . . . . . . . . . . 126
11.3 Hornerov algoritam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
11.4 Sortiranje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
11.5 Pretraˇzivanje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
11.6 Dodavanje i brisanje elemenata . . . . . . . . . . . . . . . . . . . . . . . . 145
11.6.1 Dodavanje elemenata . . . . . . . . . . . . . . . . . . . . . . . . . . 145
11.6.2 Brisanje elemenata . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
Poglavlje 1
Brojevni sustavi
Brojimo: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Kako dalje? Poˇsto nemamo dodatnih znamenaka,
prelazimo na dvoznamenkaste brojeve: na prvo mjesto stavljamo znamenku 1, a zadnju
znamenku postavljamo na najmanju mogu´cu vrijednost (nula), te dobijamo broj 10. Po-
novno brojimo kao i do sada, mijenjaju´ci samo posljednju znamenku: 11, 12, 13, 14, 15,
16, 17, 18, 19. Kad nam ponovno ponestane znamenaka, prvu znamenku pove´camo za
jedan, a posljednju opet vra´camo na nulu i tako dobijemo 20. Postupak nastavljamo dok
god je potrebno. Opisani naˇcin zapisivanja brojeva zovemo “prikaz brojeva u dekadskoj
bazi” (ili “u bazi deset”).
Kako bismo brojali kad bi nam netko zabranio upotrebu znamenaka 8 i 9?
Krenimo istom logikom: 0, 1, 2, 3, 4, 5, 6, 7. Sada viˇse nemamo znamenaka, pa na
prelazimo na dvoznamenkaste brojeve: 10. Kao i malo prije, nastavljamo: 11, 12, 13, 14,
15, 16, 17. Ponovno nam nedostaju znamenke, pa pove´cavamo prvu, dok drugu vra´camo
na nulu: 20. Ovakav zapis zovemo “prikaz brojeva u oktalnoj bazi” (ili “u bazi osam”).
Napomena 1.0.1. Iako tako izgleda, ovdje nismo preskoˇcili brojeve. Naime, kad napi-
ˇsemo “17”, to je prikaz nekog broja na odredeni naˇcin, jednako kao ˇsto su XVII, MMVII
i sl. prikazi nekih brojeva (17 i 2007). Oznaka “12” u bazi 10 predstavlja broj dvanaest;
no, ta ista oznaka (“12”) u bazi osam predstavlja broj deset. Naime, ako brojimo po redu,
iza “7” dolazi “10” (a znamo da iza sedam dolazi osam); zatim imamo “11” (tj. devet),
pa “12” (tj. deset).
Moˇzemo koristiti i 16 znamenaka. Tada, uz uobiˇcajenih deset (od 0 do 9), upotreb-
ljavamo i 6 dodatnih, koje oznaˇcavamo slovima A, B, C, D, E i F. U tom sluˇcaju, oznaka
“A” predstavlja broj deset, oznaka “B” broj jedanaest itd. Oznaka “F” ´ce predstavljati
broj petnaest, pa ´ce oznaka “10” zapravo oznaˇcavati broj ˇsesnaest. Takav prikaz zovemo
“prikaz brojeva u heksadecimalnoj bazi” (ili “u bazi ˇsesnaest”).
Da bismo znali u kojoj je bazi neki broj, zapisujemo ga na sljede´ci naˇcin:
(broj)
baza
,
npr. (10)
10
= (12)
8
= (A)
16
.
1
2 1. Brojevni sustavi
Baza Jedan Dva Tri
ˇ
Cetiri Sedamnaest Dvije tisu´ce i sedam
2 (1)
2
(10)
2
(11)
2
(100)
2
(10001)
2
(11111010111)
2
3 (1)
3
(2)
3
(10)
3
(11)
3
(122)
3
(2202100)
3
8 (1)
8
(2)
8
(3)
8
(4)
8
(21)
8
(3727)
8
10 (1)
10
(2)
10
(3)
10
(4)
10
(17)
10
(2007)
10
16 (1)
16
(2)
16
(3)
16
(4)
16
(11)
16
(7D7)
16
Tablica 1.1: Primjeri prikaza nekih brojeva u raznim brojevnim sustavima
Raˇcunalo koristi sustav sa samo dvije znamenke (tzv. binarni zapis), ˇsto znaˇci da ono
broji 0, 1, 10, 11, 100,. . .
U tablici 1 prikazani su primjeri prikaza nekih brojeva u binarnom, ternarnom, oktal-
nom, dekadskom i heksadecimalnom sustavu.
1.1 Pretvaranje brojeva medu bazama
Zapis broja a u bazi b oznaˇcavamo s
a = (a
n
a
n−1
. . . a
1
a
0
)
b
,
ˇsto moˇzemo raspisati:
a = a
n
b
n
+ a
n−1
b
n−1
+· · · + a
1
b
1
+ a
0
b
0
=
n
¸
i=0
a
i
b
i
.
Na taj naˇcin dobijamo o kojem je broju rijeˇc, tj. zapis u dekadskoj bazi.
Primijetite da uvrˇstavanjem baze b = 10 dobijamo upravo “uobiˇcajenu” interpretaciju
zapisa po znamenkama.
Zadatak 1.1.1. Pretvorite u bazu 10 sljede´ce brojeve:
a) (13)
16
b) (123)
4
c) (101001000)
2
d) (101001000)
4
Rjeˇsenje. Raspisujemo po definiciji:
a) (13)
16
= 1 · 16
1
+ 3 · 16
0
= 16 + 3 = 19,
b) (123)
4
= 1 · 4
2
+ 2 · 4
1
+ 3 · 4
0
= 16 + 8 + 3 = 27,
c) (101001000)
2
= 1 · 2
8
+ 1 · 2
6
+ 1 · 2
3
= 256 + 64 + 8 = 328.
d) (101001000)
4
= 1 · 4
8
+ 1 · 4
6
+ 1 · 4
3
= 65536 + 4096 + 64 = 69696.
1.1. Pretvaranje brojeva medu bazama 3
Prikaz broja a u bazi b dobijamo uzastopnim dijeljenjem a s b, te zapisivanjem unatrag
svih ostataka pri dijeljenju. Postupak je prikazan na slici 1.1, pri ˇcemu je konaˇcni rezultat
(“(31)
4
”) oznaˇcen sivom bojom.
13 = 3 4 + 1
3 = 0 4 + 3 1
0 3
(13) = (31)
4 10
Slika 1.1: Pretvaranje (13)
10
u bazu 4 (rezultat je (31)
4
)
Zadatak 1.1.2. Pretvorite broj a u bazu b, pri ˇcemu je:
a) a = 31, b = 4 b) a = 123, b = 16 c) a = 1719, b = 13
Rjeˇsenje.
a) 31 = 7 · 4 + 3
7 = 1 · 4 + 3 3
1 = 0 · 4 + 1 3
0 1
Rjeˇsenje: (31)
10
= (133)
4
.
b) 123 = 7 · 16 + 11
7 = 0 · 16 + 7 B (= 11)
0 7
Rjeˇsenje: (123)
10
= (7B)
16
.
c) 1719 = 132 · 13 + 3
132 = 10 · 13 + 2 3
10 = 0 · 13 + 10 2
0 A (= 10)
Rjeˇsenje: (123)
10
= (A23)
13
.
Pretvaranje broja iz baze b
1
= 10 u bazu b
2
= 10 obiˇcno radimo u dva koraka:
4 1. Brojevni sustavi
1. Pretvorimo broj iz baze b
1
u bazu 10,
2. Pretvorimo broj iz baze 10 u bazu b
2
.
Zadatak 1.1.3. Pretvorite broj a iz baze b
1
u bazu b
2
, pri ˇcemu je:
a) a = 1719, b
1
= 11, b
2
= 9 b) a = 1311, b
1
= 5, b
2
= 8
Rjeˇsenje. Pretvaranja medu bazama rade se kao u rjeˇsenjima prethodna dva zadatka.
Ovdje navodimo samo rjeˇsenja s medukorakom (prikazom broja u bazi 10):
a) (1719)
11
= (2198)
10
= (3012)
9
b) (1311)
5
= (206)
10
= (316)
8
Broj a iz baze b
1
u bazu b
2
moˇzemo izvesti direktno, ako postoje b, n
1
, n
2
∈ N takvi
da je b
1
= b
n
1
i b
2
= b
n
2
. Neka je zapis broja a u bazi b
1
dan s
a = (a
n
a
n−1
. . . a
1
a
0
)
b
1
.
Po koracima:
1. Svaku pojedinu znamenku pretvaramo iz baze b
1
u bazu b:
a
n
a
n−1
. . . a
1
a
0
−→ |(a
n
)
b
|(a
n−1
)
b
| . . . |(a
1
)
b
|(a
0
)
b
|,
pri ˇcemu svaku znamenku u poˇcetnom zapisu zamjenjujemo s n
1
znamenaka. Ako
zapis znamenke a
i
u bazi b ima manje od n
1
znamenaka, na poˇcetak dopisujemo
nule.
2. Dobiveni zapis dijelimo u grupice od po n
2
znamenaka s desna na lijevo (ako nam za
najlijeviju grupu ponestane znamenaka, na poˇcetak dopiˇsemo nule). Tako dobijemo:
|(a
n
)
b
|(a
n−1
)
b
| . . . |(a
1
)
b
|(a
0
)
b
| −→ |a

k
|a

k−1
| . . . |a

1
|a

0
|,
pri ˇcemu smo samo regrupirali postoje´ce znamenke (nema nikakve konverzije).
3. Svaku grupu znamenaka a

i
zasebno pretvorimo u bazu b
2
(od svake mora nastati
toˇcno jedna znamenka u bazi b
2
; ako ne ispadne, postoji greˇska u postupku!).
Primjer 1.1.1.
ˇ
Zelimo broj (3701)
8
pretvoriti u bazu 16. Oˇcito je b = 2, n
1
= 3 (jer je
8 = 2
3
) i n
2
= 4 (jer je 16 = 2
4
).
1. 3701 −→ |011|111|000|001|
2. |011|111|000|001| = 011111000001 −→ |0111|1100|0001|
1.1. Pretvaranje brojeva medu bazama 5
3. |0111|1100|0001| −→ 7C1,
jer je (111)
2
= (7)
16
, (1100)
2
= (12)
10
= (C)
16
i (1)
2
= (1)
16
.
Rjeˇsenje: (3701)
8
= (7C1)
16
.
Naravno, ako je b
2
= b
n
1
, tada preskaˇcemo prvi korak (jer je onda b
2
= b, n
1
= 1 i
n
2
= n). Ako je pak b
1
= b
n
2
, preskaˇcemo drugi i tre´ci korak (jer je onda b
1
= b, n
1
= n i
n
2
= 1).
Zadatak 1.1.4. Bez pretvaranja u dekadski sustav, popunite praznine:
a) (17)
8
= ( )
16
b) (313)
4
= ( )
16
c) (1412)
9
= ( )
27
d) (256)
25
= ( )
5
Rjeˇsenje.
a) (17)
8
b=2,n
1
=3
−→ |001|111|
n
2
=4
−→ |0000|1111| = (F)
16
b) (313)
4
b=4,n
1
=1
−→ preskaˇcemo 1. korak
n
2
=2
−→ |03|13| = (37)
16
ili
(313)
4
b=2,n
1
=2
−→ |11|01|11|
n
2
=4
−→ |0011|0111| = (37)
16
c) (1412)
9
b=3,n
1
=2
−→ |01|11|01|02|
n
2
=3
−→ |001|110|102| = (1CB)
27
,
jer je (110)
3
= 1 · 3
2
+ 1 · 3
1
= 9 + 3 = 12 = (C)
27
.
d) (256)
25
b=5,n
1
=2
−→ |02|10|11| = (21011)
5
(preskaˇcemo korake 2 i 3 jer je n
2
= 1).
Zadatak 1.1.5. Popunite praznine:
a) (17)
16
= ( )
17
= ( )
3
b) (314)
8
= ( )
2
c) (1412)
5
= ( )
2
= ( )
11
d) (121)
3
= ( )
9
e) (DEDA)
16
= ( )
7
= ( )
3
f ) (321)
9
= ( )
27
6 1. Brojevni sustavi
Zadatke b), d) i f ) rijeˇsite na oba naˇcina (i direktno i pomo´cu pretvaranja u dekadsku
bazu).
Rjeˇsenje.
a) (17)
16
= (16)
17
= (212)
3
b) (314)
8
= (11001100)
2
c) (1412)
5
= (11101000)
2
= (1A1)
11
d) (121)
3
= (17)
9
e) (DEDA)
16
= (325220)
7
= (2220020222)
3
f) (321)
9
= (9J)
27
Ovakve zadatke moˇzete si i sami zadavati (odredite broj i baze izmedu kojih ga ˇzelite
prebaciti; pri tome pazite da sve znamenke broja moraju biti strogo manje od baze u
kojoj je broj zapisan!), a rjeˇsenje moˇzete provjeriti na sluˇzbenoj stranici kolegija:
http://degiorgi.math.hr/prog1/apps/brsust.php
1.2 Raˇcunske operacije
Brojeve, naravno, moˇzemo zbrajati, oduzimati, mnoˇziti i dijeliti bez obzira na to u kojoj
su bazi zapisani. Jedan naˇcin je pretvaranjem u dekadsku bazu, izvodenjem operacija, te
pretvaranjem u polaznu bazu, no mogu´ce je i direktno. Sve operacije se rade analogno
onima u dekadskom sustavu, uz tu razliku da “1 dalje” i sl. ne radimo za 10 nego za b.
Napomena 1.2.1. Raˇcunske operacije moˇzemo izvrˇsavati samo na brojevima koji su pri-
kazani u istom brojevnom sustavu. Ako su brojevi prikazani s razliˇcitim bazama, potrebno
je jednog od njih (ili oba) pretvoriti u neku bazu, preporuˇcljivo u onu u kojoj treba biti
zapisan rezultat.
Primjer 1.2.1. Traˇzimo zbroj, razliku, produkt i kvocijent brojeva x = (11110)
2
i y =
(101)
2
. Pretvaranjem lako dobijemo da su to x = (30)
10
i y = (5)
10
, te dobijamo:
x + y = (35)
10
= (100011)
2
, x −y = (25)
10
= (11001)
2
,
x · y = (150)
10
= (10010110)
2
, x : y = (6)
10
= (110)
2
.
Izraˇcunajmo vrijednost tih izraza bez pretvaranja u dekadsku bazu.
1.2. Ra
ˇ
cunske operacije 7
1. zbroj:
Primijetite:
(0)
2
+ (0)
2
= (0)
2
i
(1)
2
+ (0)
2
= (1)
2
i
(0)
2
+ (1)
2
= (1)
2
, ali
(1)
2
+ (1)
2
= (1)
10
+ (1)
10
= (2)
10
= (10)
2
,
tj. rezultat zbrajanja 1 + 1 u bazi 2 je “nula i jedan dalje”.
1 1 1
11110
+ 101
100011
2. razlika:
Kad oduzimamo ve´cu znamenku od manje, npr. (0)
2
−(1)
2
, potrebno je “posuditi” 1
od lijeve znamenke. Time dobijamo oduzimanje jednoznamenkastog broja od dvoz-
namenkastog, npr. (10)
2
−(1)
2
.
Oduzimamo kao i u dekadskoj bazi, samo ˇsto “posudenih” 1 ne daje 10 nego 2 (pa
0 − 1 daje rezultat 2 − 1 = 1, uz “pamtimo 1” koji zatim oduzmemo od idu´ce zna-
menke):
11110
- 101
−1
11001
3. produkt:
Mnoˇzenje se obavlja sliˇcno zbrajanju, samo treba paziti jer nemamo nuˇzno samo 1
dalje, nego moˇze biti i viˇse. U binarnoj bazi, taj dio se ne primje´cuje; dapaˇce, nema
niti klasiˇcnog mnoˇzenja (jer mnoˇzimo samo s nulom ili jedinicom). No, potrebno je
paziti na potpisivanje i ispravno zbrojiti sve rezultate:
11110 · 101
1 1 1 1
11110
0
11110
10010110
Primijetite: (1)
2
+ (1)
2
+ (1)
2
= (10)
2
+ (1)
2
= (11)
2
. Zato, ako ve´c imamo “1
dalje”, izraz (1)
2
+ (1)
2
daje “rezultat 1 i 1 dalje”.
4. kvocijent:
Ponovno, princip je jednak onome iz dekadskog sustava. Dapaˇce, jedini koraci ko-
ji ˇcine razliku su mnoˇzenje i oduzimanje. Dakle, potrebno je “pogoditi” kvocijent
8 1. Brojevni sustavi
poˇcetka djeljenika s djeliteljem. Zatim se djelitelj mnoˇzi s “pogodenim” rezultatom,
te se rezultat oduzima od poˇcetka djeljenika. Ako je dobiveni rezultat nenegativan i
strogo manji od djelitelja, znaˇci da je kvocijent dobro pogoden. “Spuˇstamo” idu´cu
znamenku djeljenika i nastavljamo postupak:
11110 : 101 = 110
111
−101
101
−101
00
−0
0
Napomena 1.2.2. Za svaku bazu b vrijedi:
(a
n
a
n−1
. . . a
1
a
0
)
b
· b = (a
n
a
n−1
. . . a
1
a
0
)
b
· (10)
b
= (a
n
a
n−1
. . . a
1
a
0
0)
b
.
Tako, na primjer, mnoˇzenje s 2 u binarnoj bazi radimo dopisivanjem nule na kraj.
Zadatak 1.2.1. Izraˇcunajte zbroj, razliku, produkt i kvocijent brojeva x = (7347)
8
i y =
(155)
8
bez pretvaranja u dekadsku bazu.
Rjeˇsenje.
1. zbroj:
Vrijedi: (7)
8
+ (5)
8
= (7)
10
+ (5)
10
= (12)
10
= 1 · 8 + 4, pa je rezultat takvog
zbrajanja 4 i “1 dalje”. Nakon toga imamo (1)
8
+(4)
8
+(5)
8
(tih “1 dalje” zbrojeno
s predzadnje dvije znamenke), ˇsto daje (10)
10
= 1 · 8 + 2, tj. rezultat 2 i “1 dalje”.
Analogno dalje.
1 1
7347
+ 155
7524
2. razlika:
Kod oduzimanja predzadnjih znamenaka imamo: (4)
8
− (5)
8
, ˇsto daje negativan
rezultat. Zbog toga jepotrebno “posuditi” 1 od tre´ce znamenke s desna. Tada je
potrebno izraˇcunati (14)
8
−(5)
8
= (12)
10
−(5)
10
= (7)
10
= (7)
8
. Pri tome “posude-
nu” jedinicu treba oduzeti od znamenke od koje je “posudena”.
7347
− 155
−1
7172
1.2. Ra
ˇ
cunske operacije 9
3. produkt:
Mnoˇzenje s jednom znamenkom, na primjer (7347)
8
s 5, moˇzemo obaviti po koraci-
ma:
1. 7 · 5 = (35)
10
= (43)
8
→ 3
2. 4 · 5 = (20)
10
= (24)
8
; ovome joˇs treba pribrojiti “4 dalje” (prva znamenka iz
prethodnog koraka), ˇsto za rezultat daje (24)
8
+ (4)
8
= (30)
8
→ 0
3. 3 · 5 = (15)
10
= (17)
8
; dodajemo joˇs “3 dalje” iz prethodnog koraka, pa je
konaˇcni rezultat (17)
8
+ (3)
8
= (22)
8
→ 2
4. 7 · 5 = (35)
10
= (43)
8
; dodajemo joˇs “2 dalje” iz prethodnog koraka, pa je
konaˇcni rezultat (43)
8
+ (2)
8
= (45)
8
Konaˇcni rezultat dobijemo slaganjem rezultata po koracima, od zadnjeg prema pr-
vom:
(7347)
8
· (5)
8
= (45|2|0|3)
8
= (45203)
8
7347 · 155
1 1 1 1
7347
45203
45203
1454133
4. kvocijent:
7347 : 155 = 43
734
−664
507
−507
0
Provjere radi, lako vidimo da je x = (7347)
8
= (3815)
10
i y = (155)
8
= (109)
10
, pa imamo:
x + y = (3924)
10
= (7524)
8
, x −y = (3706)
10
= (7172)
8
,
x · y = (415835)
10
= (1454133)
8
, x : y = (35)
10
= (43)
8
,
ˇsto pokazuje da su dobiveni rezultati toˇcni.
Napomena 1.2.3 (
ˇ
Ceste greˇske). Prilikom raˇcunanja u raznim nedekadskim bazama,
pripazite na ˇceste greˇske primjenjivanja uobiˇcajenih pravila iz dekadskog sustava! Na
primjer:
10 1. Brojevni sustavi
• Izraze (x)
b
± (y)
b
, (x)
b
· (y)
b
i (x)
b
: (y)
b
ne smijete prvo izraˇcunati kao da su x
i y dekadski brojevi, pa zatim rezultat pretvoriti u bazu b, nego morate ili raˇcunati
direktno u bazi b (kako je opisano) ili pretvoriti u dekadsku bazu! Na primjer, (10)
2
+
(11)
2
ne moˇzemo proglasiti za 21 i onda pretvoriti u bazu 2, jer ´ce rezultat biti
(10101)
2
(toˇcan rezultat je (101)
2
).
• Izraze ne smijete niti samo evaluirati kao da su dekadski brojevi! Na primjer,
(28)
16
+ (37)
16
nije (65)
16
(= (101)
10
), nego (5F)
16
(= (95)
10
).
• Ako je zapis broja u bazi b dan s
(a
n
a
n−1
. . . a
1
a
0
)
b
,
onda za svaki i ∈ {0, 1, . . . , n} mora vrijediti:
a
i
∈ {0, 1, . . . , b −1}.
Drugim rijeˇcima, sve znamenke broja prikazanog u bazi b moraju biti nenegativne i
strogo manje od b! Na primjer, ako dobijete rezultat poput (678)
8
ili (73)
5
, on je
besmislen i samim tim pogreˇsan.
• Paˇzljivo proˇcitajte zadatak i pazite koja je baza zadana. Na primjer, broj (10110101)
8
moˇze izgledati kao binarni broj, no on je, u stvari oktalni!
Zadatak 1.2.2. Izraˇcunajte bez pretvaranja u druge baze:
a) (123)
4
+ (231)
4
b) (1234)
5
+ (2341)
5
+ (3412)
5
+ (4123)
5
c) (BABA)
16
+ (DEDA)
16
d) (624)
8
−(555)
8
e) (147AD)
15
−(EEEE)
15
f ) (DEDA)
16
−(BABA)
16
g) (505)
6
· (23)
6
h) (314)
8
· (72)
8
i) (BABA)
16
· (9A)
16
j) (111011010)
3
: (110)
3
k) (7170)
9
: (120)
9
l) (F1FA)
16
: (293)
16
1.3. Tra
ˇ
zenje baze 11
Rjeˇsenje.
a) (123)
4
+ (231)
4
= (1020)
4
b) (1234)
5
+ (2341)
5
+ (3412)
5
+ (4123)
5
= (22220)
5
c) (BABA)
16
+ (DEDA)
16
= (19994)
16
d) (624)
8
−(555)
8
= (47)
8
e) (147AD)
15
−(EEEE)
15
= (47AE)
15
f) (DEDA)
16
−(BABA)
16
= (2420)
16
g) (505)
6
· (23)
6
= (20503)
6
h) (314)
8
· (72)
8
= (27070)
8
i) (BABA)
16
· (9A)
16
= (7053E4)
16
j) (111011010)
3
: (110)
3
= (1002121)
3
k) (7170)
9
: (120)
9
= (58)
9
l) (F1FA)
16
: (293)
16
= (5E)
16
Kao i s pretvaranjem brojeva izmedu razliˇcitih brojevnih sustava, zadatke s raˇcunanjem
u odredenoj bazi moˇzete sami sastaviti, a rezultate moˇzete provjeriti na sluˇzbenoj stranici
kolegija: http://degiorgi.math.hr/prog1/apps/brsust.php.
Rezultate moˇzete provjeriti i “na ruke”, pretvaranjem u dekadsku bazu.
Napomena 1.2.4. Ukoliko Vam na kolokviju ostane dovoljno vremena, za provjeru ri-
jeˇsite zadatke s raˇcunskim operacijama na zasebnom papiru i s pretvaranjem u dekadski
sustav. Ukoliko se rezultati ne poklapaju, znaˇci da postoji greˇska (ona moˇze biti i u origi-
nalnom i u kontrolnom raˇcunanju)!
1.3 Traˇzenje baze
Ponekad se u zadacima traˇzi baza b u kojoj vrijedi neko svojstvo. U pravilu, takve zadatke
rjeˇsavamo raspisom po definiciji (tj. pretvaranjem u dekadsku bazu). Pri tome treba paziti
da x +a
i
i x · a
i
, gdje su x i a
i
jednoznamenkasti nenegativni brojevi, ne moraju viˇse biti
jednoznamenkasti, kao i da x − a
i
i a
i
− x ne moraju viˇse biti nenegativni. Takoder,
korisno je dobivena rjeˇsenja uvrstiti u poˇcetne uvjete i tako provjeriti jesu li dobra.
Napomena 1.3.1 (
ˇ
Ceste greˇske).
12 1. Brojevni sustavi
• Sve dobivene baze moraju biti strogo ve´ce od 1. Na primjer, brojevi −17, 0, 1 i sl.
nisu dobre baze brojevnih sustava.
• Baza zapisa svakog broja mora biti strogo ve´ca i od svih znamenaka tog broja.
• Baza, naravno, mora biti cijeli broj, kao i sve znamenke. Drugim rijeˇcima, ako
dobijete da je neka baza, na primjer,

5, to rjeˇsenje morate odbaciti kao nezadovo-
ljavaju´ce.
• Pazite ˇsto je baza, jer ona ne mora nuˇzno biti varijabla b, nego moˇze biti i neka
druga varijabla ili ˇcak neki izraz. Na primjer, ako imamo zadan broj (123)
b+7
za
koji mora vrijediti neko svojstvo, tada mora biti b + 7 > 3, tj. b > −4. U takvom
zadatku b = −3 moˇze (ali i ne mora) biti dobro rjeˇsenje, jer je baza b + 7, a ne b.
Zadatak 1.3.1. U kojoj bazi b je broj (123)
b
trostruko ve´ci od broja (21)
b
, a u kojoj je
trostruko ve´ci od broja (25)
b
?
Rjeˇsenje. Raspisujemo po definiciji:
(123)
b
= 3 · (21)
b
1 · b
2
+ 2 · b + 3 = 3 · (2 · b + 1) = 6 · b + 3
b
2
−4b = 0
b(b −4) = 0
Kandidati za rjeˇsenja su b
1
= 0 i b
2
= 4. No, iz zadatka vidimo da mora biti b > 3, pa b
1
ne moˇze biti rjeˇsenje. Za kraj, uvrˇstavamo rjeˇsenje b = 4 u uvjet zadatka:
(123)
4
= 4
2
+ 2 · 4 + 3 = 16 + 8 + 3 = 27 = 3 · 9 = 3 · (21)
4
.
Zakljuˇcujemo da je b = 4 jedino rjeˇsenje prvog dijela zadatka.
Rijeˇsimo sada drugi dio zadatka (na isti naˇcin):
(123)
b
= 3 · (25)
b
1 · b
2
+ 2 · b + 3 = 3 · (2 · b + 5) = 6 · b + 15
b
2
−4b −12 = 0
(b −6)(b + 2) = 0
Kandidati za rjeˇsenja su b
1
= 6 i b
2
= −2. No, iz zadatka vidimo da mora biti b > 5, pa
b
2
ne moˇze biti rjeˇsenje. Za kraj, uvrˇstavamo rjeˇsenje b = 6 u uvjet zadatka:
(123)
6
= 6
2
+ 2 · 6 + 3 = 36 + 12 + 3 = 51 = 3 · 17 = 3 · (25)
6
.
Zakljuˇcujemo da je b = 6 jedino rjeˇsenje drugog dijela zadatka.
1.3. Tra
ˇ
zenje baze 13
U oba sluˇcaja u prethodnom zadatku mogli smo jednostavno utvrditi donju granicu
za b (4 u prvom dijelu, odnosno 6 u drugom dijelu) i onda uvrˇstavanjem u uvjet zadatka
provjeravati kandidate za rjeˇsenja: 4, 5, 6,. . . U oba sluˇcaja bismo odmah pogodili rjeˇsenja,
jer su ona jednaka donjim granicama.
Ipak, takav pristup nikako nije dobar. Kao prvo, za pogodeno rjeˇsenje treba dokazati
da je jedino. Kao drugo, rjeˇsenje moˇze biti puno ve´ce od donje granice i pogadanje moˇze
potroˇsiti mnogo vremena.
Zadatak 1.3.2 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 28. 11. 2005). Nadite sve b-ove
takve da je (123)
2b+3
= (501)
b
Rjeˇsenje. Raspisujemo po definiciji:
(123)
2b+3
= (501)
b
1 · (2b + 3)
2
+ 2 · (2b + 3) + 3 = 5b
2
+ 1
4b
2
+ 16b + 18 = 5b
2
+ 1
b
2
−16b −17 = 0
(b −17)(b + 1) = 0
Kandidati za rjeˇsenja su b
1
= 17 i b
2
= −1. Zbog uvjeta nenegativnosti, b
2
ne moˇze
biti rjeˇsenje. S druge strane, mora vrijediti 2b + 3 > 3 i b > 5. Lako se vidi da b = 17
zadovoljava oba uvjeta. Za kraj, uvrˇstavamo rjeˇsenje b = 17 u uvjet zadatka:
(123)
2·17+3
= (123)
37
= 37
2
+ 2 · 37 + 3 = 1369 + 74 + 3
= 1446 = 5 · 17
2
+ 1 = (501)
17
.
Zakljuˇcujemo da je b = 17 jedino rjeˇsenje zadatka.
Zadatak 1.3.3 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 14. 2. 2005). Nadite sve b-ove
takve da je
(321)
b
+ (321)
b+1
+ (321)
b+2
= (840)
b+3
.
Rjeˇsenje. Raspisujemo po definiciji:
(321)
b
+ (321)
b+1
+ (321)
b+2
= (840)
b+3
9b
2
+ 24b + 24 = 8b
2
+ 52b + 84
b
2
−28b −60 = 0
(b −30)(b + 2) = 0
Kandidati za rjeˇsenja su b
1
= 30 i b
2
= −2. Zbog uvjeta nenegativnosti, b
2
ne moˇze biti
rjeˇsenje. S druge strane, mora vrijediti b > 3, b +1 > 3, b +2 > 3 i b +3 > 8. Lako se vidi
da b = 30 zadovoljava sve te uvjete. Za kraj, uvrˇstavamo rjeˇsenje b = 30 u uvjet zadatka:
(321)
30
+ (321)
30+1
+ (321)
30+2
= (321)
30
+ (321)
31
+ (321)
32
= 2761 + 2946 + 3137 = 8844
= (840)
33
.
Zakljuˇcujemo da je b = 30 jedino rjeˇsenje zadatka.
14 1. Brojevni sustavi
Zadatak 1.3.4 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 27. 6. 2005). Nadite sve b-ove
takve da je
(101)
b
+ (101)
b+2
+ (101)
b+4
= (271)
b+6
.
Rjeˇsenje. Zadatak rjeˇsavamo analogno prethodnom. Jedino rjeˇsenje je b = 23.
Zadatak 1.3.5 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 31. 8. 2005). Nadite sve b-ove
takve da je
(131)
b
+ (131)
b+2
+ (131)
b+4
+ (131)
b+6
= (360)
b+8
.
Rjeˇsenje. Ponovno, raspisom po definiciji dobijamo da je jedino rjeˇsenje b = 24.
Zadatak 1.3.6. Za koje b vrijedi
(123)
b
= (321)
b−12
?
Rjeˇsenje. Raspisom po definiciji dobijemo:
(123)
b
= (321)
b−12
b
2
+ 2b + 3 = 3(b −12)
2
+ 2(b −12) + 1
= 3b
2
−70b + 409
2b
2
−72b + 406 = 0
b
2
−36b + 203 = 0
(b −29)(b −7) = 0
Kandidati za rjeˇsenja su b
1
= 29 i b
2
= 7. No, iz zadatka vidimo da mora vrijediti:
b > 3 i b −12 > 3,
ˇsto ukupno daje b > 15. Zbog toga odbacujemo b
2
, a uvrˇstavanjem b = 29 (primijetimo:
b −12 = 17) u formulu zadatka dobijamo:
(123)
29
= (902)
10
= (321)
17
,
pa je konaˇcno (i jedino) rjeˇsenje zadatka b = 29.
Zadatak 1.3.7. Za koji b vrijedi
(101010)
b
= (10101)
b+1
?
Rjeˇsenje.
(101010)
b
= (10101)
b+1
b
5
+ b
3
+ b = (b + 1)
4
+ (b + 1)
2
+ 1
= b
4
+ 4b
3
+ 6b
2
+ 4b + 1 + b
2
+ 2b + 1 + 1
(b −3)(b
2
+ b + 1)
2
= 0
1.3. Tra
ˇ
zenje baze 15
Jedino realno rjeˇsenje jednadˇzbe je b = 3. Uvrˇstavanjem u formulu zadatka dobijamo:
(101010)
3
= (273)
10
= (10101)
4
.
Uvjet moˇze biti i naizgled sloˇzeniji, no rjeˇsavanje se ponovno svodi na raspis po defi-
niciji i provjeravanje svih potrebnih uvjeta:
Zadatak 1.3.8 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 5. 7. 2006). Neka je zadana
baza b ∈ N. Za koje dvoznamenkaste brojeve (xy)
b
vrijedi da je (xy)
b
· (11)
b
palindrom (u
ovisnosti o parametru b)?
Palindrom je niz znakova (ili znamenaka) koji se jednako ˇcita s lijeva na desno i s
desna na lijevo. Na primjer: 11, 616, ABBA i sl.
Rjeˇsenje. Oznaˇcimo traˇzeni broj s a = (xy)
b
= x · b + y. Tada je
(11)
b
· a = x · b
2
+ (x + y) · b + y
(za svaki b, tj. u svim brojevnim sustavima). Imamo sljede´ce sluˇcajeve:
1. x + y < b ⇒ (11)
b
· a = (x(x + y)y)
b
⇒ x = y <
b
2
2. x+y ≥ b ⇒ 0 ≤ x+y −b < 2 · b, pa broj – rastavljen na znamenke – izgleda ovako:
(x + 1) · b
2
+ (x + y −b) · b + y. Ponovno imamo dva sluˇcaja:
1. x + 1 = b ⇒ (11)
b
· a = (10cy)
b
, gdje je c = x + y − b, pa (zato jer je (11)
b
· a
palindrom), zakljuˇcujemo: y = 1, c = 0. Provjerom uvjeta c = 0 dobijemo:
0 = c = x + y −b = b −1 + 1 −b = 0,
pa je dobiveno rjeˇsenje a = ((b −1)1)
b
dobro.
2. x + 1 < b (tj. x < b − 1, ˇsto znaˇci da je na poˇcetku izraza jedna znamenka).
Tada je y = x + 1 (ˇsto je manje od b, pa je y dobra znamenka).
Konaˇcno rjeˇsenje zadatka, dobiveno spajanjem rjeˇsenja i uvjeta svih sluˇcajeva, je:
a ∈

(xx)
b
, x <
b
2


{((b −1)1)
b
} ∪

(x(x + 1))
b
, x < b −1, x ≥
(b −1)
2

.
16 1. Brojevni sustavi
Neka svojstva dekadskog sustava vrijede i op´cenitije. Dva ´cemo pokazati u sljede´cim
zadacima:
Zadatak 1.3.9. Broj zapisan u bazi b je djeljiv s brojem b−1 (tj. s najve´com znamenkom
u bazi b) ako i samo ako je njegova suma znamenaka djeljiva s b −1.
Primjer ove tvrdnje je djeljivost s 9 u dekadskom sustavu.
Rjeˇsenje. Neka je zadan broj
a = (a
n
a
n−1
. . . a
0
)
b
.
Tada je
a =
n
¸
i=0
a
i
· b
i
=
n
¸
i=0
a
i
· b
i

n
¸
i=0
a
i
+
n
¸
i=0
a
i
=
n
¸
i=0
a
i
· (b
i
−1) +
n
¸
i=0
a
i
.
Primijetimo:
b
i
−1 = (b −1) · (b
i−1
+ b
i−2
+· · · + 1),
pa je b
i
−1 djeljivo s b −1. Zakljuˇcujemo da je a djeljiv s b −1 ako i samo ako je s b −1
djeljivo i
¸
n
i=0
a
i
, ˇsto je upravo suma znamenaka broja a zapisanog u bazi b.
Zadatak 1.3.10. Neka je k ∈ N
0
, te neka je b = 2(2k + 1) paran prirodni broj takav da
je
b
2
neparan. Dokaˇzite da tada broj

b
2
+ 1

i
,
prikazan u bazi b ima zadnju znamenku
b
2
+ 1 za sve i > 0.
Primjer ove tvrdnje je znamenka 6 u dekadskom sustavu (jer je 10 = 2(2 · 2 + 1)).
Rjeˇsenje. Uvedimo oznaku: x =
b
2
+1. Dokaz provodimo indukcijom. Za i = 1, istinitost
tvrdnje je oˇcita. Za i = 2 imamo:
x
2
=

b
2
+ 1

2
=
b
2
4
+ b + 1 =
b
2
4
+
b
2
+
b
2
+ 1
=
b + 2
4
· b + x =
2(2k + 1) + 2
4
· b + x = (k + 1)b + x,
ˇsto pokazuje da je zadnja znamenka broja x
2
prikazanog u bazi b upravo x.
Pretpostavimo da tvrdnja vrijedi za sve i < j, te provjerimo vrijedi li i za j. Kako za
(x)
j−1
b
tvrdnja vrijedi (po pretpostavci), moˇzemo uvesti oznaku
(x)
j−1
b
= yb + x, y ∈ N
0
.
1.3. Tra
ˇ
zenje baze 17
Vrijedi:
(x)
j
b
= (x)
j−1
b
· (x)
b
= (yb + x) · x = xyb + x
2
= xyb + (k + 1)b + x = (xy + k + 1)b + x,
ˇcime smo pokazali da je posljednja znamenka (x)
j
b
zaista x, ˇsto znaˇci da tvrdnja vrijedi i
za j. Prema principu matematiˇcke indukcije, to znaˇci da tvrdnja vrijedi za sve i ∈ N.
Tvrdnja moˇze biti i op´cenitija, jer posljednja znamenka od proizvoljnog x
i
(za i ≥ 1)
ovisi samo o posljednjoj znamenci od x. Dakle, ako su zadovoljeni uvjeti tvrdnje iz
zadatka, i-ta potencija svakog broja sa zadnjom znamenkom
b
2
+ 1 imat ´ce opet zadnju
znamenku
b
2
+ 1 (naravno, ako je broj zapisan u bazi b).
Zadatak 1.3.11. Dokaˇzite da tvrdnja zadatka 1.3.9 ne vrijedi samo za b − 1, nego i za
sve djelitelje od b −1 (npr. djeljivost s 3 u dekadskoj bazi).
Zadatak 1.3.12. Broj a = (a
n
a
n−1
. . . a
0
) zapisan u bazi b je djeljiv s brojem b + 1 (tj. s
(11)
b
) ako i samo ako je broj
n
¸
i=0
(−1)
n
a
i
= a
0
−a
1
+ a
2
−a
3
+ . . .
takoder djeljiv s b + 1.
Rjeˇsenje. Tvrdnju je jednostavno dokazati upotrebom kongruencija, ali moˇze i direktno,
primjenom sljede´cih identiteta:
x
n
+ y
n
= (x + y)(x
n−1
−x
n−2
y +· · · −xy
n−1
+ y
n−1
), n paran,
x
n
−y
n
= (x + y)(x
n−1
−x
n−2
y +· · · + xy
n−1
−y
n−1
), n neparan.
Pretpostavimo da je n neparan (tj. da broj ima parno mnogo znamenaka). Tada je
a =
n
¸
i=0
a
i
b
i
=
(n−1)/2
¸
i=0
(a
2i
b
2i
+ a
2i+1
b
2i+1
)
=
(n−1)/2
¸
i=0

(a
2i
b
2i
+ a
2i+1
b
2i+1
) + (a
2i
−a
2i+1
)


(n−1)/2
¸
i=0
(a
2i
−a
2i+1
)
=
(n−1)/2
¸
i=0
(a
2i
(b
2i
+ 1) + a
2i+1
(b
2i+1
−1)) −
(n−1)/2
¸
i=0
(a
2i
−a
2i+1
)
=
(n−1)/2
¸
i=0
(a
2i
(b + 1)p
i
+ a
2i+1
(b + 1)q
i
) −
(n−1)/2
¸
i=0
(a
2i
−a
2i+1
)
= (b −1)
(n−1)/2
¸
i=0
(a
2i
p
i
+ a
2i+1
q
i
) −
(n−1)/2
¸
i=0
(a
2i
−a
2i+1
)
. .. .
=
P
n
i=0
(−1)
n
a
i
,
18 1. Brojevni sustavi
pri ˇcemu su p
i
i q
i
ostaci nakon izluˇcivanja b + 1 iz b
2i
+ 1 i b
2i+1
− 1 (respektivno). Ti
ostaci su cijeli brojevi, prema formulama za rastavljanje x
n
+ y
n
i x
n
−y
n
.
Ako je n paran (tj. n −1 je neparan), onda iz broja a izdavajamo vode´cu znamenku,
te na preostalih n −1 znamenaka primjenjujemo prethodni rezultat:
a =
n
¸
i=0
a
i
b
i
= a
n
+
n−1
¸
i=0
a
i
b
i
= (b −1)
(n−2)/2
¸
i=0
(a
2i
p
i
+ a
2i+1
q
i
) + a
n

(n−2)/2
¸
i=0
(a
2i
−a
2i+1
)
. .. .
=
P
n
i=0
(−1)
n
a
i
.
Alternativno, broj s neparno mnogo znamenaka (n paran) moˇzemo promatrati i kao broj
s jednom znamenkom viˇse, tako da definiramo a
n+1
:= 0.
Primjer ove tvrdnje je djeljivost s 11 u dekadskom sustavu.
Poglavlje 2
Raˇcun sudova
Sud ili izjava je svaka (smislena) reˇcenica ˇciju istinitost moˇzemo utvrditi, tj. koja je ili
istinita ili laˇzna. Na primjer:
• 17 + 19 = 36 (sud, istinit)
• 17 > 19 (sud, laˇzan)
• 17 > x (nije sud, dok god ne znamo koliki je x)
• Popocat´epetl je aktivni vulkan u
ˇ
Cileu (sud, laˇzan; Popocat´epetl se nalazi u Mek-
siku).
• Ho´cu li uspjeti poloˇziti ovaj kolegij? (nije sud, jer ne iskazuje tvrdnju ˇciju bismo
istinitost mogli provjeriti)
Jednostavne sudove zamjenjujemo sudovnim varijablama (najˇceˇs´ce ih oznaˇcavamo ve-
likim ili malim latiniˇcnim slovima), te od njih slaˇzemo sloˇzene izjave pomo´cu logiˇckih
operatora. Uz varijable, imamo i dvije konstante: 1 (istina, true, ⊤) i 0 (laˇz, false, ⊥).
Operatori koje obiˇcno koristimo prikazani su u tablici 2.1.
Operator negacije ima najve´ci prioritet; zatim dolazi operator konjukcije, te zatim
operator disjunkcije i iskljuˇcivo ILI (oni imaju jednake prioritete). Nakon njih dolaze
implikacija i, nakon nje, ekvivalencija.
Ako niste sigurni koji su prioriteti operatora, piˇsite zagrade!
2.1 Tablice istinitosti
Istinitost pojedine formule moˇzemo jednostavno provjeriti tzv. tablicom istinitosti.
Zadatak 2.1.1. Za koje vrijednosti a i b je formula a + b istinita?
19
20 2. Ra
ˇ
cun sudova
Naziv
hrv. engl. Simboli Opis
I AND ·, ∧ a · b je istina ako i samo ako su i a i
b istiniti
ILI OR +, ∨ a + b je istina ako i samo ako je a
istinit ili b istinit (ili oba)
NE NOT a, ¬a a je istina ako i samo ako je a laˇz
iskljuˇcivo
ILI
XOR ⊕ a ⊕b je istina ako i samo ako je ili a
istinit ili b istinit (ali ne oba)
Tablica 2.1: Opisi nekih logiˇckih operatora
Rjeˇsenje. Tablicu istinitosti slaˇzemo navodenjem svih kombinacija vrijednosti varijabli a
i b, te raˇcunanjem vrijednosti formule za svaku kombinaciju:
Tijekom postupka, preporuˇcljivo je raˇcunati i podizraze, na primjer b.
a b b a + b
0 0 1 1
0 1 0 0
1 0 1 1
1 1 0 1
Dakle, formula a + b je istinita ako je a istinit ili b laˇzan.
Logiˇcke operatore moˇzemo zadati pomo´cu tablice istinitosti (v. tablicu 2.1). Iz pri-
loˇzene tablice istinitosti odmah vidimo da vrijedi:
(a ⇔ b) = a ⊕b.
a b a + b a · b a a ⇒ b a ⇔ b a ⊕b
0 0 0 0 1 1 1 0
0 1 1 0 1 1 0 1
1 0 1 0 0 0 0 1
1 1 1 1 0 1 1 0
Tablica 2.2: Logiˇcki operatori
Napomena 2.1.1 (Varijable u tablici istinitosti). Tablica istinitosti za k varijabli ima 2
k
redaka. Pri tome, najlakˇse je prvi stupac popuniti s 2
k−1
nula, te s 2
k−1
jedinica, drugi
2.1. Tablice istinitosti 21
stupac s 2
k−2
nula i 2
k−2
jedinica, te opet 2
k−2
nula i 2
k−2
jedinica, idu´ci opet s dvostruko
manjim grupicama nula i jedinica itd. U stupcu posljednje varijable trebaju ispasti nule i
jedinice naizmjence.
Zadatak 2.1.2. Dokaˇzite:
a + a = 1, a · a = 0.
Uputa. Sloˇzite tablicu istinitosti za varijablu a (trebala bi imati dva retka).
Zadatak 2.1.3. Sloˇzite tablicu istinitosti za izraz
f = (a + b) · (c + d).
Rjeˇsenje. Kako ovdje imamo ˇcetiri varijable, tablica istinitosti imat ´ce 2
4
= 16 redaka
(ovdje rastavljeno u 8 + 8 redaka):
a b c d a + b c + d f a b c d a + b c + d f
0 0 0 0 0 0 0 1 0 0 0 1 0 0
0 0 0 1 0 1 0 1 0 0 1 1 1 1
0 0 1 0 0 1 0 1 0 1 0 1 1 1
0 0 1 1 0 1 0 1 0 1 1 1 1 1
0 1 0 0 1 0 0 1 1 0 0 1 0 0
0 1 0 1 1 1 1 1 1 0 1 1 1 1
0 1 1 0 1 1 1 1 1 1 0 1 1 1
0 1 1 1 1 1 1 1 1 1 1 1 1 1
Zadatak 2.1.4. Pomo´cu tablica istinitosti dokaˇzite sljede´ce vaˇzne identitete:
a) De Morganove formule:
a + b = a · b, a · b = a + b,
b) Negacija implikacije:
a ⇒ b = a · b,
c) Obrat po kontrapoziciji:
(a ⇒ b) = (b ⇒ a)
d) (a ⇔ b) = (a ⇒ b) · (b ⇒ a).
22 2. Ra
ˇ
cun sudova
Rjeˇsenje. Pokazat ´cemo da vrijede De Morganove formule:
a b a + b a +b a b a · b a · b a · b a +b
0 0 0 1 1 1 1 0 1 1
0 1 1 0 1 0 0 0 1 1
1 0 1 0 0 1 0 0 1 1
1 1 1 0 0 0 0 1 0 0
Istinitost ostalih tvrdnji provjerite za vjeˇzbu.
Zadatak 2.1.5. Politiˇcar N. T. (Nema Takvog) nikada ne laˇze, osim srijedom kada samo
laˇze. Koje dane u tjednu on moˇze re´ci:
a) “Juˇcer sam govorio istinu i lagat ´cu sutra”?
b) “Prekjuˇcer sam lagao, a danas i sutra govorit ´cu istinu”?
c) “Ako nisam lagao juˇcer, lagat ´cu sutra”?
d) “Ako danas i sutra govorim istinu, prekosutra ´cu lagati”.
e) “Ako danas i sutra laˇzem, prekosutra ´cu govoriti istinu”.
Je li izjava pod d) negacija izjave pod e)?
Rjeˇsenje. Ovdje nas ne zanima kad je neka izjava istinita, nego kad se podudara s onime
ˇsto N. T. priˇca. Drugim rijeˇcima, zanima nas kad je
izjava ⇔ p,
gdje je p istina sve dane osim srijede (kad je laˇz).
Rijeˇsimo zadatak pod a). Poˇcinjemo uvodenjem pomo´cnih varijabli:
a = “Juˇcer sam govorio istinu”
b = “Lagat ´cu sutra”
Zanima nas kad se istinitost od p poklapa s istinitoˇs´cu od a · b.
Dan a b p a · b p ⇔ (a + b)
pon 1 0 1 0 0
uto 1 1 1 1 1
sri 1 0 0 0 1
ˇcet 0 0 1 0 0
pet 1 0 1 0 0
sub 1 0 1 0 0
ned 1 0 1 0 0
2.2. Normalne forme 23
Dakle, u tablici pratimo kad je formula a · b istinita, a na kraju (posljednji stupac) pro-
vjeravamo kad se njena istinitost poklapa s istinitoˇs´cu tvrdnji koje taj dan govori N. T,
jer on istinu moˇze re´ci svaki dan osim srijede, a srijedom moˇze re´ci samo laˇz. Zbog toga
je konaˇcno rjeˇsenje: utorak i srijeda, jer je u utorak izjava istinita (a on utorkom govori
istinu), dok je u srijedu izjava laˇzna (a on srijedom laˇze). Ostale dane, izjava je laˇzna, a
on bi trebao govoriti istinu, pa zato takvu izjavu ne moˇze dati.
Ostale tvrdnje provjerite za vjeˇzbu. Rjeˇsenja su:
a) utorak i srijeda,
b) srijeda i petak,
c) utorak, srijeda i ˇcetvrtak
d) ponedjeljak i utorak
e) svi dani osim srijede (jer je lijeva strana inkluzije – “danas i sutra (dva uzastopna
dana) laˇzem” – uvijek laˇzna, pa je inkluzija uvijek istinita).
Iz priloˇzenog je jasno i da izjave pod d) i pod e) nisu jedna drugoj negacije. Izjava koja bi
bila negacija izjavi pod d), za rjeˇsenje bi imala “svi dani osim ponedjeljka i utorka”.
2.2 Normalne forme
Zadatak 2.2.1. Dokaˇzite da se svaka formula raˇcuna sudova moˇze prikazati samo pomo´cu
negacije (operator NE), konjukcije (operator I) i disjunkcije (operator ILI).
Rjeˇsenje. Ostale operacije (implikacija, ekvivalencija, iskljuˇcivo ILI) prikazat ´cemo na taj
naˇcin:
(a ⇒ b) = a · b + a · b + a · b,
(a ⇔ b) = a · b + a · b,
(a ⊕b) = a · b + a · b,
(a ⇒ b) = a + b,
(a ⇔ b) = (a + b) · (a + b),
(a ⊕b) = (a + b) · (a + b).
Za vjeˇzbu provjerite ispravnost navedenih formula.
Primijetite da, primjenom De Morganovih pravila, moˇzemo eliminirati i sve disjunkcije
ili sve konjukcije, tj. da sve formule raˇcuna sudova moˇzemo prikazati pomo´cu negacije i
samo konjukcije ili samo disjunkcije.
Kako dobiti formulu ako je zadana tablica istinitosti? Postoji viˇse naˇcina.
24 2. Ra
ˇ
cun sudova
Algoritam 2.2.1 (Konjunktivna normalna forma). U tablici istinitosti gledamo sve retke
koji sadrˇze nulu (laˇz) u rezultatu. Reci su oblika:
a
1
a
2
. . . a
n
f
.
.
.
.
.
.
.
.
.
.
.
.
v
1
v
2
. . . v
n
0
.
.
.
.
.
.
.
.
.
.
.
.
Za svaki takav redak kreiramo izraz:
B
i
= b
1
+ b
2
+· · · + b
n
,
gdje je
b
j
=

a
j
, v
j
= 1
a
j
, v
j
= 0
.
Konjunktivna normalna forma (KNF) izraza f je
B
1
· B
2
· · · · · B
k
,
gdje je k broj nula u stupcu koji odgovara izrazu f u tablici istinitosti.
Pojednostavljeno reˇceno: gledamo nule u rezultatu, negiramo varijable koje imaju vri-
jednost jedan (ostale ne mijenjamo), “zbrajamo” te varijable (i negirane i nepromijenje-
ne), te radimo “umnoˇzak” tako dobivenih “suma”.
Algoritam 2.2.2 (Disjunktivna normalna forma). U tablici istinitosti gledamo sve retke
koji sadrˇze jedinicu (istinu) u rezultatu. Reci su oblika:
a
1
a
2
. . . a
n
f
.
.
.
.
.
.
.
.
.
.
.
.
v
1
v
2
. . . v
n
1
.
.
.
.
.
.
.
.
.
.
.
.
Za svaki takav redak kreiramo izraz:
B
i
= b
1
· b
2
· · · · · b
n
,
gdje je
b
j
=

a
j
, v
j
= 1
a
j
, v
j
= 0
.
Disjunktivna normalna forma (DNF) izraza f je
B
1
+ B
2
+· · · + B
k
,
2.2. Normalne forme 25
gdje je k broj jedinica u stupcu koji odgovara izrazu f u tablici istinitosti.
Pojednostavljeno reˇceno: gledamo jedinice u rezultatu, negiramo varijable koje imaju
vrijednost nula (ostale ne mijenjamo), “mnoˇzimo” te varijable (i negirane i nepromije-
njene), te radimo “zbroj” tako dobivenih “produkata”.
Rjeˇsenje zadatka 2.2.1 pomo´cu normalnih formi. Da bismo rijeˇsili zadatak, potrebno je
prvo sloˇziti tablicu istinitosti za operatore implikacije, ekvivalencije i iskljuˇcivog ILI. Iz-
nimno, oznaˇcit ´cemo i brojeve redaka (prvi stupac) za potrebe objaˇsnjavanja postupka:
a b a ⇒ b a ⇔ b a ⊕b
1. 0 0 1 1 0
2. 0 1 1 0 1
3. 1 0 0 0 1
4. 1 1 1 1 0
Konjunktivnu normalnu formu za formulu a ⇒ b dobijemo promatranjem tre´ceg retka
(jer se samo u njemu nalazi nula u stupcu koji odgovara formuli a ⇒ b). U tom retku,
varijabla a ima vrijednost 1, a varijabla b ima vrijednost 0. Prema algoritmu 2.2.1,
trebamo negirati varijablu a i varijablu b ostaviti nepromijenjenu, te zbrojiti dobiveno:
B
1
= a + b.
Kako se nula nalazi samo u tre´cem retku, to je B
1
jedini u konjunktivnoj normalnoj formi
za a ⇒ b, pa je konaˇcno rjeˇsenje
(a ⇒ b) = a + b.
Disjunktivnu normalnu formu za formulu a ⇒ b dobijemo promatranjem redaka koji
sadrˇze jedinice (to su reci 1, 2 i 4). U prvom retku, i varijabla a i varijabla b imaju
vrijednost nula, pa ih – prema algoritmu 2.2.2 – negiramo, ˇsto znaˇci da je
B
1
= a · b.
U drugom retku, varijabla a ima vrijednost nula (pa ju negiramo), dok varijabla b ima
vrijednost 1 (pa ostaje nepromijenjena). Dakle,
B
2
= a · b.
Analogno, za tre´ci redak imamo:
B
3
= a · b.
Konaˇcno rjeˇsenje je:
(a ⇒ b) = (a · b) + (a · b) + (a · b).
Na sliˇcan naˇcin rijeˇsite formule a ⇔ b i a ⊕ b (rjeˇsenja, do na poretke operanada,
moraju biti jednaka onima iz originalnog rjeˇsenja zadatka).
26 2. Ra
ˇ
cun sudova
Napomena 2.2.1. Primijetite: ako imamo n varijabli,
• tablica istinitosti imat ´ce 2
n
redaka (ne raˇcunaju´ci naslovni redak).
• ukupni broj B-ova u konjunktivnoj i disjunktivnoj normalnoj formi bit ´ce takoder
2
n
.
Napomena 2.2.2. Generalno, ako je mogu´ce birati koju normalnu formu koristiti, dobro
je koristiti konjunktivnu ako ima malo jedinica, a disjunktivnu ako ima malo nula. Ipak,
ako se oˇcekuje i pojednostavljivanje izraza (poglavlje 2.3), ˇcesto je praktiˇcnije koristiti
disjunktivnu normalnu formu jer kod nje nije potrebno “izmnoˇziti” elemente u zagradama.
Zadatak 2.2.2. Napiˇsite formule raˇcuna sudova za izraze f, g i h odredene sljede´com
tablicom istinitosti (zbog preglednosti je podijeljena je u dva dijela):
a b c f g h a b c f g h
0 0 0 1 1 0 1 0 0 0 1 0
0 0 1 1 1 0 1 0 1 0 1 1
0 1 0 0 0 1 1 1 0 0 0 0
0 1 1 1 1 0 1 1 1 1 1 0
Rjeˇsenje. U zadatku ne piˇse koju normalnu formu treba napisati (dapaˇce, ne piˇse niti da
trebaju biti normalne forme), pa moˇzemo birati. Za izraz f je svejedno koju normalnu
formu izaberemo jer tom izrazu odgovara jednag broj jedinica i nula. Napisat ´cemo obje
normalne forme za f:
KNF: f = (a + b + c) · (a + b + c) · (a + b + c) · (a + b + c),
DNF: f = a · b · c + a · b · c + a · b · c + a · b · c.
Izrazu g odgovaraju dvije nule i ˇcak ˇsest jedinica, pa je lakˇse napisati konjunktivnu nor-
malnu formu:
g = (a + b + c) · (a + b + c).
Izrazu h odgovara ˇcak ˇsest nula i samo dvije jedinice, pa je lakˇse napisati disjunktivnu
normalnu formu:
h = a · b · c + a · b · c.
Interaktivnu vjeˇzbalicu za normalne forme moˇzete na´ci na adresi
http://degiorgi.math.hr/prog1/apps/knfdnf.pl
2.3. Pojednostavljivanje logi
ˇ
ckih izraza 27
2.3 Pojednostavljivanje logiˇckih izraza
Formule izraˇzene u normalnim formulama u pravilu su komplicirane. Primjenom jed-
nostavnih identiteta (poput De Morganovih pravila), formule moˇzemo znaˇcajno pojed-
nostaviti, ˇsto je izuzetno vaˇzno u primjenama. Na primjer, logiˇcki izraz moˇze predstav-
ljati uvjet koji neki program treba izvrˇsiti (v. zadatak 7.1.4), pa njegova sloˇzenost moˇze
znaˇcajno usporiti ili ubrzati izvodenje programa. Takoder, logiˇcki izraz moˇze predstavljati
i elektroniˇcki sklop koji treba sastaviti. Kompliciraniji sklop (koji je rezultat komplicira-
nijeg izraza) ima viˇse elemenata, ˇsto povlaˇci ve´cu cijenu, ve´cu potroˇsnju energije, sporije
izvodenje operacija i ve´ci konaˇcni sklop.
U praksi, ve´cina elektroniˇckih sklopova (iznimka je DRAM) sastoji se od NAND-vrata
(NOT AND) i NOR-vrata (NOT OR) s tri ili viˇse ulaza.
Neke od formula koje mogu pomo´ci prilikom pojednostavljivanja logiˇckih izraza nave-
dene su u tablici 2.3.
1. a + b = b + a a · b = b · a
2. a + (b + c) = (a + b) + c a · (b · c) = (a · b) · c
3. a + 0 = a a · 0 = 0
4. a + 1 = 1 a · 1 = a
5. a + a = a a · a = a
6. a · (b + c) = a · b + a · c a + b · c = (a + b) · (a + c)
7.
¯
¯ a = a
8.
¯
1 = 0
¯
0 = 1
9. ¯ a + a = 1 ¯ a · a = 0
10. a + ¯ a · b = a + b a · (¯ a + b) = a · b
11. a + b = ¯ a ·
¯
b a · b = ¯ a +
¯
b
12. a + a · b = a a · (a + b) = a
13. a · b + ¯ a · c + b · c = a · b + ¯ a · c
(a + b) · (¯ a + c) · (b + c) = (a + b) · (¯ a + c)
Tablica 2.3: Neke formule za pojednostavljivanje logiˇckih izraza
Napomena 2.3.1 (
ˇ
Cesta greˇska). U raˇcunu sudova NE VRIJEDI 1 + 1 = 2; ˇstoviˇse,
u raˇcunu sudova 2 uop´ce nema nikakvo znaˇcenje!
Zadatak 2.3.1. Dokaˇzite formule iz tablice 2.3 pomo´cu tablica istinitosti.
Zadatak 2.3.2. Pojednostavite formule raˇcuna sudova:
a) f = a · b · c + a · b · c + a · b · c,
28 2. Ra
ˇ
cun sudova
b) g = a · b · c + a · b · c + a · b · c + a · b · c,
c) h = c · a + c · b · c · a + c + b,
d) k = a · b · (a + b) + a · b · b + a.
Op´cenito, formule je najlakˇse pojednostaviti tako da ih se svede na disjunktivnu formu
(ne nuˇzno normalnu, tj. ne mora svaki sumand sadrˇzavati sve varijable). Zatim se spretnim
izluˇcivanjem i sliˇcnim pravilima (v. tablicu 2.3) formula pojednostavljuje.
Rjeˇsenje.
a) Poˇcinjemo izluˇcivanjem zajedniˇckog podizraza (a·c) iz prva dva elementa disjunkcije:
f = a · b · c + a · b · c + a · b · c
= a · c · (b + b
....
=1
) + a · b · c
= a · c + a · b · c = a · ( c + b · c
. .. .
=b+c (pr. 10)
)
= a · (b + c).
b) Primijetimo:
g = f + a · b · c i b + c = b + c + b · c.
Sada imamo:
g = f + a · b · c = a · (b + c) + a · b · c
= a · (b + c + b · c) + a · b · c
= a · (b + c) + a · b · c + a · b · c
= a · (b + c) + (a + a) · b · c
= a · (b + c) + b · c.
Moˇzemo i direktno:
g = a · b · c + a · b · c + a · b · c + a · b · c
= (a + a) · b · c + a · b · c + a · b · c
= b · c + a · b · c + a · b · c
= (b + a · b) · c + a · b · c
= (a + b) · c + a · b · c = a · c + b · c + a · b · c
= a · (c + b · c) + b · c = a · (b + c) + b · c
= a · b + a · c + b · c.
2.3. Pojednostavljivanje logi
ˇ
ckih izraza 29
Primijetite da formula a · b + a · c + b · c ima 5 operatora, dok prethodna formula,
a· (b+c)+b· c, ima samo 4. Zbog toga kao rjeˇsenje uzimamo formulu a· (b+c)+b· c.
Inaˇce, ovisno o izboru izluˇcivanja, mogli smo dobiti i druga, jednako dobra rjeˇsenja.
Na primjer:
a · b + (a + b) · c.
c) Ovdje kre´cemo s viˇsestrukom primjenom De Morganovih pravila kako bismo se ri-
jeˇsili sloˇzenih izraza ispod negacija (jer s njima najˇceˇs´ce ne moˇzemo niˇsta napraviti):
h = c · a + c · b · c · a + c + b
= c · a + c · b + c · a + c · b
= c · a + c · b + c · a + c · b
= a · (c + c) + (c + c) · b = a + b.
Kao ˇsto vidimo, konaˇcna formula ne mora sadrˇzavati sve varijable.
d) Ponovno kre´cemo primjenom De Morganovih pravila, te “mnoˇzenjem” zagrada:
k = a · b · (a + b) + a · b · b + a
= a · b · a
. .. .
=a·b
+a · b · b
. .. .
=0
+(a + b) · (a · b)
= a · b + a · a · b + b · a · b
. .. .
=0
= a · b + a · b
= (a + a) · b = b.
Prilikom pojednostavljivanja, svaka dobivena formula mora biti ekvivalentna poˇcetnoj.
Jednakost formula moˇzete provjeriti na sluˇzbenoj stranici kolegija:
http://degiorgi.math.hr/prog1/apps/logika_sudova.pl
Zadatak 2.3.3 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 14.2.2005). Definirajte formulu
raˇcuna sudova koja kao ulaz uzima binarne znamenke x
0
, x
1
i x
2
, te vra´ca 1 ako se broj
(x
2
x
1
x
0
)
2
moˇze prikazati kao umnoˇzak dva prosta broja. Inaˇce vra´ca 0. Pojednostavite
dobiveni izraz!
Napomena 2.3.2 (
ˇ
Cesta greˇska). Broj 1 nije ni prost ni sloˇzen!
Rjeˇsenje. Najprije slaˇzemo tablicu istinitosti:
x
2
x
1
x
0
(x
2
x
1
x
0
)
2
f x
2
x
1
x
0
(x
2
x
1
x
0
)
2
f
0 0 0 0 0 1 0 0 4 1 (4 = 2 · 2)
0 0 1 1 0 1 0 1 5 0
0 1 0 2 0 1 1 0 6 1 (6 = 2 · 3)
0 1 1 3 0 1 1 1 7 0
30 2. Ra
ˇ
cun sudova
Sada vidimo i zaˇsto je ovakav raspored varijabli dobar: brojevi koje one daju (ako ih
interpretiramo kao binarne znamenke) idu po redu od 0 do 2
n
−1, gdje je n broj varijabli
(ovdje je n = 3).
Problem je oˇcito lakˇse rijeˇsiti pomo´cu disjunktivne, nego pomo´cu konjunktivne nor-
malne forme jer imamo samo dvije jedinice i ˇcak ˇsest nula:
f = x
2
· x
1
· x
0
+ x
2
· x
1
· x
0
= x
2
· x
0
.
Zadatak 2.3.4 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 22.4.2002). Napiˇsite formulu
raˇcuna sudova (koja se sastoji samo od operatora ILI i negacije) koja za ulaz x = (x
2
x
1
x
0
)
2
provjerava je li x nultoˇcka funkcije f(x) = x
3
−x
2
−4x + 4.
Upute. Izraˇcunajte nultoˇcke funkcije ili uvrstite sve mogu´ce vrijednosti x (cijeli brojevi
od 0 do 7), te napiˇsite tablicu istinitosti. Zatim izvedite konjunktivnu ili disjunktivnu
normalnu formu, te primjenom De Morganovih pravila eliminirajte sve konjukcije.
2.4 Osnovni sklopovi
Kao ˇsto smo naveli, logiˇcki izrazi ˇcesto se koriste prilikom izrade elektroniˇckih sklopova.
Izraze moˇzemo i nacrtati, na naˇcin da svaki operator zamijenimo odgovaraju´cim sklopom,
koje zatim povezujemo u cjelinu. Sklopovi koji odgovaraju osnovnim operatorima su dani
su u tablici 2.4.
Simbol Naziv Oznake
negacija a, ¬a
konjukcija a · b, a ∧ b
disjunkcija a + b, a ∨ b
iskljuˇcivo ILI a ⊕b
Tablica 2.4: Osnovni sklopovi
Sklop gradimo tako da svakoj varijabli dodijelimo jednu ulaznu “ˇzicu” (liniju), te ju
povezujemo sa sklopovima koji odgovaraju operatorima koje ti sklopovi predstavljaju. Na
isti naˇcin nastavljamo gradnju s izlazima iz sklopova.
Primjer 2.4.1. Nacrtajmo sklop koji odgovara izrazu
f = a + b · c + a · c.
Rjeˇsenje je priloˇzeno na slici 2.1.
“Mosti´ci” pokraj varijabli b i c sluˇze da se naglasi da se “ˇzica” od a ne sijeˇce sa “ˇzicama”
od b i c.
2.5. Poluzbrajalo i potpuno zbrajalo 31
a
b
f
c
Slika 2.1: Sklop f = a + b · c + a · c
Zadatak 2.4.1. Nacrtajte sklopove koji odgovaraju originalnim i pojednostavljenim izra-
zima iz zadatka 2.3.2.
Napomena 2.4.1. Ponekad se u operatore ubacuje viˇse ulaznih “ˇzica” nego je to uobiˇca-
jeno, kao – na primjer – kod sklopa AND na slici 2.2. Time se ˇzeli skra´ceno prikazati izraz
a
b
c
Slika 2.2: Sklop AND s tri ulazne “ˇzice”
a · b · c. Ipak, iako je nacrtan samo jedan sklop, on je samo pokrata i zato se broji
kao dva sklopa! Ovakvim “zahvatima” u crtanju ne smanjujete broj operatora/sklopova
u rjeˇsenju zadatka!
2.5 Poluzbrajalo i potpuno zbrajalo
Zadatak 2.5.1 (Poluzbrajalo). Konstruirajte (nacrtajte) poluzbrajalo (engl. half adder),
tj. sklop koji ima ulaze x i y (jednoznamenkasti binarni brojevi), te izlaze s (sum) i c
(carry) za koje vrijedi:
s = znamenka jedinica u sumi x + y
c = znamenka desetica u sumi x + y
Oˇcito, s predstavlja “sumu”, a c “jedan dalje” prilikom zbrajanja dva binarna broja.
Rjeˇsenje. Sastavimo tablicu istinitosti za s i c:
x y c s
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 0
32 2. Ra
ˇ
cun sudova
Primijetite: x + y = (sc)
2
.
Izraze nalazimo pomo´cu normalnih formi:
DNF: c = x · y
KNF: s = (x + y) · (x + y) = (x + y) · x · y
Konaˇcno, moˇzemo nacrtati poluzbrajalo (v. sliku 2.3).
x
y
c
s
Slika 2.3: Poluzbrajalo
Poluzbrajalo oznaˇcavamo kao na slici 2.4. Kako izrazi c i s ne komutiraju, prilikom
H.A. c
s
Slika 2.4: Simbol poluzbrajala
crtanja poluzbrajala nuˇzno je naglasiti koji je koji (tj. na svaku izlaznu “ˇzicu” napisati
je li ona s ili c).
Zadatak 2.5.2 (Potpuno zbrajalo). Konstruirajte (nacrtajte) potpuno zbrajalo (engl. full
adder), tj. sklop koji ima ulaze x, y i z (jednoznamenkasti binarni brojevi), te izlaze s
(sum) i c (carry) za koje vrijedi:
s = znamenka jedinica u sumi x + y + z
c = znamenka desetica u sumi x + y + z
Oˇcito, s predstavlja “sumu”, a c “jedan dalje” prilikom zbrajanja tri binarna broja.
2.5. Poluzbrajalo i potpuno zbrajalo 33
Rjeˇsenje. Sastavimo tablicu istinitosti za s i c:
x y z c s
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1
Primijetite: x + y + z = (sc)
2
.
Izraze moˇzemo lako dobiti pomo´cu normalnih formi (napravite to sami za vjeˇzbu). No,
potpuno zbrajalo moˇzemo nacrtati i koriste´ci poluzbrajala, simuliraju´ci time zbrajanje
“znamenku po znamenku” (v. sliku 2.5). Suma x + y + z ima jednaku zadnju znamenku
H.A.
H.A.
z
x
y
c
s
c
1
c
2
s
1
s
2
Slika 2.5: Potpuno zbrajalo
kao i suma s
1
+z (pri ˇcemu je s
1
zadnja znamenka sume x+y), a prenosimo “jedan dalje”
ako imamo “jedan dalje” u bilo kojem od ta dva zbrajanja (tj. ako je c
1
jednak 1 ili ako
je c
2
jednak 1).
Potpuno zbrajalo oznaˇcavamo kao na slici 2.6. Kako izrazi c i s ne komutiraju, prilikom
F.A. c
s
Slika 2.6: Simbol potpunog zbrajala
crtanja potpunog zbrajala (kao i kod poluzbrajala) nuˇzno je naglasiti koji je koji (tj.
na svaku izlaznu “ˇzicu” napisati je li ona s ili c).
34 2. Ra
ˇ
cun sudova
Zadatak 2.5.3. Konstruirajte sklop koji zbraja dva 3-bitna binarna broja x = (x
2
x
1
x
0
)
2
i y = (y
2
y
1
y
0
)
2
.
Rjeˇsenje. Tablica istinitosti bi imala 2
6
= 64 retka, ˇsto je velik posao. Zbog toga ´cemo
simulirati zbrajanje “na ruke” (slika 2.7). Prvo zbrajamo zadnje znamenke brojeva: x
0
+
H.A. F.A. F.A.
0
1
1
2
2
0
x
x
x
y
y
y
c
0
c
1
c
2
s
0
s
1
s
2
z
0
z
1
z
2
z
3
Slika 2.7: Sklop za zbrajanje troznamenkastih binarnih brojeva
y
0
. Rezultat tog zbroja daje posljednju znamenku konaˇcnog rezultata z
0
i, eventualno,
“jedan dalje” (oznaˇcimo ga s c
0
). U drugom koraku zbrajamo c
0
+ x
1
+ y
1
; rezultar ´ce
biti znamenka z
1
i, eventualno, “jedan dalje” (oznaˇcimo ga s c
1
). Konaˇcno, zbrajamo
c
1
+ x
2
+ y
2
; rezultat tog zbrajanja je (c
2
s
2
)
2
, ˇsto su prve dvije znamenke konaˇcnog
rezultata (tj. c
2
= z
3
, s
2
= z
2
).
2.6 Dodatni zadaci
Zadatak 2.6.1. Konstruirajte logiˇcke sklopove za 7-segmentni indikator s 3-bitnim ulazom
(tj. za brojeve od 0 do 7).
Uputa. U ovom zadatku je sadrˇzano sedam istovjetnih zadataka. Svaki broj od 0 do 7
f
1
f
2
f
3
f
4
f
5
f
6
f
7
Slika 2.8: 7-segmentni indikator s prikazanim brojem 3
treba nacrtati kao ˇsto ga iscrtava kalkulator (pri tome se broj 1 moˇze nacrtati na dva
naˇcina; izaberite jedan). Za svaki od brojeva, neke od dioda f
1
− f
7
´ce biti upaljene
2.6. Dodatni zadaci 35
(stanje 1), a neke ´ce biti ugaˇsene (stanje 0). Potrebno je sastaviti tablicu istinitosti za
sve brojeve, te pomo´cu konjunktivnih ili disjunktivnih normalnih formi dobiti formule za
pojedine f
i
. Na kraju, te formule treba pojednostaviti i nacrtati pripadne sklopove.
Pazite: tablicu je najlakˇse popuniti po recima (tj. za svaki x = (x
2
x
1
x
0
)
2
popuniti
nulama i jedinicama stupce f
1
− f
7
ovisno o tome koja dioda svjetli za prikaz broja x),
ali normalne forme moramo konstruirati po stupcima (tj. jednu za f
1
, jednu za f
2
, itd).
Neka od rjeˇsenja koje trebate dobiti (uz pretpostavku da smo broj 1 dobili paljenjem
f
3
i f
6
, a ne f
2
i f
5
):
f
1
= (x
0
+ x
1
+ x
2
) · (x
0
+ x
1
+ x
2
)
= x
0
· x
0
+ x
0
· x
1
+ x
0
· x
2
+ x
1
· x
0
+ x
1
· x
1
+ x
1
· x
2
+ x
2
· x
0
+
x
2
· x
1
+ x
2
· x
2
= x
1
· (x
0
+ x
0
+ 1 + x
2
+ x
2
) + x
0
· x
2
+ x
0
· x
2
= x
1
+ x
0
· x
2
+ x
0
· x
2
= x
1
+ x
0
· x
2
+ x
0
+ x
2
,
f
2
= x
0
· x
1
· x
2
+ x
0
· x
1
· x
2
+ x
0
· x
1
· x
2
+ x
0
· x
1
· x
2
= x
0
· x
1
(x
2
+ x
2
) + x
0
· x
1
· x
2
+ x
0
· x
1
· x
2
= x
1
· (x
0
+ x
0
· x
2
) + x
0
· x
1
· x
2
= x
1
· (x
0
+ x
2
) + x
0
· x
1
· x
2
= x
1
· x
0
+ x
1
· x
2
+ x
0
· x
1
· x
2
= x
0
· x
1
+ (x
1
+ x
0
· x
1
) · x
2
= x
0
· x
1
+ (x
1
+ x
0
) · x
2
= x
0
· x
1
+ x
1
· x
2
+ x
0
· x
2
= x
0
+ x
1
+ (x
0
+ x
1
) · x
2
= x
0
+ x
1
+ x
0
· x
1
· x
2
.
Zadatak 2.6.2. Konstruirajte logiˇcke sklopove za 7-segmentni indikator s 4-bitnim ulazom
(tj. za heksadecimalne brojeve od 0 do (F)
16
).
Uputa. I ovaj zadatak sadrˇzi 7 podzadataka (tj. trebate sloˇziti 7 sklopova), no ovaj put
sklopovi ovise o 4 ulazne varijable, ˇsto znaˇci da ´ce tablica istinitosti sadrˇzavati 2
4
= 16
redaka.
Zadatak 2.6.3 (Kolokvij iz “Uvoda u raˇcunarstvo”, 30. 11. 2001). Napiˇsite konjunktivnu
i disjunktivnu normalnu formu formule f raˇcuna sudova zadane pomo´cu tablice:
a b c f a b c f
0 0 0 0 1 0 0 0
0 0 1 0 1 0 1 1
0 1 0 1 1 1 0 1
0 1 1 1 1 1 1 1
Zadatak 2.6.4. Pojednostavite koliko god je mogu´ce formulu raˇcuna sudova:
f = a · b + a · b + a · b · c + a · c · b.
36 2. Ra
ˇ
cun sudova
Rjeˇsenje. f = a · b · c.
Zadatak 2.6.5 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 22. 4. 2002). Napiˇsite formulu
raˇcuna sudova koja se sastoji od varijabli x
0
, x
1
i x
2
. Formula poprima vrijednost 1 ako
je broj x = (x
2
x
1
x
0
)
2
nultoˇcka funkcije
f(x) = x
3
−x
2
−4x + 4,
a 0 inaˇce. Obavezno pojednostavite formulu!
Zadatak 2.6.6 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 10. 7. 2002). Formula raˇcuna
sudova f sadrˇzi varijable x, y i z, te poprima vrijednost 1 ako su barem dvije od varijabli
isitinite, a 0 inaˇce. Napiˇsite f tako da sadrˇzi samo operatore I i NE.
Zadatak 2.6.7 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 18. 6. 2001). Konstruirajte
logiˇcki sklop s tri ulaza x, y i z, te izlazom f koji treba biti 1 ako je broj (xyz)
2
prost, a
0 inaˇce. Obavezno minimizirajte sklop!
Uputa. Zadatak rjeˇsavamo klasiˇcno, kreiranjem tablice istinitosti. Konaˇcno rjeˇsenje je
f = x · y + x · z.
Napomena 2.6.1 (
ˇ
Ceste greˇske). Kod opisnih zadataka u raˇcunu sudova, potrebno je
paziti kako je uvjet zadan. Na primjer, u prethodnom zadatku treba paziti da je prost broj
(xyz)
2
, a ne (zyx)
2
.
Dodatno, poˇstujte nazive varijabli iz zadatka. Na primjer, ako je zadatrak zadan s
varijablama x
0
, x
1
i x
2
, onda i postupak i rjeˇsenje trebaju biti s tim varijablama (a ne,
recimo, a, b i c). Ako postoji potreba za izmjenom naziva varijabli, onda treba jasno
naznaˇciti o kakvoj je supstituciji rijeˇc (npr. x
0
= a, x
1
= b i sl).
Nije greˇska, ali je nepotrebno: nemojte rjeˇsavati ono ˇsto se u zadatku ne traˇzi. Ako se
ne traˇzi crtanje sklopa, onda za crteˇz ne´cete dobiti bodove, nego ´cete samo izgubiti vrijeme.
Ako se ne traˇzi pojednostavljivanje formule, ono vam ne´ce donijeti dodatne bodove. Da-
paˇce, ako pogrijeˇsite, konaˇcni rezultat ´ce biti pogreˇsan, pa ´cete izgubiti poneˇsto bodova.
Zadatak 2.6.8 (Pismeni ispit iz “Uvoda u raˇcunarstvo”, 11. 7. 2001). Logiˇcki sklop s tri
ulaza x, y, z i izlazom f zadan je pomo´cu sheme:
z
f
x
y
2.6. Dodatni zadaci 37
Sastavite ekvivalentan logiˇcki sklop koriste´ci samo jedna NE-vrata, jedna ILI-vrata i jedna
I-vrata.
Rjeˇsenje. Da bismo rijeˇsili zadatak, potrebno je prvo iz sklopa rekonstruirati izraz f, ˇsto
radimo kao na priloˇzenoj slici:
z
x
y
x
y
x · y
x · z
x · y · z
f = x · y + x · y · z
Sada moˇzemo pojednostaviti izraz, paze´ci na ispunjavanje uvjeta zadatka (tj. uz upotrebu
po jednog od operatora negacije, disjunkcije i konjukcije):
f = x · y · z + x · z = (x · y + x) · z = (x + y) · z.
Treba joˇs samo nacrtati sklop koji odgovara tako pojednostavljenom izrazu f:
z
f
x
y
Zadatak 2.6.9. Konstruirajte logiˇcki sklop s tri ulaza x
0
, x
1
i x
2
, te izlazom f koji treba
biti 1 ako je broj x = (x
2
x
1
x
0
)
2
nultoˇcka polinoma
p(x) = x
3
−3x
2
−6x + 8,
a 0 inaˇce. Obavezno minimizirajte sklop!
Zadatak 2.6.10. Konstruirajte logiˇcki sklop s ˇcetiri ulaza x
0
, x
1
, x
2
i x
3
, te izlazom f
koji treba biti 1 ako se broj x = (x
3
x
2
x
1
x
0
)
2
moˇze prikazati kao suma barem dva uzastopna
prirodna broja, a 0 inaˇce. Obavezno minimizirajte sklop!
38 2. Ra
ˇ
cun sudova
Poglavlje 3
Konaˇcni automati i regularni izrazi
Pri matematiˇckom modeliranju raˇcunala moˇzemo koristiti razne modele. U ovom poglav-
lju osvrnut ´cemo se na konaˇcne automate i regularne jezike, s naglaskom na regularne
izraze koji su ˇcesto dostupno (i izuzetno korisno!) pomagalo u naprednijim tekst editori-
ma. Konaˇcni automati su posebno korisni za modeliranje raˇcunala s vrlo malo memorije
(poput automatskih vrata, dizala, mikrovalnih pe´cnica i sl).
3.1 Konaˇcni automati
Pogledajmo kako bismo opisali ponaˇsanje klima-uredaja specijaliziranog za vinske podru-
me. Kao ˇsto je poznato, idealna temperatura za ˇcuvanje vina otprilike 12.2

C. Razmotrit
´cemo pojednostavljeni model, jer se stvarni kompleksniji modeli ne razlikuju suˇstinski.
Pretpostavljamo da uredaj zna hladiti i grijati, oboje s dvije raspoloˇzive snage (“slabo”
i “jako”), te pokuˇsava cijelo vrijeme odrˇzavati temperaturu prostorije na ˇzeljenih 12.2

C.
Pri tome ne smije prenaglo mijenjati temperaturu, ˇsto znaˇci da je “jaˇce” hladenje ili za-
grijavanje prostora poˇzeljno samo ako “slabije” nije dostatno (dakle, uredaj ne´ce “ˇzuriti”
i uvijek raditi ˇsto jaˇce).
Uredaj zapoˇcinje rad u stanju “odrˇzavanje”, te pomo´cu senzora u pravilnim vremen-
skim intervalima oˇcitava temperaturu zraka u prostoriji, te ju usporeduje sa zadanom
vrijednoˇs´cu. Ako je oˇcitana temperatura niˇza od ˇzeljene, uredaj ulazi u stanje “slabo
grijanje” u kojem zagrijava prostor. Ako je uredaj ve´c bio u stanju “slabo grijanje”, a
proˇsla oˇcitana temperatura je viˇsa od upravo oˇcitane (dakle, prostor se i dalje hladi, ˇsto
znaˇci da “slabo grijanje” nije dostatno), stroj prelazi u stanje “jakog grijanja”. Sliˇcno i za
visoke temperature i hladenje. Kad je postignuta idealna temperatura, uredaj ´ce prije´ci
u stanje “odrˇzavanje” u kojem samo prati temperaturu.
Sliˇcno bi radio i ovlaˇzivaˇc zraka koji bi drˇzao vlaˇznost na, za vinski podrum idealnih
70%.
Prikazani uredaj je jednostavan, no pokazuje ˇsto konaˇcni automati rade: u memo-
riji pamte vrlo ograniˇcenu koliˇcinu podataka (u opisanom primjeru je to jedno od pet
39
40 3. Kona
ˇ
cni automati i regularni izrazi
ponudenih stanja), te prima nekakve ulazne podatke (u opisanom primjeru: oˇcitanja sen-
zora). U ovisnosti o tim podacima (i upam´cenima i primljenima), uredaj mijenja stanje
ili zadrˇzava postoje´ce. Uz stanja se mogu vezati neke akcije koje ´ce obaviti neki komad
hardwarea (u naˇsem primjeru sam klima uredaj kojim upravljamo).
U samom primjeru, uz stanje, pamtimo i proˇslo oˇcitanje temperature, no to moˇze-
mo smatrati i ulaznim podatkom (npr. senzor temperature moˇze pamtiti zadnju oˇcitanu
vrijednost, te slati nju i aktualnu vrijednost).
Konaˇcne automate moˇzemo prikazati grafiˇcki, no to ˇcesto ispada nepregledno (v. Sliku
3.1). U takvim prilikama su prikladniji tabliˇcni i funkcijski prikaz, no njih ovdje ne´cemo
detaljnije obradivati.
odrˇzavanje
idealno
idealno
idealno
idealno
idealno
pretoplo
pretoplo
pretoplo
pretoplo
pretoplo
prehladno
prehladno
prehladno
prehladno
prehladno
joˇs
joˇs
joˇs
joˇs
jako
jako
toplije
toplije
hladnije
hladnije
grijanje
grijanje
hladenje
hladenje
Slika 3.1: Konaˇcni automat za upravljanje klima-uredajem
Pogledajmo formalnu definiciju matematiˇckog modela konaˇcnog automata.
Definicija 3.1.1 (Konaˇcni automat). Konaˇcni automat je uredena petorka (Q, Σ, δ, q
0
, F),
pri ˇcemu je
• Q konaˇcan skup stanja,
• Σ konaˇcan skup koji zovemo abeceda,
• δ : Q×Σ → Q funkcija prijelaza,
• q
0
∈ Q poˇcetno stanje, te
• F ⊆ Q skup konaˇcnih stanja.
Iz prikazanog primjera je jasno ˇsto je skup stanja (“odrˇzavanje”, te po dva “grijanja”
i “hladenja”), kao i koje je stanje poˇcetno (“odrˇzavanje”). Abeceda se na prvi pogled
ˇcini velika (skup svih mogu´cih oˇcitanja temperature), no zapravo je dovoljno da senzori
ˇsalju podatke “idealna temperatura”, “prehladno”, “prehladno i hladnije nego maloprije”,
3.2. Regularni izrazi 41
“pretoplo”, te “pretoplo i toplije nego prije”. Nakon ˇsto smo popisali stanja i ˇclanove
abecede, jasno je kako je definirana funkcija δ. Na primjer,
δ(“hladenje”, “pretoplo”) = “hladenje”,
δ(“hladenje”, “pretoplo i toplije nego prije”) = “jako hladenje”.
Konaˇcno stanje ovdje nije zadano jer ˇzelimo da stroj radi unedogled.
3.2 Regularni izrazi
Kako smo vidjeli u prethodnom poglavlju, osnovna ideja konaˇcnog automata je da “ˇcita”
nekakve podatke, te mijenja stanja u kojima se nalazi. Primijetimo da je takav model
idealan za prepoznavanje nekakvih rijeˇci. Npr. kad bismo ˇzeljeli prepoznati sve rijeˇci koje
imaju barem jedno slovo “e”, te zavrˇsavaju na “ca”, stroj bi pomo´cu stanja morao pamtiti
je li proˇcitao slovo “e”, te – ako je – koja su zadnja dva slova. Stanje u kojem bi “e” bilo
proˇcitano, te bi zadnja dva slova bila “c” i “a”, proglasili bismo za zavrˇsno stanje.
Stroj bi tako ˇcitao zadanu rijeˇc i “preskakao” iz stanja u stanje. Kad “potroˇsimo” sva
slova, provjerili bismo je li stroj u zavrˇsnom stanju. Ako je, rijeˇc je kakvu traˇzimo; inaˇce
nije.
Skup A svih rijeˇci koje prihva´ca konaˇcni automat M zovemo jezik automata M, u
oznaci L(M) = A. Za taj jezik kaˇzemo da ga automat M prihva´ca ili prepoznaje. Kao
ˇsto smo vidjeli, konaˇcni automat moˇze prihva´cati i pojedine rijeˇci, pa – da bismo izbjegli
zabune – za jezike obiˇcno kaˇzemo da ih “prepoznaje”.
Konaˇcni automat moˇze prihva´cati viˇse rijeˇci, no uvijek prepoznaje samo jedan jezik.
Definicija 3.2.1 (Regularni jezik). Kaˇzemo da je jezik regularan ako postoji konaˇcni
automat koji ga prepoznaje.
Izrazi kojima opisujemo regularne jezike zovu se regularni izrazi. Da bismo mogli pre-
cizno definirati regularne izraze, potrebne su nam prvo operacije na regularnim jezicima.
Definicija 3.2.2 (Regularne operacije). Neka su A i B dva regularna jezika. Za njih
definiramo sljede´ce regularne operacije:
• Unija: A ∪ B := {x : x ∈ A ili x ∈ B},
• Konkatenacija (spajanje): A ◦ B := {xy : x ∈ A i x ∈ B},
• Zvjezdica: A

:= {x
1
x
2
. . . x
k
: k 0 i svaki x
i
∈ A}.
Primijetite da zvjezdica producira beskonaˇcni jezik koji sadrˇzi i praznu rijeˇc! Pomo´cu
regularnih operacija prirodno definiramo regularne izraze.
42 3. Kona
ˇ
cni automati i regularni izrazi
Definicija 3.2.3 (Regularni izraz). Kaˇzemo da je R regularni izraz ako je R jedno od
navedenog:
• a ∈ Σ (jedan znak zadanog alfabeta),
• ε (prazna rijeˇc, tj. rijeˇc duljine nula),
• ∅ (prazni jezik),
• (R
1
∪ R
2
), pri ˇcemu su R
1
i R
2
regularni izrazi,
• (R
1
◦ R
2
), pri ˇcemu su R
1
i R
2
regularni izrazi, ili
• (R

1
), pri ˇcemu je R
1
regularni izraz.
Napomena 3.2.1. Razlikujte ε (prazna rijeˇc, odnosno – u terminima jezika – jezik koji
sadrˇzi jednu (praznu) rijeˇc) i ∅ (prazni jezik, odnosno jezik koji ne sadrˇzi niti jednu rijeˇc)!
Regularni izrazi samo su dio priˇce o konaˇcnim automatima i regularnim izrazima.
Matematiˇcka teorija je puno ˇsira, no u nastavku ´cemo se baviti samo regularnim izrazima
jer su oni direktno primjenjivi u svakodnevnom koriˇstenju raˇcunala. Zainteresirani ˇcitatelji
mogu viˇse prona´ci u knjizi M. Sipsera, “Introduction to the theory of computation”.
Iako je prikazana definicija matematiˇcki korektna, te se koristi u znanstvenoj i struˇcnoj
literaturi, odabrani simboli su nespretni za upotrebu na raˇcunalu (npr. u tekst editori-
ma i programskim jezicima). Zbog toga koristimo prilagodene oznake (zajedniˇcke ve´cini
implementacija regularnih izraza).
Definicija 3.2.4. Oznake koriˇstene za zapis regularnih izraza:
• R|S = R ∪ S (unija izraza R i S),
• RS = R ◦ S (konkatenacija izraza R i S),
• (R)* = (R)

,
• (R)+ = R(R)

(izraz R ponovljen jednom ili viˇse puta),
• (R)? = (|R) (prazna rijeˇc ili izraz R),
• (R){n} ≡ izraz R ponovljen toˇcno n puta,
• (R){n,m} ≡ izraz R ponovljen barem n, a najviˇse m puta,
• (R){n,} = (R){n}(R)* ≡ izraz R ponovljen barem n puta,
• ^ ≡ poˇcetak rijeˇci,
• $ ≡ kraj rijeˇci,
3.2. Regularni izrazi 43
• [znakovi] ≡ toˇcno jedan od znakova pobrojanih unutar zagrada,
• [^znakovi] ≡ toˇcno jedan znak, razliˇcit od svih znakova pobrojanih unutar zagrada,
• . ≡ bilo koji znak,
• \n, n ∈ N ≡ n-ta grupacija (tj. ono ˇcemu odgovara n-ta zagrada),
• \x ≡ x ako je x neka od specijalnih oznaka (npr. \[ prihva´ca uglatu zagradu, tj.
NE predstavlja poˇcetak izraza [znakovi], dok \. prihva´ca toˇcku, a ne bilo koji
znak; sliˇcno, \\ prihva´ca “naopaku kosu crtu” \),
• \s ≡ jedan razmak, tabulator ili neki drugi znak za razmak,
• \d ≡ jedna znamenka,
• \w ≡ jedan alfanumeriˇcki znak (slovo ili znamenka) ili _,
• \S, \D i \W ≡ suprotno od \s, \d i \w, respektivno,
• \b ≡ rub rijeˇci, tj. mjesto izmedu \w i \W (nije znak!). U nekim verzijama se koriste
oznake \< i \> za poˇcetak, odnosno kraj rijeˇci.
Oznaka . jako ˇcesto ne ukljuˇcuje skok u novi redak, no mi ´cemo ukljuˇciti i skok u no-
vi redak, jer definicija skoka u novi red takoder ovisi o dodatnim okolnostima (npr. o
operativnom sustavu i programu u kojem koristimo regularni izraz).
U prethodnoj definiciji dodani su novi simboli, proizaˇsli iz same upotrebe regularnih
izraza. Konkretno, u matematiˇckoj teoriji raˇcunalstva regularni izraz provjerava cijele ri-
jeˇci. U praktiˇcnim primjenama, on traˇzi neku rijeˇc (op´cenito govore´ci, “rijeˇc” u kontekstu
regularnih izraza moˇze sadrˇzavati i razmake!), obiˇcno liniju po liniju teksta. Zbog toga,
kad ˇzelimo osigurati da se pronadena rijeˇc nalazi na poˇcetku ili kraju retka, koristimo
znakove ^ i $.
Oznaka \n nam sluˇzi kada se ˇzelimo osigurati da se neki dio rijeˇci ponavlja. Na primjer,
izraz ([ab])c\1 prihva´ca rijeˇci “aca” i “bcb” (ali NE i “acb”).
Izraze [znakovi] i [^znakovi] ponekad moˇzemo kra´ce zapisati koriˇstenjem raspona.
Tako [ag-m] oznaˇcava bilo koji znak iz skupa {a, g, h, i, j, k, l, m}.
Vaˇzno je naglasiti da kvantifikatori *, + i {·} djeluju samo na prethodni znak ili
zagradu. Dakle, izraz ab+ prihvatit ´ce rijeˇci “ab”, “abbbbb” i sl. (ali NE i “abab”, kao
niti “a”). S druge strane, operator | djeluje na najˇsire susjedne podizraze, ˇsto znaˇci da je
L(a(bc|def)g) = {“abcg”, “adefg”},
tj. jezik koji izraz a(bc|def)g prepoznaje ima toˇcno dvije rijeˇci (“abcg” i “adefg”).
44 3. Kona
ˇ
cni automati i regularni izrazi
Postoji nekoliko standarda za zapis regularnih izraza na raˇcunalima. Najraˇsireniji su
POSIX
1
Basic (BRE) i POSIX Extended (ERE). Najnapredniji, no manje raˇsireni su Perl
2
Compatibile Regular Expression (PCRE). Ovdje smo opisali podskup PCRE-a (zapravo
ERE s dodacima koje podrˇzava ve´cina programa s podrˇskom za regularne izraze).
Neki od programa i jezika koji podrˇzavaju takve ili sliˇcne regularne izraze su:
• (e)grep – program za traˇzenje teksta u datotekama.
Besplatna komandnolinijska verzija za Windows nalazi se na
http://gnuwin32.sourceforge.net/packages/grep.htm,
a postoje i “jaˇce” (ali komercijalne) verzije,
• (g)vim – editor teksta.
Dostupan na http://www.vim.org/download.php,
• emacs – editor teksta.
Dostupan na http://www.gnu.org/software/emacs/,
• PSPad – editor teksta.
Samo za Windows, na http://www.pspad.com/en/,
• Notepad++ – editor teksta sa skromnom podrˇskom za regularne izraze.
Postoji samo za Windows, a moˇzete ga “skinuti” na
http://notepad-plus.sourceforge.net/uk/download.php,
• OpenOffice.org – besplatan uredski paket.
Dostupno na http://download.openoffice.org/.
Uz pobrojane programe, opisane ili sliˇcne regularne izraze podrˇzavaju i neki SQL sustavi,
te jezici Perl, PHP
3
, Python, Ruby, JavaScript, .NET jezici itd., a postoje i dodaci koji
regularne izraze dodaju i jezicima koji ih a priori ne podrˇzavaju, poput Delphija (v.
http://www.regular-expressions.info/delphi.html). Regularni izrazi dostupni su i
u GNU C-u, pomo´cu funkcija u biblioteci regex.
Neke implementacije regularnih izraza prepoznaju neke od specijalnih znakova do-
slovno, a opisana znaˇcenja im daju tek ako ispred dodamo \. Na primjer, u gvim-u,
oznaka + jednostavno oznaˇcava znak “plus”, dok je kvantifikator za “jedan ili viˇse izraza”
specificiran oznakom \+.
Toˇcnu sintaksu regularnih izraza provjerite u uputama za program ili jezik u kojem
koristite regularne izraze.
1
Portable Operating System Interface for uniX
2
Perl je, sluˇzbeno, akronim od Practical Extraction and Report Language, iako je naziv “Perl” nastao
prije. Humoristiˇcna verzija L. Walla, autora Perla, kaˇze da “Perl” znaˇci “Pathologically Eclectic Rubbish
Lister”.
3
PHP podrˇzava i ERE i PCRE, preko dva odvojena seta funkcija.
3.2. Regularni izrazi 45
Napomena 3.2.2. Na ispitu smijete koristiti bilo koji od uobiˇcajenih standarda, no
ako koristite pravila razliˇcita od ovdje opisanih obavezno napiˇsite koji standard koristi-
te! Takoder, standarde ne smijete mijeˇsati, nego se morate drˇzati jednog standarda!
Napomena 3.2.3. Povratne reference (\1 i sl) NISU regularni izrazi u matematiˇckom
smislu (tj. ne opisuju regularne jezike), ali su zbog praktiˇcnosti ˇcest dio implementiranih
regularnih izraza u raznim traˇzilicama.
Kvantifikatori *, + i {·} rade “pohlepno”, ˇsto znaˇci da ´ce “pokupiti” najve´ci mogu´ci
dio teksta. Na primjer, izraz [qrts].*i ´ce u tekstu “skoˇcimiˇs” prepoznati rijeˇc “skoˇcimi”.
Da je rijeˇc bila “skoˇcimˇs”, izraz bi prepoznao “skoˇci”. Ova razlika je bitna kad se regularni
izraz koristi za zamjene dijelova teksta. Opisano ponaˇsanje moˇze se u PCRE (ili njihovim
dijelovima) zamijeniti tzv. “lijenim” prepoznavanjem.
“Pohlepnost” algoritma “ide” u smjeru slijeva na desno. To znaˇci da ´ce izraz ^a*.
“pokupiti” sve uzastopne znakove “a” (podziraz a*) na poˇcetku linije i prvi znak razliˇcit
od “a” (podizraz .). No, ako linija sadrˇzi samo n znakova “a” (i niˇsta viˇse nakon tih
a-ova) za neki n > 0, onda ´ce podizrazu a* odgovarati prvih n − 1 znakova “a”, dok ´ce
posljednji znak “a” odgovarati podizrazu “.”.
Primjer 3.2.1. U tekstu je potrebno urediti “viˇsak” razmaka. Kako to napraviti u editoru
koji podrˇzava regularne izraze?
Za poˇcetak, potrebno je odrediti ˇsto je to “viˇsak razmaka”. Ovdje ´cemo uzeti da su to
svi razmaci na poˇcetu i na kraju linija, te oni kojih ima dva ili viˇse za redom.
Da bismo maknuli sve razmake na poˇcecima svih linija, traˇzimo
^\s+
te zadajemo editoru da pronadeno zamijeni s praznim stringom. Analogno, za razmake
na kraju redaka traˇzimo
\s+$
i opet zamjenjujemo s praznim stringom. Ako neka linija nema razmake na poˇcetku/kraju,
prikazani izrazi ju ne´ce prepoznati, pa se zamjena za njih ne´ce izvrˇsiti, baˇs kao ˇsto bismo
i oˇcekivali.
Ako editor podrˇzava povratne reference, ove dvije stvai moˇzemo zamijeniti jednim
traˇzenjem
^\s*(.*\S)\s*$
prilikom kojeg ´cemo pronadeni tekst zamijeniti s povratnom referencom \1. Pri tome,
opisani izraz ne´ce obrisati linije koje sadrˇze samo razmake (zbog \S). Primijetite i da,
zbog pohlepnosti kvantifikatora, izraz ^\s*(.*)\s*$ ne bi bio dobar, jer nikad ne bi brisao
razmake na kraju linije. Ako ˇzelimo “poˇcistiti” i takve linije, traˇzimo
46 3. Kona
ˇ
cni automati i regularni izrazi
^\s*(.*\S|)\s*$
Dakle, traˇzimo razmake, zatim niz znakova koji zavrˇsava ne-razmakom ili prazan niz zna-
kova (u zagradi), te na kraju razmake do kraja linije.
Viˇsestruke razmake (ukljuˇcivo i tabulatore i sl.) unutar teksta ˇzelimo zamijeniti s po
jednim obiˇcnim razmakom. Dakle, traˇzimo dva ili viˇse razmaka:
\s{2,} ili \s\s+ (ako editor ne podrˇzava {·})
te pronadeni tekst zamjenjujemo s obiˇcnim razmakom ( ). Mogli smo traˇziti i samo \s+,
no to optere´cuje editor s puno nepotrebnih zamjena (zamjena jednog razmaka s tim istim
razmakom). Ipak, takva zamjena moˇze biti korisna ako ˇzelimo i pojedinaˇcne tabulatore
(ili druge “nevidljive” znakove) zamijeniti razmacima.
Iako razmak moˇzemo oznaˇcavati kao , op´cenito je bolje koristiti \s (v. prethodni
primjer) jer ono ˇsto u tekstu izgleda kao razmak moˇze biti tabulator ili neˇsto sliˇcno.
Naravno, iznimka su formatirane datoteke kad zaista ˇzelimo prepoznavati baˇs razmake,
ali ne i ostale znakove koji samo liˇce na razmak.
Naravno, koriˇstenje \s kao onoga s ˇcime zamjenjujemo pronadeni tekst je besmisleno,
jer \s znaˇci “razmak ili tabulator ili. . . ”, a ne jedan toˇcno odredeni znak.
U primjeru smo pokazali jednu praktiˇcnu primjenu regularnih izraza. U zadacima
´cemo se baviti samo regularnim izrazima, no ne i time ˇcime ih treba zamjenjivati, jer
zamjene ovise o konkretnim primjenama, a lagane su za napraviti, kad znamo ispravno
traˇziti.
Zadatak 3.2.1. U datoteci su pohranjeni opisi fotografija i filmova napravljenih digitalnim
fotoaparatom. U svakoj liniji datoteke nalazi se opis jedne slike ili filma i to tako da je
navedeno ime datoteke (bez ekstenzije), zatim “ - ” (razmak, minus i joˇs jedan razmak),
te opis. Neke slike i filmovi nemaju opisa.
Napiˇsite regularni izraz koji prepoznaje sve opisane separatore iza kojih nema opisa
(kako biste ih u nekom editoru obrisali, pa da u tim linijama ostanu samo nazivi datoteka).
Rjeˇsenje. Osnovno prepoznavanje je lagano: \s-\s ili - . No, ovakav izraz prepoznat
´ce SVA pojavljivanja separatora “ - ”, dakle i one koji iza sebe imaju opis. Traˇzeni
regularni izraz ima samo jedan znak viˇse – onaj za oznaˇcavanje kraja retka:
\s-\s$ ili - $
Op´cenito, prvo rjeˇsenje je bolje, jer drugo prejudicira da nam traˇzimo samo razmake, a
ne i druge “nevidljive” znakove.
Zadatak 3.2.2. Napiˇsite regularni izraz koji prepoznaje sve linije teksta koje sadrˇze
1. barem jedan znak “y”,
3.2. Regularni izrazi 47
2. toˇcno jedan znak “y”.
Rjeˇsenje.
1. Sam pronalazak linije je jednostavan: y (regularni izraz koji ´ce prona´ci znak “y”).
No, ovakav izraz ne´ce prepoznati cijelu liniju nego samo pojedini znak (ˇsto ´ce stvoriti
neˇzeljene posljedice kod izmjene teksta). Umjesto toga, moramo zadati izraz koji
prepoznaje sve znakove od poˇcetka do kraja linije:
^.*y.*$
Ako u liniji postoji viˇse znakova “y”, njih ´ce pokupiti prvi podizraz .* (zbog “po-
hlepnog” traˇzenja).
2. Na osnovu prethodnog podzadatka slaˇzemo ovo rjeˇsenje. Poˇsto ˇzelimo toˇcno jedan
znak “y” (koji ve´c imamo), moramo se osigurati da niti jedan znak koji podizrazi
.* prihvate ne bude “y”. Dakle:
^[^y]*y[^y]*$
Zadatak 3.2.3. Napiˇsite regularni izraz koji prepoznaje sve linije teksta u kojima se
neposredno iza svakog znaka “a” nalazi znak “b” ili znak “c”.
Rjeˇsenje. Poˇsto ˇzelimo provjeravati cijele linije, izraz moramo omediti znakovima ^ i $.
ˇ
Cesto, ali POGRE
ˇ
SNO rjeˇsenje kod ovakvih zadataka je
^.*(a[bc].*)*$
Problem ovdje je da toˇcka odgovara bilo kojem znaku, pa tako i znaku “a”. Drugim ri-
jeˇcima, podizraz .* moˇze odgovarati cijeloj liniji (bilo kojoj!), pa (a[bc].*)* jednostavno
moˇze biti prazna rijeˇc. Ispravno je osigurati ne samo gdje ´ce se “a” pojaviti (ispred “b”
ili “c”), nego i gdje ne´ce:
^[^a]*(a[bc][^a]*)*$
Zadatak 3.2.4. Napiˇsite regularni izraz koji u tekstu prepoznaje
1. pozitivne binarne brojeve,
2. ispravno zapisane pozitivne binarne brojeve (bez vode´cih nula),
3. ispravno zapisane binarne brojeve (bez vode´cih nula, sa ili bez negativnog predznaka),
4. ispravno zapisane binarne brojeve s toˇcno 3 znamenke,
5. ispravno zapisane binarne brojeve s barem 3 znamenke,
48 3. Kona
ˇ
cni automati i regularni izrazi
6. ispravno zapisane binarne brojeve s barem 3 i najviˇse 5 znamenaka.
Rjeˇsenje.
1. Pozitivni binarni brojevi su nizovi nula i jedinica, pri ˇcemu ˇcitani niz znakova mora
sadrˇzavati barem jedan znak (tj. prazna rijeˇc nije broj), pa je traˇzeni izraz, “na prvu
loptu”,
[01]+
No, ovo nije u potpunosti toˇcno, jer ´ce kao pozitivni broj prepoznati i text koji sadrˇzi
samo nule (npr. “0”, “0000” i sl.). Nama treba da barem jedna znamenka (za sada
ne nuˇzno vode´ca, jer joˇs ne inzistiramo na “ispravnom” zapisu) bude razliˇcita od
nule (tj. 1).
[01]*1[01]*
Primijetite da smo kvantifikator + zamijenili kvantifikatorom *. Naime, + nam je
trebao osigurati da imamo barem jednu znamenku. Ovdje smo tu znamenku izdvojili
(“1” u sredini), pa lijevo i desno od nje smiju biti i prazne rijeˇci.
2. Ako ˇzelimo osigurati da nema vode´cih nula, prepoznata rijeˇc mora zapoˇceti sa
znamenkom koja nije nula. Dakle, traˇzeni izraz sliˇcan je prethodnom, s time da
znak “1” mora biti na poˇcetku:
1[01]*
Primijetite: izraz 1[01]+ bi odgovarao pozitivnim binarnim brojevima strogo ve´cim
od 1 (poˇcinju sa znamenkom 1 i imaju joˇs barem jednu znamenku iza).
3. Da bismo prepoznali minus koji se moˇze pojaviti najviˇse jednom (ali se i ne mora
pojaviti), upotrijebit ´cemo kvantifikator ?. Dodatno, viˇse ne ograniˇcavamo broje-
ve na pozitivne, pa treba prepoznati i broj 0 (jedini binarni broj koji ne poˇcinje
znamenkom 1). Dakle, traˇzeni izraz je
-?1[01]*|0
Da smo kao ispravan broj ˇzeljeli prihvatiti i −0, izraz bi glasio
-?(1[01]*|0)
4. Ovdje kvantifikator * zamjenjujemo kvantifikatorom {·}. Pri tome treba uzeti u
obzir da je jedna znamenka ona prva jedinica, pa ostatak broja treba imati dvije (a
ne tri) znamenke. Konaˇcno, imamo izraz
3.2. Regularni izrazi 49
-?1[01]{2}
5. Ako kvantifikatoru {·} dodamo zarez, mijenjamo mu znaˇcenje iz “toˇcno koliko piˇse”
u “barem koliko piˇse”. Novi izraz je
-?1[01]{2,}
6. Ako kvantifikator {·} zamijenimo s {·,·}, mijenjamo mu znaˇcenje iz “toˇcno koliko
piˇse” u “barem koliko je prvi parametar i najviˇse koliko je drugi” (opet smanjujemo
oba broja za jedan jer jednu znamenku provjeravamo prije [·]). Novi izraz je
-?1[01]{2,4}
U rjeˇsenjima prethodnog zadatka prepoznajemo binarne brojeve bez obzira na to ˇsto se
nalazi oko njih. Tako ´ce, na primjer, u tekstu “Pero101x” podstring “101” biti prepoznat
kao binarni broj, iako je samo dio rijeˇci (npr. neˇcijeg korisniˇckog imena). Kako prepoznati
samo brojeve odvojene od teksta, ovisi donekle o tome ˇsto toˇcno ˇzelimo. Najˇceˇs´ci naˇcin
vidjet ´cemo kasnije, npr. u rjeˇsenjima Zadatka 3.2.7.
Kvantifikator {·} nije mogu´ce koristiti u varijanti {,·}, tj. prva vrijednost uvijek mora
biti zadana. To nije problem: jednostavno, ako ˇzelimo re´ci “najviˇse n ponavljanja, umjesto
nepostoje´ceg {,n} koristimo {0,n}.
Zadatak 3.2.5. Rijeˇsite prethodni zadatak (svih ˇsest varijanti) prepoznavaju´ci
a) oktalne brojeve,
b) heksadecimalne brojeve i
c) parne dekadske brojeve.
Uputa. Parni brojevi su oni koji zavrˇsavaju znamenkom 0, 2, 4, 6 ili 8. Tu znamenku
izdvojite, no pripazite da ispravno prepoznate i jednoznamenkaste brojeve (jer je prva
znamenka ve´c izdvojena).
Zadatak 3.2.6. Napiˇsite regularni izraz koji prepoznaje ispravno napisane e-mail adrese.
Rjeˇsenje. Osnovno na ˇsto ovdje ˇzelimo paziti je da niz znakova mora sadrˇzavati toˇcno
jedan znak “@”, te barem jednu toˇcku:
[^@]+@[^@.]+(\.[^@.]+)+
Toˇcan izraz, koji uzima u obzir i koji su znakovi gdje dozvoljeni, je
[a-z0-9._%-]+@([a-z0-9-]+\.)+[a-z]{2,4}
50 3. Kona
ˇ
cni automati i regularni izrazi
no to nije potrebno znati na ispitu. Ipak, primijetite u podizrazu [a-z0-9-] zavrˇsni
minus: on oznaˇcava znak “minus”, a ne raspon (jer nema znak do kojeg bi raspon trebao
i´ci).
Zadatak 3.2.7. Napiˇsite regularni izraz koji prepoznaje
1. bilo kakvu rijeˇc (u klasiˇcnom smislu, dakle niz slova omedenih razmacima),
2. nenaglaˇsenu rijeˇc (prvo slovo moˇze biti malo ili veliko; ostala moraju biti mala),
Prvo prikazujemo rjeˇsenje u kojem ´cemo traˇziti odgovaraju´ci raspored razmaka u oko-
lini traˇzenih rijeˇci.
Rjeˇsenje pomo´cu razmaka. Bilo koje slovo prepoznajemo podizrazom [a-zA-Z]. Bilo koje
malo slovo prepoznajemo podizrazom [a-z], dok veliko slovo prepoznajemo podizrazom
[A-Z]. U svim podzadacima moramo prepoznati “viˇsak”, tj. bliˇzu okolinu rijeˇci. Zato
´cemo samo rijeˇc dodatno grupirati u zagrade, a uz izraz treba naglasiti i koja grupa
zagrada daje samu rijeˇc (jer nju zadatak traˇzi).
1. Rijeˇc omedena razmacima:
\s([A-Za-z]+)\s
Rijeˇc odgovara prvoj grupaciji (zagradi).
Ovdje treba uzeti u obzir da se rijeˇc moˇze nalaziti i na poˇcetku ili na kraju retka u
tekstu, kad ispred ili iza nje nema razmaka. Poˇsto ˇzelimo i takve rijeˇci prepoznati,
piˇsemo
(^|\s)([A-Za-z]+)(\s|$)
Dakle, ispred rijeˇci moˇze biti poˇcetak retka (ovo nije znak!) ili razmak, a nakon
rijeˇci moˇze biti razmak ili kraj retka (koji takoder nije znak).
Rijeˇc odgovara drugoj grupaciji (zagradi), dok prva i tre´ca sluˇze za ispravno grupi-
ranje podizraza oko operatora |.
2. Sliˇcno kao kod prepoznavanja brojeva, treba izdvojiti prvo slovo od ostalih:
(^|\s)([A-Za-z][a-z]*)(\s|$)
Rijeˇc koju traˇzimo odgovara drugoj grupaciji (zagradi).
Da bismo u potpunosti ispravno prepoznavali poˇcetak reˇcenice, tekst je potrebno tretirati
kao cjelinu (a ne redak po redak). To se radi ovisno o programu/jeziku, pa ovdje ne´cemo
razmatrati.
3.2. Regularni izrazi 51
Ovakvo rjeˇsenje se NE
´
CE ponaˇsati kako bismo ˇzeljeli. Naime ako imamo tekst
Kupus sadi ciklu
onda ´ce opisani regularni izrazi prepoznati svaku drugu rijeˇc, jer kad prepoznamo “Kupus ”,
prepoznavanje idu´ce rijeˇci kre´ce nakon ve´c prepoznatog niza znakova, tj. od slova “s” u
“sadi”. Zbog toga prikazani regularni izraz ne´ce prepoznati da ispred rijeˇci “sadi” postoji
razmak. Da bismo izbjegli takve probleme, koristimo rub rijeˇci \b (ili, u nekim izvedbama,
poput (g)vim-a, \< i \>).
Rjeˇsenje pomo´cu ruba rijeˇci.
1. Rijeˇc:
\b[A-Za-z]+\b ili \<[A-Za-z]+\>
Poˇsto \b nije znak, onda ´ce prikazani regularni izraz prihvatiti toˇcno jednu rijeˇc, ˇsto
je upravo ono ˇsto ˇzelimo. Zato nam ne treba grupiranje, kao niti posebna provjera
jesmo li na poˇcetku ili kraju retka.
2. Opet ´cemo izdvojiti prvo slovo od ostalih:
\b[A-Za-z][a-z]*\b ili \<[A-Za-z][a-z]*\>
Prikazano rjeˇsenje (pomo´cu ruba rijeˇci) ispravno ´ce prepoznati i rijeˇci koje nisu omedene
samo razmacima, nego i interpunkcijskim i sliˇcnim znakovima.
Napomena 3.2.4. Ako izraz prepoznaje “viˇsak”, obavezno naglasite koja grupacija (ili
zagrada) odgovara rjeˇsenju zadatka. Ako takvog naglaˇsavanja nema, smatra se da cijeli
izraz odgovara onome ˇsto se u zadatku traˇzi.
Zadatak 3.2.8. Napiˇsite regularni izraz koji prepoznaje rijeˇci koje sadrˇze nehrvatska
slova engleskog alfabeta (“q”, “w”, “x”, “y”).
Zadatak 3.2.9. Napiˇsite regularni izraz koji prepoznaje sve jednostavne L
A
T
E
X naredbe
oblika
\naredba{glavni parametar} ili
\naredba[pomocni parametar]{glavni parametar}
pri ˇcemu treba odvojiti naredbu i parametre (u tri odvojene grupacije). Moˇzete pretpostaviti
da se naredba sastoji samo od slova (barem jednog), dok parametri u sebi ne sadrˇze uglate,
odnosno vitiˇcaste zagrade, ali mogu biti i prazni.
52 3. Kona
ˇ
cni automati i regularni izrazi
Rjeˇsenje. Ovdje koristimo nekoliko specijalnih znakova (\, [, ], {, }) ispred kojih treba
dodati \ kako bismo prihva´cali upravo njih, bez specijalnih znaˇcenja koja inaˇce imaju
u regularnim izrazima. Takoder, podizraz koji prihva´ca [pomocni parametar] treba
oznaˇciti kao neˇsto ˇsto se moˇze i ne mora pojaviti. To radimo dodatnim grupiranjem, uz
kvantifikator ?.
\\([a-zA-Z]+)(\[([^]]*)\])?\{([^}]*)\}
Naredba ´ce se nalaziti u \1, pomo´cni parametar (ako postoji) bit ´ce u \3 (ako ne postoji,
\3 ´ce biti prazan), dok ´ce se glavni parametar na´ci u \4.
Zadatak 3.2.10. Napiˇsite regularni izraz koji prepoznaje sve sloˇzenije L
A
T
E
X naredbe
oblika
\naredba{gp1}{gp2}...{gpn} ili \naredba[pp]{gp1}{gp2}...{gpn}
pri ˇcemu treba odvojiti naredbu i parametre sliˇcno prethodnom zadatku. Moˇzete pretpos-
taviti da postoji barem jedan glavni parametar, tj. n ≥ 1 te da niti jedan od njih ne sadrˇzi
vitiˇcaste zagrade.
Pokuˇsajte u jednu grupaciju (napiˇsite i koju!) “uhvatiti” sve glavne parametre (gp1,
gp2,. . . , gpn), zajedno s pripadnim vitiˇcastim zagradama.
Rjeˇsenje.
\\([a-zA-Z]+)(\[([^]]*)\])?(\{([^}]*)\})+
Sve glavne parametre ´cemo “uloviti” dodatnim grupiranjem:
\\([a-zA-Z]+)(\[([^]]*)\])?((\{([^}]*)\})+)
Glavni parametri bit ´ce pospremljeni u \4.
ˇ
Sto ´ce se nalaziti u \6 ako je tekst koji pretraˇzujemo
Jedna \slozena{La}{TeX} naredba
poˇsto ´ce ta grupacija prepoznati i “La” i “TeX”?
Napomena 3.2.5. U prethodnim zadacima vidimo relativno zbunjuju´ci podizraz [^]].
Kad bi prvi znak ] zatvaro izraz, tj. kad bismo pod izraz gledali kao [^] i ] posebno, onda
bi [^] znaˇcilo “bilo koji znak osim niˇcega”, ˇsto je besmisleno (postiˇze se toˇckom). Zato,
kad ˇzelimo prihvatiti neki znak koji ne ukljuˇcuje zatvorenu uglatu zagradu (i, eventualno,
joˇs neke znakove), nju postavljamo na prvo mjesto:
[^]...]
3.2. Regularni izrazi 53
Sliˇcno, ako ˇzelimo prihvatiti neki znak koji moˇze biti zatvorena uglata zagrada (i, eventu-
alno, joˇs neki znak):
[ ]...]
Ako ˇzelimo prihvatiti samo ^, piˇsemo
\^
Ako ˇzelimo prihvatiti ^ i joˇs neke znakove, npr. a ili b, znak ^ ne smijemo staviti na
poˇcetak (da ne ispadne negacija), pa piˇsemo
[a^b] ili [ab^] ili [a-b^]
Zadatak 3.2.11. Napiˇsite regularni izraz koji prepoznaje sve palindrome (rijeˇci koje se
jednako ˇcitaju slijeva i sdesna) od toˇcno 5 slova.
Rjeˇsenje. Ovdje nam trebaju povratne reference, te rubovi rijeˇci:
\b([A-Za-z])([A-Za-z])[A-Za-z]\2\1\b
Zadatak 3.2.12. Napiˇsite regularni izraz koji prepoznaje brojeve telefona u formatu
+kod1-kod2-broj
gdje kod1 oznaˇcava kˆod drˇzave, kod2 oznaˇcava kˆod grada/regije, a broj je lokalni broj
telefona. Kodovi drˇzave i grada/regije sadrˇze izmedu jedne i tri znamenke, dok se lokalni
broj telefona sastoji od znamenaka (barem tri) i najviˇse jedne crtice (koja ne smije biti na
poˇcetku i kraju broja).
Kˆodove i lokalni broj izdvojite u zasebne grupacije (i, naravno, napiˇsite ˇsto je u kojoj).
Kako biste prepoznali linije koje se sastoje samo od takvih brojeva (po jedan u svakoj
liniji), tj. koje sadrˇze takve brojeve i niˇsta viˇse?
Rjeˇsenje. Ovdje imamo znak + koji ima specijalno znaˇcenje, pa ispred njega dodajemo \:
\b\+(\d{1,3})-(\d{1,3})-(\d+-?\d{2,}|\d{2,}-?\d+)\b
Kˆodu drˇzave odgovara \1, kˆodu regije \2, a lokalnom broju telefona \3. Kad bismo htjeli
prepoznavati linije (kako je opisano na kraju zadatka), izraz bi bio:
^\+(\d{1,3})-(\d{1,3})-(\d+-?\d{2,}|\d{2,}-?\d+)$
Zadatak 3.2.13. Napiˇsite regularni izraz koji prepoznaje datume u formatu
1. dd.mm.yyyy.
2. dd. mjesec yyyy.
54 3. Kona
ˇ
cni automati i regularni izrazi
3. yyyy/mm/dd
pri ˇcemu je dd dan, mm mjesec, a yyyy godina (prirodni brojevi s najviˇse dvije, odnosno
ˇcetiri znamenke). “mjesec” oznaˇcava tekstualni naziv mjeseca. Ne morate paziti koliko
koji mjesec ima dana, no izbjegnite oˇcito nebulozne datume (dd > 31, mm > 12, viˇse od
jedne rijeˇci u nazivu mjeseca).
Dobivene dijelove datuma (dan, mjesec i godinu) izdvojite u grupacije (i, naravno,
napiˇsite ˇsto je u kojoj).
Zadatak 3.2.14. Napiˇsite regularni izraz koji prepoznaje linije s ispravnim zapisom vre-
mena u .srt datotekama (SubRip Text, za pohranu titlova). Traˇzeni format je
vrijeme1 --> vrijeme2
pri ˇcemu je svako od vremena zapisano kao
H:M:S,ms
gdje H oznaˇcava sate, M minute, S sekunde, a ms milisekunde (nenegativni cijeli brojevi,
sa ili bez vode´cih nula, s tim da su milisekudne uvijek zapisane kao troznamenkasti broj).
Pazite da minute i sekunde ograniˇcite na dozvoljene vrijednosti.
Rjeˇsenje. Prepoznajmo najprije jedno vrijeme:
\d+:[0-5]?\d:[0-5]?\d,\d{3}
Sada ovaj izraz treba zapisati dva puta, te izmedu postaviti separator “ --> ”. Usput,
treba pripaziti i na oznake za poˇcetak i kraj linije teksta:
^\d+:[0-5]?\d:[0-5]?\d,\d{3} --> \d+:[0-5]?\d:[0-5]?\d,\d{3}$
Grupiranjem bismo mogli dobiti pojedine dijelove iz prvog ili drugog vremena (npr. sate
i minute).
Napomena 3.2.6. U prethodnom zadatku sljede´ce rjeˇsenje bilo bi KRIVO:
^(\d+:[0-5]?\d:[0-5]?\d,\d{3}) --> \1$
jer bi odgovaralo iskljuˇcivo linijama kod kojih su oba zadana vremena potpuno jednaka.
Zadatak 3.2.15. Napiˇsite regularni izraz koji prepoznaje ispravne linije .sub datoteka
(MicroDVD, za pohranu titlova). Svaka linija datoteke sadrˇzava toˇcno jedan titl ˇciji je
format
{frame1}{frame2}Tekst
3.2. Regularni izrazi 55
Parametri frame1 i frame2 su nenegativni cijeli brojevi, a Tekst moˇze biti bilo ˇsto. Iz-
dvojite te tri cjeline u zasebne grupacije.
Zadatak 3.2.16. Napiˇsite regularni izraz koji prepoznaje sve linije u tekstu koje zapoˇcinju
validnim JMBAGom (prirodni deseteroznamenkasti broj) iza kojeg se mogu (ali i ne mo-
raju) nalaziti podaci o vlasniku JMBAGa (ako se nalaze, odvojeni su barem jednim raz-
makom). JMBAG izdvojite u jednu grupaciju, a podatke (bez poˇcetnih razmaka) u drugu.
Zadatak 3.2.17. Napiˇsite regularni izraz koji prepoznaje sve linije u tekstu koje zapoˇcinju
validnim JMBGom (prirodni broj koji zapoˇcinje s datumom (format ddmmyyy: dvoznamen-
kasti dan i mjesec i troznamenkasta godina), te ima ukupno 13 znamenaka) iza kojeg se
mogu (ali i ne moraju) nalaziti podaci o vlasniku JMBGa (ako se nalaze, odvojeni su
barem jednim razmakom). JMBG izdvojite u jednu grupaciju, a podatke (bez poˇcetnih
razmaka) u drugu.
Zadatak 3.2.18. Napiˇsite regularni izraz koji prepoznaje rimske brojeve u originalnoj no-
taciji (dozvoljeno je samo “zbrajanje”, tj. IIII, a ne IV, je 4). Koristite oznake I (jedan),
V (pet), X (deset), L (pedeset), C (sto), D (petsto) i M (tisu´cu). Pazite da ne dozvolite
prazne rijeˇci, te da ne prepoznate dijelove ve´cih rijeˇci (npr. DVI u “PREDVIDJETI”).
Zadatak 3.2.19. Napiˇsite regularni izraz koji prepoznaje reˇcenice s najmanje 3 rijeˇci.
Rijeˇci su nizovi slova odvojeni razmacima, a reˇcenice zavrˇsavaju toˇckom, upitnikom
ili uskliˇcnikom i ne prelamaju se kroz retke.
Rjeˇsenje.
[A-Za-z]+(\s+[A-Za-z]+){2,}\.
U prethodnom zadatku, varijante s
1. toˇcno 3 rijeˇci i
2. najviˇse 3 rijeˇci
ne moˇzemo jednostavno prepoznati. Zaˇsto?
Zadatak 3.2.20. Zadan je tekst
Alan Mathison Turing (1912–1954), nositelj ordena Reda britanskog carstva i poˇcasni
ˇclan Kraljevskog druˇstva znanosti, bio je engleski matematiˇcar, logiˇcar, kriptoanalitiˇcar i
raˇcunalni znanstvenik. Izvrˇsio je veliki utjecaj na razvoj raˇcunalne znanosti i pridonio je
formalizaciji koncepta algoritma i izraˇcunavanja s tzv. Turingovim strojem. Godine 1999.
Time Magazine nazvao je Turinga jednim od 100 najvaˇznijih ljudi dvadesetog stolje´ca za
ulogu koju je odigrao u stvaranju modernih raˇcunala – njegov Turingov test bio je znaˇcajan
i karakteristiˇcno provokativan doprinos raspravi o umjetnoj inteligenciji.
56 3. Kona
ˇ
cni automati i regularni izrazi
Tijekom Drugog svjetskog rata Turing je radio za britansku obavjeˇstajnu agenciju odgo-
vornu za razbijanje obavjeˇstajnih signala i osiguranje podataka britanskoj Vladi i oruˇzanim
snagama. Neko je vrijeme bio i ˇsef Odjeljka 8 koji je bio odgovoran za analiziranje nje-
maˇckih mornariˇckih kriptograma i glavni sudionik u naporima za razbijanje njemaˇckih
ˇsifri. Osmislio je brojne tehnike za razbijanje njemaˇckih ˇsifri, ukljuˇcuju´ci elektromeha-
niˇcki stroj koji bi mogao prona´ci postavke Enigma stroja. U prosincu 1940. Turing je
rijeˇsio pomorski Enigma sustav, koji je bio daleko sloˇzeniji matematiˇcki sustav od svih
koriˇstenih od strane ostalih sluˇzbi. Takoder je izumio statistiˇcke tehnike za pomo´c u razbi-
janju Enigma koda. U srpnju 1942. izmislio je tehniku za koriˇstenje protiv nove njemaˇcke,
Lorenzove ˇsifre.
Koji ´ce sve dijelovi teksta odgovarati sljede´cim regularnim izrazima, te koje ´ce vrijed-
nosti vratiti njihove grupacije?
1. [A-Z]\w+
2. [a-z]\w+
3. \d{4}
4. \d{3}
5. \d{3,}
6. [^A-Za-z ]+
7. \w+ \d
8. U\s(.+u)
9. (.)(.\1){2,}
10. T((.)*)ing
11. ^(\D+)(\d+)
12. [aeiou]{2,}
13. \w+-$
Rjeˇsenje.
1. “Alan”, “Mathison”, “Turing”, “Reda”, “Kraljevskog”,. . .
2. “lan”, “athison”, “uring”, “nositelj”, “ordena”,. . .
3. “1912”, “1954”, “1999”, “1940” i “1942”
3.2. Regularni izrazi 57
4. “191”, “195”, “199”, “100”, “194” i “194”
5. “1912”, “1954”, “1999”, “100”, “1940” i “1942”
6. “(1912–1954),”, “-” (prekid rijeˇci na kraju prve linije), “,”,. . .
7. “ne 1”, “od 1”, “Odjeljka 8”,. . .
8. “U prosincu”, “U srpnju 1942. izmislio je tehniku” (NE samo “U srpnju”, zbog
pohlepnog principa rada algoritma)
U oba sluˇcaja, \1 ´ce biti sve osim prva dva znaka (poˇcetno “U” i razmak)
9. “aˇcaja” (\1 = “a”, \2 = “ja”), “ataka” (\1 = “a”, \2 = “ka”), “anagama” (\1 =
“a”, \2 = “ma”), “a ana” (\1 = “a”, \2 = “na”), “uˇcuju” (\1 = “u”, \2 = “ju”)
Preostale rijeˇsite samostalno za vjeˇzbu, raˇcunaju´ci da je svaka linija teksta zasebna upravo
onako kako su prelomljene.
Primjere rjeˇsenja iz ovog poglavlja, kao i druge regularne izraze pisane po opisanom
standardu, moˇzete isprobati na sluˇzbenoj stranici kolegija, preciznije ovdje:
http://degiorgi.math.hr/prog1/apps/regex.php.
58 3. Kona
ˇ
cni automati i regularni izrazi
Poglavlje 4
Uvod u algoritme i osnovni program
U prethodnim poglavljima vidjeli smo razliˇcite upute kako neˇsto napraviti. Na primjer,
kako se u raznim brojevnim sustavima zbraja, oduzima, mnoˇzi i dijeli, kako od tablice
istinitosti sloˇziti konjunktivnu i disjunktivnu normalnu formu i sl.
Opisani procesi su primjeri algoritama. Precizna definicija pojma “algoritam” je kom-
plicirana, ali opisno moˇzemo re´ci da je algoritam postupak za rjeˇsavanje nekog problema.
Neke vaˇzne karakteristike algoritama su:
1. Jednim algoritmom moˇzemo rijeˇsiti samo toˇcno odredenu klasu problema. Na
primjer, algoritam za zbrajanje u bazi b treba ispravno raˇcunati sumu dva broja
zapisana u bazi b, ali nije odredeno ˇsto mora raditi ako brojevi nisu dobro zapisani
(npr. neki ima znamenku ve´cu ili jednaku b).
To znaˇci da se moˇzete osloniti na to da ´ce ulazni podaci biti onakvi kakvi su navedeni
u zadatku. Na primjer, ako zadatak kaˇze da treba uˇcitati prirodan broj, niste
duˇzni provjeravati je li uˇcitani broj zaista ve´ci od nule (osim ako se takva provjera
eksplicitno traˇzi u zadatku).
2. Algoritam uzima ulazne i vra´ca izlazne podatke koji predstavljaju rjeˇsenje
problema. To znaˇci da programi moraju ispisati rezultat, a potprogrami ga moraju
ili ispisati ili nekako vratiti glavnom programu (obiˇcno ´ce u zadatku biti precizirano
ˇsto treba).
Ponekad ´ce u zadatku biti navedeno da treba napisati samo dio programa koji neˇsto
radi; tada nije potrebno uˇcitavati ulazne podatke i ispisivati rezultat (osim ako se u
zadatku to eksplicitno traˇzi).
3. Algoritam zavrˇsava nakon konaˇcno mnogo koraka, tj. ne smije se izvrˇsavati u
nedogled!
4. Svaki korak mora biti precizno i jednoznaˇcno opisan, tako da ga moˇze izvrˇsiti
i raˇcunalo.
59
60 4. Uvod u algoritme i osnovni program
Odakle potjeˇce rijeˇc “algoritam”? Arapi su skupljali i prevodili klasiˇcna grˇcka djela,
te znanost iz Indije i Kine. Muammad ibn M¯ us¯a al-Khw¯arizm
¯
i napisao je knjigu o “indij-
skim brojevima” (precizni sustav sa znamenkama 0, 1, . . . , 9), te je u njoj opisao postupke
zbrajanja, oduzimanja, mnoˇzenja, dijeljenja i vadenja korijena. Danas postoji saˇcuvan
latinski prijevod iz dvanaestog stolje´ca pod naslovom “Algoritmi de numero Indorum”,
pri ˇcemu je rijeˇc “Algoritmi” bila predstavljala latinizirano ime autora. Kasnije je to mi-
sinterpretirano kao mnoˇzina na latinskom, pa je rijeˇc “algoritam” preuzeta kao “postupak
za raˇcunanje”.
Najpoznatije al-Khw¯arizm
¯
ijevo djelo je “al-Kit¯ab al-mukhtaar f
¯
i is¯ab al-jabr wa-l-
muq¯abala” u kojem je opisao postupke rjeˇsavanja jednadˇzbi prvog i drugog reda. Prema
tom djelu, od rijeˇci “al-jabr” (uspostaviti, dovrˇsiti) potjeˇce rijeˇc “algebra”.
U starom znaˇcenju, “algoritmi” su samo postupci za raˇcunanje, dok je moderno zna-
ˇcenje bitno ˇsire. Pojam algoritma centralni je pojam raˇcunarstva, a postaje i sve vaˇzniji
u matematici.
4.1 Tko “programira”?
Danas je uvrijeˇzena definicija da su programeri “oni koji programiraju”, no ˇsto to znaˇci?
U osnovi, “one koji programiraju” dijelimo u dvije grupe:
1. projektanti – osobe koje osmiˇsljavaju algoritme i strukture podataka kojima se
rjeˇsava neki problem te
2. programeri – osobe koje piˇsu programski kˆod u odredenom programskom jeziku,
prema uputama koje daju projektanti.
Kod manjih projekata, to dvoje je ˇcesto isto. Medutim, kod zahtjevnijih projekata,
ta razlika je jako bitna. Naime, za realizaciju velikih projekata ˇcesto je potrebno mnogo
“onih koji programiraju”. Bilo bi izuzetno loˇse za konaˇcno rjeˇsenje kad bi svatko to radio
na svoj naˇcin. Zbog toga je potreban manji tim projektanata koji ´ce osmisliti rjeˇsenje i
dati upute programerima.
Ovdje (na raˇcunarskim kolegijima na PMF-MO) prvenstveno obrazujemo projektante,
dakle osobe sposobne “algoritamski razmiˇsljati”. Pri tome, nuˇzno je poznavanje nekog
programskog jezika (zbog provjere rjeˇsenja i poznavanja mogu´cnosti raˇcunala), ali se ne
stavlja naglasak na apsolutno poznavanje sintakse odabranog jezika (u naˇsem sluˇcaju C-
a), nego na poznavanje principa rada i konstrukcija jezika u onoj mjeri koja je nuˇzna za
zapisivanje algoritama koje ´cemo raditi.
Gornja podjela na projektante i programere je simplificirana. Veliki projekti rade
se u viˇse razvojnih faza, a glavnu ulogu u tom procesu imaju software inˇzenjeri – vrlo
sliˇcno onome ˇsto ovdje zovemo projektantima. Viˇse o tom dijelu posla uˇci se na kolegiju
“Softversko inˇzenjerstvo”, a rijeˇc je o izuzetno dobro pla´cenim struˇcnjacima. Dakle, isplati
4.2. Osnovni program 61
se uˇciti kolegije “Programiranje 1” i “Programiranje 2”, kao uvertiru u ono ˇsto slijedi u
nastavku studija.
4.2 Osnovni program
Pod pojmom “osnovni program” u svakom programskom jeziku podrazumijevamo pro-
gram koji ispisuje neku jednostavnu poruku i zavrˇsava s radom. Svrha takvog programa
je demonstracija osnovne sintakse: zaglavlja, naˇcin navodenja naredbi i sl.
Najˇceˇs´ce se ispisuje poruka “hello, world”, pa se i takvi programi ˇcesto zovu “hello
world” programi. Veliku arhivu takvih programa u raznim jezicima moˇzete vidjeti ovdje:
http://www2.latech.edu/
~
acm/HelloWorld.shtml
U C-u, takav program izgleda ovako:
Primjer 4.2.1 (“Hello world” program pisan u C-u).
1 #include <s t di o . h>
2
3 i nt main( void) {
4 pr i nt f ( ” he l l o , worl d\n” ) ;
5 return 0;
6 }
Lako se vidi koja naredba ispisuje tekst, ali vidimo da je (ˇcak i za ovako jednostavan
program!) potrebno napisati i neke “dodatke”.
Osnovni program u C-u sastoji se od:
1. #include <stdio.h>
Direktiva compileru da ukljuˇci u program sadrˇzaj datoteke stdio.h. Ta datoteka
sadrˇzi sve ˇsto je potrebno za ispravan ispis teksta na standardni izlaz (najˇceˇs´ce ekran
raˇcunala).
2. int main(void)
Zaglavlje glavnog dijela programa. Kako ´cemo kasnije vidjeti, main() je obiˇcan
potprogram koji se od ostalih potprograma razlikuje samo po tome ˇsto upravo njega
raˇcunalo izvodi prilikom pokretanja programa.
Kad negdje navedemo programski kod bez funkcije main(), to znaˇci da prikazujemo
samo dio programa! Za uspjeˇsno compiliranje i izvodenje takvog koda, potrebno je
dopisati elemente koji nedostaju!
3. printf("hello, world\n");
Sama naredba za ispis. Tekst koji ´ce se ispisati navodimo izmedu dvostrukih na-
vodnika.
ˇ
Cesto se dodaju i druge vrijednosti, ˇsto ´cemo takoder vidjeti malo kasnije.
Specijalni znak \n (engl. backslash n) oznaˇcava skok u novi red.
62 4. Uvod u algoritme i osnovni program
4. return 0;
Povratna vrijednost funkcije; kod funkcije main() oznaˇcava vrijednost koju program
vra´ca operacijskom sustavu. Ako je program ispravno obavio posao, potrebno je
vratiti nulu; inaˇce se navodi neka druga (cjelobrojna) vrijednost.
5. {}
Vitiˇcaste zagrade sluˇze za grupiranje pojedinih cjelina programa. Ovdje je to upo-
trijebljeno za grupiranje dvije naredbe u funkciju main().
U C-u se ne navode brojevi linija (kao, na primjer, u BASICu). Ovdje te brojeve
navodimo samo za lakˇse snalaˇzenje u kodu.
Program iz primjera 4.2.1 je ispravno napisani program u jeziku C koji ´ce ispisati
ˇzeljenu poruku. Ve´cina danaˇsnjih C compilera ´ce prihvatiti i jednostavnije verzije, poput
1 main ( ) {
2 pr i nt f ( ” he l l o , worl d\n” ) ;
3 }
Ipak, mi ´cemo pisati korektne programe, jer prilikom “skra´civanja” kompliciranijih pro-
grama moˇze do´ci do problema: neobiˇcna ponaˇsanja programa ili nemogu´cnost prevodenja
na nekom raˇcunalu ili compileru.
4.3 Ispis
U prethodnom poglavlju vidjeli smo osnovni program koji prilikom svakog izvrˇsavanja
ispisuje isti tekst. Nakon izvrˇsavanja naredbe printf(), kursor ostaje toˇcno tamo gdje je
ispis stao. Idu´ci poziv naredbe printf() ´ce nastaviti pisati upravo na tom mjestu. Zbog
toga, isti ispis kao u primjeru 4.2.1 daje i sljede´ci program:
1 #include <s t di o . h>
2
3 i nt main( void) {
4 pr i nt f ( ” h e l l ” ) ;
5 pr i nt f ( ”o , ” ) ;
6 pr i nt f ( ” worl d” ) ;
7 pr i nt f ( ”\n” ) ;
8 return 0;
9 }
Bilo kakvo drugaˇcije cjepkanje niza znakova “hello, world” bi poluˇcilo isti rezultat.
Primijetimo da je potrebno ispisati sve znakove (tj. compiler ne´ce niˇsta sam dodati).
Zbog toga smo tre´ci printf() zapoˇceli razmakom jer je to prvi znak koji ˇzelimo ispisati
iza zareza (njega ispisuje drugi printf()).
Ispisati moˇzemo i brojˇcane vrijednosti, jednostavnim uvrˇstavanjem u niz znakova:
4.3. Ispis 63
1 pr i nt f ( ”Prog1 cu p o l o z i t i s ocjenom 4 i l i 5. \ n” ) ;
Ponekad ˇzelimo neke vrijednosti navesti odvojeno. Tada u nizu znakova koji ispisujemo
treba navesti gdje ´ce se dodatne vrijednosti pojaviti, te kojeg su one tipa (cijeli broj,
realni broj, znak, niz znakova,...).
Primjer 4.3.1 (Ispis dodatnih vrijednosti).
1 pr i nt f ( ”Ovdje cemo i s p i s a t i %s v r i j e dno s t i : ” ,
2 ” r a z l i c i t e ” ) ;
3 pr i nt f (
4 ” c i j e l i br oj %d , r e a l ni br oj %g i znak %c . \ n” ,
5 17 ,
6 17. 19 , ’Q’
7 ) ;
Ova naredba ispisuje sljede´ci tekst:
Ovdje cemo ispisati razlicite vrijednosti: cijeli broj 17,
realni broj 17.19 i znak Q.
Tekst ´ce biti ispisan u jednoj liniji (izmedu zareza i rijeˇci “realni” nalazit ´ce se razmak).
Ovdje je razlomljen samo zato da bi stao na stranicu.
Nakon izvrˇsavanja naredbi printf(), kursor ´ce biti na poˇcetku sljede´ceg retka (zbog
znaka \n na kraju).
Podizrazi koji se navode u naredbi printf(), a poˇcinju znakom % zovu se formati
za ispis. Njih ´cemo koristiti u svim primjerima i zadacima. Znaˇcenje samih formata je
detaljno objaˇsnjeno na predavanjima.
Primijetimo da naredbe smijemo “lomiti” izmedu parametara (npr. novi redak izmedu
17 i 17.19). To je poˇzeljno raditi da bi programi bili pregledniji, no ne treba pretjerivati.
ˇ
Cemu sluˇze formati? Oˇcito, program koji ispisuje uvijek istu poruku nije naroˇcito ko-
ristan. Potrebno je omogu´citi uˇcitavanje vrijednosti, raˇcunanje, snimanje i mnoge druge
operacije da bi program mogao rjeˇsavati odredene probleme. U tu svrhu koristimo vari-
jable, ˇcije vrijednosti ´cemo onda ispisivati upravo pomo´cu formata u naredbi printf().
64 4. Uvod u algoritme i osnovni program
Poglavlje 5
Varijable
U ovom poglavlju bavimo se spremanjem podataka u memoriju, bez ˇcega bi svaki program
radio uvijek isto, bez mogu´cnosti da mu zadajemo podatke. Prvo ´cemo prikazati s kakvim
sve podacima moˇzemo baratati, a zatim i na koji naˇcin to radimo.
5.1 Uvod
Varijable su simboliˇcka imena za memorijske lokacije u koje pohranjujemo vrijednosti.
Svaka varijabla ima tip koji treba navesti prije upotrebe varijable. Osnovni tipovi su:
• brojevi (cijeli, realni,. . . )
• znakovi
• pokazivaˇci (sadrˇze adrese drugih varijabli)
Neki jezici imaju i logiˇcki tip (varijable koje mogu imati samo dvije vrijednosti: istina
i laˇz), no u C-u tog tipa nema. Umjesto logiˇckog tipa koristi se cjelobrojni, gdje 0
predstavlja laˇz, a sve ostale vrijednosti predstavljaju istinu (obiˇcno koristimo vrijednost
1).
Napomena 5.1.1. Naˇcin uˇcitavanja varijabli ovisi o tipu varijable! Varijable nekog od
osnovnih tipova moˇzemo uˇcitati direktno (pomo´cu naredbe scanf() ili neke sliˇcne), dok
za sloˇzene tipove treba posebno sloˇziti dio programa za uˇcitavanje.
Naredba scanf() prihva´ca formate sliˇcne onima koje prima naredba printf(). Ti
formati se moraju slagati s tipom varijable koju uˇcitavamo.
Napomena 5.1.2. Funkcije u C-u ne mogu mijenjati vrijednosti varijabli koje
navedemo kao ulazne parametre (pri pozivu funkcije)! Zbog toga funkciji scanf()
zadajemo adrese varijabli u koje spremamo uˇcitane vrijednosti. Adresu varijable dobijamo
operatorom &.
65
66 5. Varijable
Dakle, ako imamo varijablu x, onda njenu adresu moˇzemo dobiti izrazom &x.
Zadatak 5.1.1. Napiˇsite program koji uˇcitava tri cijela broja i ispisuje njihovu sumu.
Rjeˇsenje.
1 #include <s t di o . h>
2
3 i nt main( void) {
4 i nt a , b , c ; / ∗ D e k l a r a c i j a v a r i j a b l i ∗ /
5 s c anf ( ”%d” , &a ) ; / ∗ U c i t a v a n j e j e d n e v a r . ∗ /
6 s c anf ( ”%d %d” , &b , &c ) ; / ∗ U c i t a v a n j e d v i j e v a r . ∗ /
7 pr i nt f ( ”%d + %d + %d = %d\n” , a , b , c , a + b + c ) ;
8 return 0;
9 }
U naredbama scanf() (linije 5 i 6), kao i u naredbi printf(), prvo navodimo formate
vrijednosti koje uˇcitavamo. Pri tome, %d oznaˇcava cijeli broj. Nakon formata (navedenih
unutar dvostrukih navodnika) popisujemo adrese varijabli koje uˇcitavamo.
U liniji 7 vidimo klasiˇcan ispis tri varijable i jednog izraza.
Napomena 5.1.3 (Komentari). Tekst naveden izmedu /* i */ je komentar, ˇsto znaˇci
da ga compiler ignorira. Koristimo ga kao zabiljeˇske za lakˇse snalaˇzenje u programskom
kodu.
Na sliˇcan naˇcin uˇcitavamo znakove (tip char), ali upotrebom formata %c. Bitna razlika
je u tome ˇsto prilikom uˇcitavanja viˇse brojeva, pripadne formate odvajamo razmakom (v.
liniju 6 u rjeˇsenju prethodnog zadatka), dok kod znakova taj razmak izostavljamo. Razlozi
takvog navodenja formata objaˇsnjeni su na predavanjima.
Zadatak 5.1.2. Napiˇsite program koji uˇcitava tri znaka, te ih ispisuje obrnutim redosli-
jedom.
Uˇcitavanje niza znakova je sloˇzenije i to ´cemo kasnije obraditi. Ako ˇzelimo ispisati niz
znakova, to radimo pomo´cu formata %s. Sam niz znakova navodimo pomo´cu dvostrukih
navodnika (v. primjer 4.3.1). Na primjer, dio koda
printf("Danas %sje lijep dan.\n", "ni");
´ce ispisati
Danas nije lijep dan.
Za realne brojeve koristimo tipove float (format %f) i double (format %lg). Potonji
omogu´cuje ve´ci raspron vrijednosti.
5.2. Jo
ˇ
s o formatima 67
Zadatak 5.1.3. Napiˇsite program koji uˇcitava tri realna broja (jedan tipa float i dva
tipa double), te ispisuje njihov produkt.
Rjeˇsenje.
1 #include <s t di o . h>
2
3 i nt main( void) {
4 f l oat a ;
5 double b , c ;
6 s c anf ( ”%f ” , &a ) ;
7 s c anf ( ”%l g %l g ” , &b , &c ) ;
8 pr i nt f ( ”%g ∗ %g ∗ %g = %g\n” , a , b , c , a ∗ b ∗ c ) ;
9 return 0;
10 }
Prilikom ispisa varijabli tipa double ne treba navoditi l u formatu.
5.2 Joˇs o formatima
Pomo´cu formata moˇzemo dodatno definirati izgled ispisanog teksta.
Primjer 5.2.1.
1 #include <s t di o . h>
2
3 i nt main ( void) {
4 i nt i ;
5
6 / ∗ u c i t a v a n j e v a r . t i p a i n t u d e k a d s k o m z a p i s u ∗ /
7 s c anf ( ”%d” , &i ) ;
8
9 / ∗ i s p i s u j e m o v a r i j a b l u i u r a z l i c i t i m f o r m a t i m a : ∗ /
10
11 / ∗ −−− d e k a d s k o m −−−> % d i l i % i ∗ /
12 pr i nt f ( ” dekadski z api s : %d\n” , i ) ;
13
14 / ∗ −−− o k t a l n o m −−−> % o ∗ /
15 pr i nt f ( ” okt al ni z api s : %o\n” , i ) ;
16
17 / ∗ −−− h e x a d e c i m a l n o m s v e l i k i m s l o v i m a −−−> % X ∗ /
18 pr i nt f ( ”hexadec . z api s s vel i ki m sl ovi ma : %X\n” , i ) ;
19
20 / ∗ −−− h e x a d e c i m a l n o m s m a l i m s l o v i m a −−−> % x ∗ /
21 pr i nt f ( ”hexadec . z api s s malim sl ovi ma : %x\n” , i ) ;
22
68 5. Varijable
23 / ∗ −−− m i n . 1 0 m j e s t a , d e s n o p o r a v n a v a n j e −> % 1 0 d ∗ /
24 pr i nt f ( ”10 mj esta desno poravnavanato : %10d\n” , i ) ;
25
26 / ∗ −−− m i n . 7 m j e s t a , l i j e v o p o r a v n a v a n j e −> % −7 d ∗ /
27 pr i nt f ( ”7 mj esta s l i j e v o poravnavnato : %−7d\n” , i ) ;
28
29 / ∗ u c i t a v a n j e u o k t a l n o m i l i h e x − f o r m a t u : ∗ /
30 pr i nt f ( ” une s i t e c i j e l i br oj u hex−formatu ” ) ;
31 pr i nt f ( ” ( mala s l ova ) : ” ) ;
32 s c anf ( ”%x” , &i ) ;
33 pr i nt f ( ”dekadska vr i j e dno s t od %x j e %d\n” , i , i ) ;
34
35 / ∗ u c i t a m o l i i n t s a % i f o r m a t s e a u t o m a t s k i ∗ /
36 / ∗ p r e p o z n a j e ∗ /
37 / ∗ 0 1 2 3 −> o k t a l n i z a p i s ; 0 x 1 2 3 −> h e x − z a p i s ∗ /
38 s c anf ( ”%i ” , &i ) ;
39 pr i nt f ( ”dec : %d ; oct : %o ; hex : %x” , i , i , i ) ;
40
41 return 0;
42 }
Formati %o, %x i %X rade samo s nenegativnim cijelim brojevima!
Formati kod ispisa realnih brojeva:
• %f – obicni decimalni zapis, npr. 3.14159
• %e – e-notacija, npr. -3.14e-3; koristi slovo e
• %E – e-notacija, npr. -3.14E-3; koristi slovo E
• %g – automatski se prepoznaje o kojem se tipu zapisa radi; ako je potrebna e-
notacija, koristi se slovo e
• %G – automatski se prepoznaje o kojem se tipu zapisa radi; ako je potrebna e-
notacija, koristi se slovo E
Napomena 5.2.1. Znak “%” ispisujemo navodenjem formata %%.
Primjer 5.2.2.
1 #include <s t di o . h>
2
3 i nt main ( void) {
4 double dbl ;
5 f l oat f l t ;
6
7 s c anf ( ”%f ” , &f l t ) ;
5.2. Jo
ˇ
s o formatima 69
8 pr i nt f ( ”%%f −−> %f \n” , f l t ) ;
9 pr i nt f ( ”%%e −−> %e\n” , f l t ) ;
10 pr i nt f ( ”%%g −−> %g\n” , f l t ) ;
11
12 / ∗ d a b i u c i t a l i d o u b l e N U Z N O j e k o r i s t i t i p r e f i x l
13 / ∗ z a i s p i s n e t r e b a ∗ /
14 s c anf ( ”%l g ” , &dbl ) ;
15
16 / ∗ % . 5 f −−> z a o k r u z e n o n a 5 d e c i m a l n i h m j e s t a ∗ /
17 pr i nt f ( ” zaokruzeno na 5 dec . mj esta : %.5 f \n” , dbl ) ;
18
19 / ∗ % . 0 f −−> z a o k r u z e n o n a 0 d e c . m j e s t a ∗ /
20 / ∗ d e c i m a l n a t o c k a s e n e i s p i s u j e ∗ /
21 pr i nt f ( ” zaokruzeno na 0 dec . mj esta : %.0 f \n” , dbl ) ;
22
23 / ∗ % 1 0 . 3 f −−> z a o k r u z e n o n a 3 d e c . m j e s t a , t r o s i ∗ /
24 / ∗ u k u p n o n a j m a n j e 1 0 z n a k o v a ∗ /
25 pr i nt f ( ” zaokruzeno na 3 dec . mj esta , ukupno bar ” ) ;
26 pr i nt f ( ”10 znakova : \ ’ %10. 3 f \ ’ \n” , dbl ) ;
27
28 / ∗ N a i s t i n a c i n z a o k r u z u j e m o i s % e i % g ∗ /
29 pr i nt f ( ”2 dec . mj esta , ukupno bar 12 znakova , ” ) ;
30 pr i nt f ( ”poravnato l i j e v o : \’%−12.2e \ ’ \n” , dbl ) ;
31
32 return 0;
33 }
Pokazivaˇci (engl. pointeri) sadrˇze, kako smo naveli, memorijske adrese. Raˇcunalo sve,
pa tako i adrese, pamti kao brojeve. Zbog toga pokazivaˇce moˇzemo ispisati kao prirodne
brojeve (unsigned int):
1 i nt x = 17;
2 pr i nt f ( ”x = %d , &x = %u\n” , x , &x ) ;
Napomena 5.2.2. U nastavku ´cemo uglavnom navoditi samo tijela ili dijelove programa,
bez zaglavlja. Naravno, inaˇce programe treba pisati cijele, osim ako je u zadatku
naglaˇseno da se piˇse samo dio programa! Da biste na raˇcunalu testirali dijelove
programa, potrebno je dopisati one dijelove koji nedostaju (u pravilu zaglavlja, deklaracije
i uˇcitavanja varijabli, ispisi,. . . ).
Takoder, viˇse ne´cemo posebno oznaˇcavati razmake u programima.
70 5. Varijable
Poglavlje 6
Osnovne raˇcunske operacije
Vrijednosti nije dovoljno pohraniti. Oˇcito, potrebno nam je i nekakvo mijenjanje tih
vrijednosti koje se obiˇcno svodi na raˇcunanje i pohranjivanje novih vrijednosti u nove ili
ve´c koriˇstene varijable.
6.1 Uvod
Cijele brojeve moˇzemo zbrajati (operator +), oduzimati (operator -), mnoˇziti (operator
*) i dijeliti (operatori / i %). Operatori +, - i * se ponaˇsaju identiˇcno kao u matematici
(s tim da treba paziti da rezultat nije prevelik, tj. da ga spremamo u varijablu s dovoljno
memorije).
Operator dijeljenja, /, vra´ca cjelobrojni rezultat dijeljenja dva cijela broja, dok ope-
rator ostatka, %, vra´ca ostatak pri dijeljenju dva cijela broja.
Ukoliko je jedan od operanada realan broj, operacije se vrˇse realno (a ne cjelobrojno).
Primjer 6.1.1.
1 i nt a = 17 , b = 7;
2 double c = 17. 0 , d = 7 . 0 ;
3 pr i nt f ( ”a+b=%d , a−b=%d , a∗b=%d , a/b=%d , a%%b=%d\n” ,
4 a+b , a−b , a∗b , a/b , a%b ) ;
5 pr i nt f ( ”a+d=%g , a−d=%g , a∗d=%g , a/d=%g” ,
6 a+d , a−d , a∗d , a/d ) ;
7 pr i nt f ( ”c+d=%g , c−d=%g , c∗d=%g , c/d=%g” ,
8 c+d , c−d , c∗d , c/d ) ;
Ispis ovog dijela programa bit ´ce
a+b=24, a-b=10, a*b=119, a/b=2, a%b=3
a+d=24, a-d=10, a*d=119, a/d=2.42857
c+d=24, c-d=10, c*d=119, c/d=2.42857
71
72 6. Osnovne ra
ˇ
cunske operacije
Primijetite razliku u rezultatima cjelobrojnog (prva linija ispisa) i realnog dijeljenja (druga
i tre´ca linija ispisa).
Napomena 6.1.1 (
ˇ
Cesta greˇska). Razlikujte znakove “/”, “|” i “\”! Znak “/” oznaˇcava
dijeljenje koje ne smijete pisati “a \ b”, dok znak “\” sluˇzi za specijalne znakove, tj.
skok u novi red ne smijete pisati “/n”! Znak “|” oznaˇcava operator bitwise-OR i ne
moˇze biti zamjena niti za jedan od preostala dva znaka.
6.2 Pridruˇzivanje
Varijabli pridruˇzujemo vrijednost tako da iza nje stavimo znak = i desno od njega nave-
demo vrijednost koju pridruˇzujemo. Na primjer, izraz
x = 17;
´ce varijabli x pridruˇziti vrijednost 17. Na sliˇcan naˇcin varijabli moˇzemo pridruˇziti i rezultat
nekog izraza. Na primjer, izraz
x = a + b;
´ce varijabli x pridruˇziti rezultat zbrajanja varijabli a i b.
Svi izrazi u C-u vra´caju neku vrijednost, pa tako i izraz x = A. Rezultat koji taj izraz
vra´ca je upravo vrijednost izraza A. Zbog toga smijemo napisati i
y = (x = 17);
ˇsto ´ce varijablama x i y pridruˇziti vrijednost 17. Dapaˇce, ovakvo pridruˇzivanje moˇzemo
navesti i bez zagrada (iz razloga objaˇsnjenih na predavanjima). Na primjer, izraz
y = x = a + b;
´ce varijablama x i y pridruˇziti rezultat zbrajanja vrijednosti koje se nalaze u varijablama
a i b.
Vrijednost koju ´cemo pridruˇziti nekoj varijabli smijemo raˇcunati pomo´cu te iste vari-
jable. Na primjer:
p = p * 2;
Prilikom pridruˇzivanja izraza varijabli, raˇcunalo prvo raˇcuna vrijednost desne strane, te
tu vrijednost pridruˇzuje varijabli s lijeve strane znaka jednakosti. Dakle, ovaj izraz ´ce
udvostruˇciti vrijednost varijable p.
Navedeni izraz smo mogli i kra´ce zapisati:
6.2. Pridru
ˇ
zivanje 73
p *= 2.
Na taj naˇcin moˇzemo skratiti i ostale izraze oblika
a = a op b,
gdje je “op” neki operator. Dakle, sljede´ci izrazi su ekvivalentni:
x = x + d x += d
x = x - d x -= d
x = x * d x *= d
x = x / d x /= d
x = x % d x %= d
Isti naˇcin skra´civanja moˇze se primijeniti i na operatore koje ´cemo tek obraditi (logiˇcke,
bitovne,...).
Postoje joˇs i sljede´ce posebne pokrate:
x++ i ++x za inkrement, te
x-- i --x za dekrement.
Pri tome x++ i ++x pove´cavaju vrijednost varijable x za jedan, a razlikuju se u povratnoj
vrijednosti izraza. Naime, x++ vra´ca staru vrijednost varijable x (tj. onu vrijednost koju
je varijabla imala prije inkrementa), dok ++x vra´ca novu vrijednost varijable x (tj. onu
vrijednost koju je poprimila inkrementom).
Na sliˇcan naˇcin, izraz x-- smanjuje vrijednost od x za jedan i vra´ca staru vrijednost,
dok --x smanjuje vrijednost od x za jedan, ali vra´ca novu vrijednost.
Primjer 6.2.1. Pogledajmo dio programa:
1 i nt i = 17 , d = 17;
2
3 pr i nt f ( ” i = %d , ” , i ) ;
4 pr i nt f ( ” ( i ++) = %d , ” , i ++);
5 pr i nt f ( ” i = %d\n” , i ) ;
6
7 pr i nt f ( ” i = %d , ” , i ) ;
8 pr i nt f ( ”(++i ) = %d , ” , ++i ) ;
9 pr i nt f ( ” i = %d\n” , i ) ;
10
11 pr i nt f ( ”d = %d , ” , d ) ;
12 pr i nt f ( ” ( d−−) = %d , ” , d−−);
13 pr i nt f ( ”d = %d\n” , d ) ;
14
74 6. Osnovne ra
ˇ
cunske operacije
15 pr i nt f ( ”d = %d , ” , d ) ;
16 pr i nt f ( ”(−−d) = %d , ” , −−d ) ;
17 pr i nt f ( ”d = %d\n” , d ) ;
Ispis ovog dijela programa ´ce biti:
i = 17, (i++) = 17, i = 18
i = 18, (++i) = 19, i = 19
d = 17, (d--) = 17, d = 16
d = 16, (--d) = 15, d = 15
Kao ˇsto vidimo, izraz i++ je pove´cao vrijednost varijable i sa 17 na 18, ali je vrijednost
izraza jednaka 17 (dakle, vrijednost koju je varijabla i imala prije inkrementa). S druge
strane, izraz ++i je takoder pove´cao vrijednost varijable i (ovaj put s 18 na 19), ali je
njegova povratna vrijednost jednaka novoj vrijednosti varijable i (dakle, 19).
Analogno vrijedi i za operator --.
Napomena 6.2.1. Na sljede´ci naˇcin moˇzete jednostavno zapamtiti “koji je koji” (na
primjeru operatora za inkrement): ++x ima operator prije varijable, pa se zato prvo
pove´ca vrijednost varijable, a zatim vrati. S druge strane, izraz x++ ima operator nakon
varijable, pa se zato prvo vrati vrijednost varijable, pa tek onda pove´ca.
Tehniˇcki, ovo nije ispravno, jer se vrijednost izraza vra´ca uvijek nakon ˇsto je sve ostalo
raˇcunanje gotovo, no dobro je kao sugestija prilikom pam´cenja operatora.
Poglavlje 7
Grananje
ˇ
Cesto ˇzelimo da se, ovisno o vrijednostima varijabli, izvrˇse razliˇcite naredbe. U tu svrhu
koristimo obiˇcno grananje (if), uvjetni operator (?:) ili viˇsestruko grananje (koje ´cemo
obraditi u poglavlju 9).
7.1 Obiˇcno grananje
Zadatak 7.1.1. Napiˇsite dio programa koji uˇcitava cijeli broj i ispisuje poruku je li taj
broj negativan.
Rjeˇsenje.
1 i nt x ;
2 s c anf ( ”%d” , &x ) ;
3 i f ( x < 0)
4 pr i nt f ( ”Broj %d j e negati van . \ n” , x ) ;
5 el se
6 pr i nt f ( ”Broj %d ni j e negati van . \ n” , x ) ;
Grananje ima nekoliko komponenti:
1. Kljuˇcna rijeˇc if i uvjet koji provjeravamo.
2. Programski kod koji se izvodi ako je uvjet istinit.
3. Kljuˇcna rijeˇc else i programski kod koji se izvrˇsava ako uvjet nije istinit. Ovaj dio
nije nuˇzno navesti ako u sluˇcaju neispunjenja uvjeta ne treba niˇsta izvrˇsiti.
Napomena 7.1.1. Ako se u nekom sluˇcaju (npr. kad je uvjet ispunjen) treba izvrˇsiti viˇse
naredbi, onda ih grupiramo pomo´cu vitiˇcastih zagrada!
75
76 7. Grananje
Zadatak 7.1.2. Napiˇsite dio programa koji uˇcitava cijeli broj i ispisuje poruku je li taj
broj paran.
Uputa. Upotrijebite operator %.
Uvjete moˇzemo kombinirati kao i u logici sudova.
Zadatak 7.1.3. Napiˇsite dio programa koji uˇcitava cjelobrojne varijable a, b i c, te
ispisuje je li a ve´ci od b i c.
Rjeˇsenje.
1 i nt a , b , c ;
2 s c anf ( ”%d %d %d” , &a , &b , &c ) ;
3 i f ( a > b && a > c )
4 pr i nt f ( ”Broj %d j e ve c i od %d i %d. \ n” , a , b , c ) ;
5 el se
6 pr i nt f ( ”Broj %d ni j e ve c i od %d i %d. \ n” , a , b , c ) ;
Operator && oznaˇcava “logiˇcko I”, operator || oznaˇcava “logiˇcko ILI”, dok operator !
oznaˇcava logiˇcku negaciju. Dakle izraz
(a > b) i (c > d ili e = d)
C-ovski zapisujemo kao
(a > b) && (!(c > d) || e == d).
Napomena 7.1.2 (
ˇ
Cesta greˇska). Operator za provjeru jednakosti dva broja je == (dvos-
truko “jednako”). Treba paziti da ga se ne zamijeni s = (jednostruko “jednako”), ˇsto je
uvijek pridruˇzivanje!
Napomena 7.1.3. U C-u ne postoje znakovi ≤ i ≥. Umjesto njih, koristimo <= i >=
respektivno (NE =< i =>!).
Operator za provjeru “razliˇcitosti” je != (“uskliˇcnik” i “jednako”, bez razmaka izmedu).
Dakle, uvjet x != y znaˇci x = y.
Napomena 7.1.4 (
ˇ
Cesta greˇska). Operatori && i || povezuju logiˇcke izraze. Drugim
rijeˇcima, izraz
a > b, c
ne smijemo
1
zapisati kao
1
U stvari, smijemo napisati i a > b && c i a > b, c, ali ´ce rezultat u oba sluˇcaja biti pogreˇsan
(evaluirat ´ce se drugaˇcije od oˇcekivanog). Pokuˇsajte otkriti kako C interpretira takve izraze.
7.2. Uvjetni operator 77
a > b && c ili a > b, c.
Ispravan naˇcin za zapisati zadani izraz je
a > b && a > c.
Zadatak 7.1.4. Napiˇsite dio programa koji uˇcitava cjelobrojne varijable a, b i c koje
imaju vrijednosti 0 ili 1 (potrebno je provjeriti da je dobro upisano i, ako nije, prijaviti
greˇsku). Potom, program treba re´ci je li izraz
¯ abc + a
¯
bc + ab¯ c + abc
istinit ili laˇzan.
Uputa. Pojednostavite izraz, “pretvorite” ga u C-ovski zapis i upotrijebite if.
7.2 Uvjetni operator
U C-u postoji posebni operator ?: koji sluˇzi za jednostavnije ubacivanje uvjeta u izraze.
Osnovni poziv operatora izgleda ovako:
x = (UVJ ? A : B);
Pri tome, varijabla x poprima vrijednost izraza A ako je uvjet UVJ zadovoljen, odnosno
vrijednost izraza B ako uvjet UVJ nije zadovoljen. Zapisano pomo´cu if, taj izraz izgleda
ovako:
if (UVJ) x = A; else x = B;.
Primjer 7.2.1. Uˇcitavamo cijeli broj x i ispisujemo prvi parni broj strogo ve´ci od njega.
Pri tome koristimo ˇcinjenicu da je idu´ci parni broj x+1 ako je x neparan, odnosno x+2
ako je x paran.
1 s c anf ( ”%d” , &x ) ;
2 pr i nt f ( ” Prvi par ni br oj s t r o\−go ve c i od %d j e %d . ” ,
3 x , ( x % 2 == 1 ? x + 1 : x + 2 ) ) ;
Napomena 7.2.1. Podsjetimo se: ako broj promatramo kao logiˇcki izraz, onda 0 oz-
naˇcava laˇz, a sve ostalo istinu. Zbog toga, gornji dio koda smo mogli zapisati i bez “== 1”:
1 s c anf ( ”%d” , &x ) ;
2 pr i nt f ( ” Prvi par ni br oj s t r o\−go ve c i od %d j e %d . ” ,
3 x , ( x % 2 ? x + 1 : x + 2 ) ) ;
78 7. Grananje
Poglavlje 8
Petlje
Gotovo svaki program neke dijelove koda izvodi viˇse puta, u pravilu svaki put s drugim
vrijednostima nekih varijabli. U tu svrhu koristimo razne petlje. U C-u postoje while(),
for() i do...while(), a izbor one “prave” ovisi o tome ˇsto se toˇcno traˇzi, kao i o ukusu
programera. Same petlje su ekvivalentne i svaka moˇze manje ili viˇse jednostavno zamijeniti
ostale dvije.
Nakon pregleda petlji u C-u, objasnit ´cemo ˇsto je to sloˇzenost algoritama i kako
usporedujemo razliˇcite algoritme koji rjeˇsavaju isti problem.
8.1 while()-petlja
Zadatak 8.1.1. Napiˇsite dio programa koji uˇcitava prirodni broj x i ispisuje sve potencije
broja 2 strogo manje od x.
Rjeˇsenje.
1 unsigned long i nt x , p = 1;
2
3 pr i nt f ( ” Unesi t e x : ” ) ;
4 s c anf ( ”%l u ” , &x ) ;
5 while ( p < x) {
6 pr i nt f ( ”%u\n” , p ) ;
7 p ∗= 2;
8 }
U prethodnom rjeˇsenju imamo nekoliko novosti:
• U deklaraciji (linija 1) deklariramo varijable x i p, te za njihov tip navodimo
unsigned long int.
79
80 8. Petlje
Kad brojevnom tipu dodamo atribut unsigned, compileru dajemo do znanja da
´cemo u tu varijablu pohranjivati iskljuˇcivo nenegativne vrijednosti (engl. unsig-
ned znaˇci “bez predznaka”). Zbog toga ˇsto ne trebamo pamtiti negativne brojeve,
umjesto njih moˇzemo pamtiti duplo viˇse pozitivnih brojeva. Varijable s atributom
unsigned se u raˇcunalu pamte kao obiˇcni binarni brojevi, jer nema potrebe za dvoj-
nim komplementima.
Atribut long znaˇci da ´ce varijabla zauzeti dvostruko viˇse memorije. Posljedica je
opet mogu´cnost memoriranja viˇse vrijednosti. Kako ovdje radimo s potencijama,
vrijednosti ´ce brzo rasti, pa je dobro imati varijable koje mogu pamtiti ˇsto viˇse
vrijednosti.
• Takoder u deklaraciji, imamo izraz p = 1. Naime, moˇzemo zadati vrijednost varija-
ble odmah prilikom deklaracije. Tako smo ovdje deklarirali varijablu x kojoj nismo
zadali nikakvu vrijednost (pa ´ce ona biti neka sluˇcajna) i varijablu p kojoj dajemo
vrijednost 1.
• U liniji 4 uˇcitavamo cjelobrojnu vrijednost u varijablu x. Format %u najavljuje
uˇcitavanje varijable tipa unsigned int, dok slovo l dodajemo prilikom uˇcitavanja
bilo koje varijable tipa long.
Primijetite da smo slovo l dodali i prilikom uˇcitavanja varijable dbl u primjeru
5.2.2. To je zato jer je double zapravo long float.
• U liniji 5 vidimo zaglavlje while petlje: kljuˇcna rijeˇc while i uvjet (naveden u oblim
zagradama) do kada se petlja izvrˇsava.
Nakon svakog izvrˇsavanja tijela petlje, provjerava se uvjet. Ako je on istinit, tijelo petlje
se ponovno izvrˇsava; ako nije, izvrˇsavanje programa se nastavlja nakon petlje.
U praksi, prirodne brojeve moˇzemo spremati i u “obiˇcan” int (dakle, ne nuˇzno u
unsigned int). Mi ´cemo uglavnom koristiti int, neovisno o tome radi li se s prirodnim
ili s cijelim brojevima, jer udvostruˇcenje raspona nije naroˇcito veliko, a moˇze prouzroˇciti
probleme (kako ´cemo vidjeti u jednom od zadataka).
Napomena 8.1.1. Uvjet petlje se ne provjerava u toku izvodenja tijela petlje!
Zadatak 8.1.2. Napiˇsite dio programa koji uˇcitava prirodni broj x, te ispisuje je li on
prost ili nije.
Rjeˇsenje.
1 i nt x , p = 2 , pr os t = 1;
2
3 pr i nt f ( ” Unesi t e x : ” ) ;
4 s c anf ( ”%d” , &x ) ;
5 i f ( x < 2) pr os t = 0;
6 while ( pr os t && p < x) {
7 i f ( x % p == 0) pr os t = 0;
8.2. for()-petlja 81
8 p++;
9 }
10 i f ( pr os t ) pr i nt f ( ”Broj j e pr os t . \ n” ) ; el se
11 pr i nt f ( ”Broj ni j e pr os t . \ n” ) ;
8.2 for()-petlja
Zadatak 8.2.1. Napiˇsite dio programa koji uˇcitava prirodni broj n, te ispisuje koliko je
k! za sve prirodne k manje ili jednake n.
Rjeˇsenje.
1 i nt k , n , f akt = 1;
2
3 pr i nt f ( ” Unesi t e n : ” ) ; s c anf ( ”%d” , &n ) ;
4 for ( k = 1; k <= n ; k++) {
5 f akt ∗= k ;
6 pr i nt f ( ”%d ! = %d\n” , k , f akt ) ;
7 }
Navedeni programski isjeˇcak je ekvivalentan sljede´cem kodu:
1 i nt k , n , f akt = 1;
2
3 pr i nt f ( ” Unesi t e n : ” ) ; s c anf ( ”%d” , &n ) ;
4 k = 1;
5 while ( k <= n) {
6 f akt ∗= k ;
7 pr i nt f ( ”%d ! = %d\n” , k , f akt ) ;
8 k++;
9 }
Prikazana konverzija for() u while() se uvijek moˇze provesti.
Kod for() petlje imamo tri polja:
for(INICIJALIZACIJA; UVJET; INKREMENT).
Nije nuˇzno navesti sva polja. Na primjer, prethodni zadatak smo mogli rijeˇsiti i is-
puˇstanjem (tj. premjeˇstanjem) inicijalizacije i inkrementa:
1 i nt k , n , f akt = 1;
2
82 8. Petlje
3 pr i nt f ( ” Unesi t e n : ” ) ; s c anf ( ”%d” , &n ) ;
4 k = 1;
5 for ( ; k <= n ; ) {
6 f akt ∗= k ;
7 pr i nt f ( ”%d ! = %d\n” , k , f akt ) ;
8 k++;
9 }
Primijetite da separatori izmedu polja (;) moraju ostati!
8.3 do...while()-petlja
Ponekad ˇzelimo da se dio programa izvrˇsi nekoliko puta, ali bezuvjetno barem jednom.
Kod while() i for(), uvjet se provjerava prije prvog izvrˇsavanja tijela petlje. Da bismo
tu (prvu) provjeru izbjegli, koristimo do...while petlju.
Zadatak 8.3.1. Napiˇsite dio programa koji uˇcitava prirodne brojeve i ispisuje njihovu
sumu. Uˇcitavanje treba prekinuti kad korisnik upiˇse vrijednost 0.
Rjeˇsenje.
1 i nt sum = 0 , x ;
2
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ;
5 s c anf ( ”%d” , &x ) ;
6 sum += x ;
7 } while ( x != 0 ) ;
8
9 pr i nt f ( ”Suma uc i t ani h br oj eva j e %d. \ n” , sum) ;
Ovaj kod trivijalno moˇzemo pretvoriti u while() ili for() na sljede´ci naˇcin
1 i nt sum = 0 , x = 1;
2
3 while ( x != 0) {
4 pr i nt f ( ” Unesi t e br oj : ” ) ;
5 s c anf ( ”%d” , &x ) ;
6 sum += x ;
7 };
8
9 pr i nt f ( ”Suma uc i t ani h br oj eva j e %d. \ n” , sum) ;
Primijetite da smo varijabli x pridruˇzili vrijednost 1 (mogla je biti bilo koja vrijednost raz-
liˇcita od nule!). Bez toga, program bi bio neispravan jer ne smijemo ˇcitati vrijednost
8.4. Zadaci 83
varijable prije nego joj pridruˇzimo neku vrijednost (npr. pomo´cu pridruˇzivanja ili
scanf()).
Ovdje smo iskoristili pomo´cnu varijablu x, no postoji i “recept” koji uvijek vrijedi.
Primjer 8.3.1. Pretvorite programski kod
1 do {
2 TIJELO;
3 } while (UVJET) ;
u while() i for().
To radimo koriˇstenjem pomo´cne varijable koja ´ce biti istinita samo prilikom prve pro-
vjere uvjeta (te ´ce tako osigurati da se tijelo petlje barem jednom izvrˇsi):
1 pr vi kor ak = 1;
2 while ( pr vi kor ak | | UVJET) {
3 pr vi kor ak = 0;
4 TIJELO;
5 }
Analogno, slaˇzemo for() petlju:
1 for ( pr vi kor ak = 1; pr vi kor ak | | UVJET; ) {
2 pr vi kor ak = 0;
3 TIJELO;
4 }
Ovdje, for() petlja nema inkrement, ali ima inicijalizaciju.
Zadatak 8.3.2. Pretvorite sljede´ce programske isjeˇcke u do...while petlju:
1 for ( INICIJALIZACIJA; UVJET; INKREMENT) {
2 TIJELO;
3 }
i
1 while (UVJET) {
2 TIJELO;
3 }
8.4 Zadaci
Zadatak 8.4.1. Napiˇsite dio programa koji uˇcitava cijele brojeve dok korisnik ne upiˇse
nulu. Program treba ispisati produkt svih brojeva koje je korisnik uˇcitao.
Rjeˇsenje. U zadatku 8.3.1, uˇcitanu nulu smo pribrojili sumi. To smijemo raditi u sluˇcaju
sume jer ona ostaje nepromijenjena. No, u sluˇcaju produkta, nula bi poniˇstila rezultat,
pa na to treba paziti.
84 8. Petlje
1 i nt prod = 1 , x ;
2
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ;
5 s c anf ( ”%d” , &x ) ;
6 i f ( x != 0) prod ∗= x ;
7 } while ( x != 0 ) ;
8
9 pr i nt f ( ”Produkt uc i t ani h br oj eva j e %d. \ n” , prod ) ;
Zadatak 8.4.2. Napiˇsite dio programa koji uˇcitava prirodne brojeve dok korisnik ne upiˇse
nulu. Program treba ispisati vrijednost najve´ceg uˇcitanog broja, te koji je on (po redu)
uˇcitan.
Rjeˇsenje. Poˇsto uˇcitavamo prirodne brojeve, znamo da ´ce svi biti nenegativni. Dakle,
moˇzemo pretpostaviti da je maksimum neki negativni broj (npr. −1), pa ´ce prvi uˇcitani
broj sigurno biti ve´ci i onda ´ce postaviti ispravnu vrijednost maksimuma.
Nadalje, moramo pamtiti i koji broj (po redu) uˇcitavamo, te koji je redni broj samog
maksimuma. Za to ´ce sluˇziti varijable i (kao index) i im (kao index maksimuma).
1 i nt max = −1, x , i = 0 , im;
2
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ;
5 s c anf ( ”%d” , &x ) ;
6 i ++;
7 i f ( x > max) {
8 max = x ;
9 im = i ;
10 }
11 } while ( x != 0 ) ;
12
13 pr i nt f ( ” Naj veci uc i t a ni br oj j e %d , uci t an ” , max ) ;
14 pr i nt f ( ” %d . po redu . \ n” , im ) ;
Zadatak 8.4.3. Napiˇsite dio programa koji uˇcitava cijele brojeve dok korisnik ne upiˇse
nulu. Program treba ispisati vrijednost najve´ceg uˇcitanog broja, te koji je on (po redu)
uˇcitan.
Rjeˇsenje. Na ˇzalost, sada ne moˇzemo krenuti od najmanjeg broja jer takav ne postoji u
skupu cijelih brojeva. Zbog toga je bolje prvi broj uˇcitati posebno i odmah tu vrijednost
pridruˇziti varijabli max. Takoder, treba zadati i poˇcetnu vrijednost varijabli i i im.
8.4. Zadaci 85
1 i nt max, x , i = 1 , im = 1;
2
3 pr i nt f ( ” Unesi t e br oj : ” ) ;
4 s c anf ( ”%d” , &x ) ;
5 max = x ;
6
7 while ( x != 0) {
8 pr i nt f ( ” Unesi t e br oj : ” ) ;
9 s c anf ( ”%d” , &x ) ;
10 i ++;
11 i f ( x && x > max) {
12 max = x ;
13 im = i ;
14 }
15 }
16
17 pr i nt f ( ” Naj veci uc i t a ni br oj j e %d , uci t an ” , max ) ;
18 pr i nt f ( ” %d . po redu . \ n” , im ) ;
Prikazani naˇcin djeluje op´cenito (dakle, mogao je biti ispravno rjeˇsenje prethodnog za-
datka). Drugi mogu´ci naˇcin je izoliranje prvog koraka (u ovisnosti o parametru i):
1 i nt max, x = 1 , i = 0 , im;
2
3 while ( x != 0) {
4 pr i nt f ( ” Unesi t e br oj : ” ) ;
5 s c anf ( ”%d” , &x ) ;
6 i ++;
7 i f ( i == 1 | | ( x && x > max) ) {
8 max = x ;
9 im = i ;
10 }
11 }
12
13 pr i nt f ( ” Naj veci uc i t a ni br oj j e %d , uci t an ” , max ) ;
14 pr i nt f ( ” %d . po redu . \ n” , im ) ;
Primijetite da smo sada varijabli x morali zadati inicijalnu vrijednost koja osigurava ulazak
u petlju u prvom koraku. To nije morala biti vrijednost 1, nego bilo koja koja zadovoljava
uvijet while() petlje (x != 0).
Zadatak 8.4.4. Napiˇsite dio programa koji uˇcitava prirodni broj n, te uˇcitava n realnih
brojeva. Program treba ispisati sumu najve´ceg i najmanjeg uˇcitanog broja.
Uputa. Kad petlja treba imati unaprijed odredeni broj koraka, praktiˇcno je upotrijebiti
for(). Preporuˇca se uzeti inicijalizaciju i = 0 i uvjet i < n, jer je tako lakˇse raditi s
poljima (koja ´cemo kasnije obraditi).
86 8. Petlje
Zadatak 8.4.5. Napiˇsite dio programa koji uˇcitava prirodni broj n, te uˇcitava n cijelih
brojeva. Program treba ispisati sumu svih parnih i produkt svih neparnih brojeva.
Ako nije uˇcitan niti jedan paran broj, pripadna suma je 0; ako nije uˇcitan niti jedan
neparan broj, pripadni produkt je 1.
Zadatak 8.4.6. Napiˇsite dio programa koji uˇcitava prirodne brojeve n i k, te ispisuje
koliko je

n
k

.
Rjeˇsenje. Prema definiciji vrijedi:

n
k

=
n!
k!(n −k)!
.
No, faktorijele su ˇcesto veliki brojevi, ˇsto moˇze izazvati overflow. Zbog toga je puno bolje
raˇcunati
n · (n −1) · · · · · (k + 1)
(n −k)!
ili
n · (n −1) · · · · · (n −k + 1)
k!
,
ovisno o tome kakvi su n i k. Prva formula je “bolja” ako je n −k < k, tj. n < 2k.
Sliˇcno prethodnom programu, opet je praktiˇcno upotrijebiti for():
1 i nt i , n , k , povrh = 1;
2 pr i nt f ( ” Unesi t e n : ” ) ; s c anf ( ”%d” , &n ) ;
3 pr i nt f ( ” Unesi t e k : ” ) ; s c anf ( ”%d” , &k ) ;
4 i f ( n < 2 ∗ k) {
5 for ( i = n ; i > k ; i −−) povrh ∗= i ;
6 for ( i = 1; i <= n − k ; i ++) povrh /= i ;
7 } el se {
8 for ( i = n ; i > n − k ; i −−) povrh ∗= i ;
9 for ( i = 1; i <= k ; i ++) povrh /= i ;
10 }
11 pr i nt f ( ” Rezul t at : %d\n” , povrh ) ;
Primijetimo da promjenom inkrementa (i, shodno tome, inicijalizacije i uvjeta), for()
petlja moˇze i´ci i “prema gore” i “prema dolje”.
Napomena 8.4.1. Primijetimo da su dijeljenja u linijama 6 i 9 u rjeˇsenju prethodnog
zadatka cjelobrojna. To smijemo napraviti zato jer znamo da je

n
k

uvijek cijeli broj!
Inaˇce, morali bismo paziti da dijeljenje bude realno.
Zadatak 8.4.7. Napiˇsite dio program koji za zadani prirodni broj n ispisuje vrijednost
izraza
n
¸
i=1
a
i
· i,
gdje je
a
i
=

1, i paran
3, i neparan
.
8.4. Zadaci 87
Rjeˇsenje. Uz for() petlju, ovdje ´ce nam pomo´ci uvjetni operator:
1 i nt i , r e s = 0;
2 for ( i = 1; i <= n ; i ++)
3 r e s += i ∗ ( i % 2 ? 3 : 1 ) ;
4 pr i nt f ( ”%d\n” , r e s ) ;
Napomena 8.4.2. Podsjetimo se: izraz i % 2 vra´ca ostatak pri dijeljenju i s 2. Poˇsto
ga koristimo kao uvjet, taj uvjet ´ce biti istinit ako je ostatak razliˇcit od 0 (tj. ako je broj
neparan). Ako je broj paran, tj. rezultat je nula, uvjet je laˇzan.
Petlje se mogu smjeˇstati jedna u drugu. Pri tome treba paziti kako koristimo varijable,
da jedna petlja ne bi naruˇsila vrijednosti o kojima ovisi uvjet druge petlje.
Za razliku od dijelova programa, napiˇsimo i jedan cijeli program:
Zadatak 8.4.8. Napiˇsite program koji uˇcitava n prirodnih brojeva, te ispisuje produkt
prostih.
Rjeˇsenje. U zadatku 8.1.2 smo vidjeli kako se provjerava je li broj prost. Sad ´cemo taj
programski kod kombinirati s rjeˇsenjem zadatka 8.4.5:
1 #include <s t di o . h>
2
3 i nt main( void) {
4 i nt n , i , x , p , prost , prod = 1;
5
6 pr i nt f ( ” Unesi t e n : ” ) ;
7 s c anf ( ”%d” , &n ) ;
8
9 for ( i = 0; i < n ; i ++) {
10 pr i nt f ( ” Unesi t e br oj : ” ) ;
11 s c anf ( ”%d” , &x ) ;
12 p = 2;
13 pr os t = ( x > 1 ) ;
14 while ( pr os t && p < x) {
15 i f ( x % p == 0) pr os t = 0;
16 p++;
17 }
18 i f ( pr os t ) prod ∗= x ;
19 }
20 pr i nt f ( ”%d\n” , prod ) ;
21 return 0;
22 }
88 8. Petlje
Zadatak 8.4.9. Napiˇsite dio programa koji za zadane prirodne brojeve n i b (b ≥ 2)
ispisuje koliko znamenaka ima dekadski broj n ako ga zapiˇsemo u bazi b.
Rjeˇsenje.
1 i nt i = 0;
2 while ( n > 0) {
3 n /= b ;
4 i ++;
5 }
6 pr i nt f ( ” Rezul t at : %d\n” , i ) ;
Zadatak 8.4.10. Primijetite da bi u rjeˇsenju prethodnog zadaka ispis
printf("Broj %d u bazi %d ima %d znamenaka.\n", n, b, i);
bio pogreˇsan. U ˇcemu je greˇska i kako ju ispraviti (a da poruka ostane kako smo ju upravo
naveli)?
Uputa. Isprobajte program na raˇcunalu i primijetite da ´ce ispis uvijek zapoˇcinjati s
“Broj 0 u bazi...”. Vrijednost koju n ima prije petlje treba saˇcuvati u pomo´cnoj vari-
jabli jer uzastopnim dijeljenjima tu vrijednost gubimo!
Zadatak 8.4.11. Napiˇsite dio programa koji uˇcitava prirodne brojeve dok ne uˇcita nulu.
Za svaki broj (osim nule) treba ispisati sumu njegovih znamenaka u bazi 7.
Rjeˇsenje.
1 i nt x , sum, t ;
2
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
5 sum = 0;
6 i f ( x) {
7 t = x ;
8 while ( t > 0) {
9 sum += ( t % 7 ) ;
10 t /= 7;
11 }
12 pr i nt f ( ”Suma znamenaka : %d\n” , sum) ;
13 }
14 } while ( x ) ;
8.4. Zadaci 89
Napomena 8.4.3. Kao ˇsto vidimo, ako zadatak zahtijeva, rezultat se moˇze ispisati i u
tijelu petlje; ne nuˇzno izvan nje. Nema recepta gdje ide ispis rezultata; to treba shvatiti iz
teksta zadatka!
Sljede´ci zadatak je izuzetno vaˇzan za razumjeti, zajedno s ˇcestim greˇskama koje na-
vodimo odmah nakon ispravnog rjeˇsenja.
Zadatak 8.4.12. Napiˇsite dio programa koji uˇcita prirodni broj b, a zatim uˇcitava pri-
rodne brojeve dok ne uˇcita nulu. Program treba ispisati sumu najve´cih znamenaka svih
uˇcitanih brojeva zapisanih u bazi b.
Rjeˇsenje.
1 i nt x , sum, t , max;
2
3 sum = 0;
4 do {
5 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
6 max = 0;
7 t = x ;
8 while ( x > 0) {
9 i f (max < ( x % b) ) max = x % b ;
10 x /= b ;
11 }
12 sum += max;
13 } while ( t ) ;
14 pr i nt f ( ”Suma naj veci h znamenaka : %d\n” , sum) ;
Ovakvim zadacima treba pristupiti oprezno. Primijetimo da traˇzimo sumu – jednu
za cijeli program – ˇsto znaˇci da nju treba inicijalizirati izvan svih petlji. Traˇzimo i
neki maksimum – ali po jedan za svaki uˇcitani broj – pa njega moramo inicijalizirati
unutar petlje u kojoj uˇcitavamo brojeve! Pogledajmo dvije ˇceste greˇske:
1. Ako sumu inicijaliziramo unutar do...while petlje, onda ´ce se ona za svaki uˇcitani
broj “vra´cati” na nulu, pa ´ce na kraju imati vrijednost jednaku najve´coj znamenci
posljednjeg uˇcitanog broja (a to je 0):
1 do {
2 sum = 0;
3 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
4 max = 0;
5 t = x ;
6 while ( x > 0) {
7 i f (max < ( x % b) ) max = x % b ;
8 x /= b ;
90 8. Petlje
9 }
10 sum += max;
11 } while ( t ) ;
Isprobajte za b = 10 i uˇcitane brojeve 17, 19, 31 i 0 (suma bi trebala biti 7+9+3 =
19, a ispast ´ce 0).
2. Ako max inicijaliziramo izvan do...while, onda se najve´ca znamenka brojeva uˇcitanih
nakon prvog ne´ce dobro raˇcunati:
1 sum = 0;
2 max = 0;
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
5 t = x ;
6 while ( x > 0) {
7 i f (max < ( x % b) ) max = x % b ;
8 x /= b ;
9 }
10 sum += max;
11 } while ( t ) ;
Isprobajte za b = 10 i uˇcitane brojeve 17, 19, 31 i 0. Suma bi opet trebala biti
7 + 9 + 3 = 19, no umjesto toga program ´ce izraˇcunati najve´cu znamenku broja
17 i ona ´ce (ispravno) ispasti 7. To ´ce biti vrijednost varijable max nakon prvog
izvodenja tijela petlje. Zatim ´ce taj 7 (nepromijenjen, jer se max postavlja na nulu
samo prije tijela do...while petlje!) usporedivati s 1 i 9 (od broja 19) i dobit ´ce
(ispravno) najve´cu znamenku drugog broja: 9. No, za tre´ci broj, usporedivat ´ce
znamenke 3 i 1 s maksimumom, a to ´ce (opet, od prije) biti 9. Kako je su i 3 i 1
manji od 9, vrijednost varijable max ´ce i za tre´ci broj ostati 9, pa ´ce ispasti suma
7 + 9 + 9 = 25 ˇsto je pogreˇsno!
Dodatno, u rjeˇsenju ovog zadatka, uvjet u vanjskoj while() petlji ovisi o t, dok je u
prethodnom zadatku ovisio o x. Ta razlika proizlazi iz naˇcina na koji te varijable koristi-
mo. Naime, unutarnja petlja dijeli jednu od tih varijabli dok njena vrijednost ne padne
na nulu, pa nam ta varijabla viˇse nema nikakvu korisnu vrijednost (nakon izvrˇsavanja
petlje, vrijednost je nuˇzno nula!). S druge strane, uvjet u vanjskoj petlji mora ovisiti o
originalnom uˇcitanom broju. Zato u prethodnom zadatku u unutraˇsnjoj petlji “troˇsimo”
pomo´cnu varijablu t, pa uvjet ovisi o nepromijenjenoj varijabli x, dok u ovom zadatku
u unutraˇsnjoj petlji “troˇsimo” varijablu x, pa uvjet ovisi o njenoj poˇcetnoj vrijednosti
pospremljenoj u varijabli t. Naravno, ovi naˇcini su ekvivalentni, dakle oba ispravna.
8.5. Malo o slo
ˇ
zenosti 91
8.5 Malo o sloˇzenosti
Ve´cinu zadataka mogu´ce je rijeˇsiti na viˇse naˇcina, od kojih su neki “brˇzi”, a neki “sporiji”.
Sloˇzenost algoritama bavi se usporedivanjem algoritama, pri tome zanemaruju´ci dobitke u
brzini koji se mogu dobiti jednostavnom kupnjom brˇzeg hardwarea. To znaˇci da program
koji radi 2 puta brˇze od drugog programa nije interesantan (u terminima sloˇzenosti), dok
onaj koji za ulaz n ∈ N (ˇsto god n bio) radi u vremenu n sekundi umjesto n
2
sekundi
smatramo velikim poboljˇsanjem. Dapaˇce, poboljˇsanje je i svaki onaj program koji radi
u vremenu c · n sekundi, gdje je c ∈ R
+
neka konstanta, bez obzira na veliˇcinu same
konstante c.
Zadatak 8.5.1. Napiˇsite dio programa koji uˇcitava prirodni broj n, te ispisuje sve djelitelje
broja n (proizvoljnim redoslijedom, ali svakog toˇcno jednom).
Rjeˇsenje (jednostavno).
1 i nt i , n ;
2
3 s c anf ( ”%d” , &n ) ;
4 for ( i = 1; i <= n ; i ++)
5 i f ( ! ( n % i ) ) pr i nt f ( ”%d\n” , i ) ;
U ovom rjeˇsenju provjeravamo djeljivost sa svim brojevima od 1 do n. No, ako pogle-
damo rastav
n = p · q,
primijetit ´cemo da ne moˇze biti p, q >
n
2
, jer bismo onda imali
n = p · q >
n
2
4
⇒ n < 4.
Dakle, dana situacija je mogu´ca samo za brojeve 1, 2 i 3. No, to nisu sloˇzeni brojevi,
tj. djeljivi su samo s 1 i sa samim sobom, pa niti kod njih ograniˇcenje i ≤
n
2
ne uvodi
probleme. Drugim rijeˇcima, brˇzi algoritam je:
Rjeˇsenje (dvostruko brˇze).
1 i nt i , n , lmt ;
2
3 s c anf ( ”%d” , &n ) ;
4 lmt = n / 2;
5 i f ( n > 1)
6 for ( i = 1; i <= lmt ; i ++)
7 i f ( ! ( n % i ) ) pr i nt f ( ”%d\n%d\n” , i , n / i ) ;
8 pr i nt f ( ”%d\n” , n ) ;
92 8. Petlje
Ovaj program ´ce se izvoditi dvostruko brˇze od prethodnog, no to znaˇci da smo jed-
nako ubrzanje mogli dobiti i kupnjom dvostruko brˇzeg raˇcunala. U terminima sloˇzenosti
algoritama, algoritmi su jednako sloˇzeni (oba su linearni!).
Joˇs gore, neki djelitelji ´ce se ispisati dva puta (npr. 2 i 4 za n = 16). To se moˇze
rijeˇsiti dodatnim uvjetom:
Rjeˇsenje (ispravak prethodnog).
1 i nt i , n , lmt , t ;
2
3 s c anf ( ”%d” , &n ) ;
4 lmt = n / 2;
5 for ( i = 1; i <= lmt ; i ++)
6 i f ( ! ( n % i ) )
7 i f ( ( t = n / i ) <= lmt )
8 pr i nt f ( ”%d\n” , i ) ;
9 el se
10 pr i nt f ( ”%d\n%d\n” , i , t ) ;
U ovim rjeˇsenjima smo uveli pomo´cnu varijablu lmt koja sluˇzi tome da se izraz n / 2
ne raˇcuna u svakom koraku petlje, nego samo jednom. Takva uvodenja pomo´cnih varijabli
su uvijek poˇzeljna, i zbog brzine izvrˇsavanja i zbog preglednosti programa: rijeˇc “lmt” je
izabrano kao pokrata engleske rijeˇci limit, dok slovo “t” oznaˇcava privremenu varijablu,
engl. temporary. Za limit nismo uzeli jednoslovnu pokratu jer je slovo “l” presliˇcno broju
1, pa moˇze zbuniti kod ˇcitanja programa (prilikom uˇcenja ili traˇzenja greˇsaka).
Dodatni uvjeti znaˇce i dodatno raˇcunanje, pa ostaje upitno je li (i koliko) ovakav pro-
gram uop´ce brˇzi od prvog rjeˇsenja (raˇcunalo obavlja razliˇcite zada´ce razliˇcitom brzinom).
Zbog toga se, prilikom raˇcunanja sloˇzenosti algoritama, i inzistira da se algoritmi razlikuju
za viˇse od konstantnog faktora.
Ako iskoristimo ˇcinjenicu da ne postoji x ∈ N takav da je n djeljiv s x i
n
2
< x < n,
onda zadatak moˇzemo rijeˇsiti i ovako:
Rjeˇsenje (poboljˇsanje prethodnog).
1 i nt i , n , lmt ;
2
3 s c anf ( ”%d” , &n ) ;
4 lmt = n / 2;
5 for ( i = 1; i <= lmt ; i ++)
6 i f ( ! ( n % i ) )
7 pr i nt f ( ”%d\n” , i ) ;
8 pr i nt f ( ”%d\n” , n ) ;
8.5. Malo o slo
ˇ
zenosti 93
Postignuto ubrzanje je i dalje dvostruko (dakle, konstantno, tj. neovisno o n).
Primijetimo da iz
n = p · q
moˇzemo zakljuˇciti da je
p ≤

n ili q ≤

n,
ˇsto nas navodi na zakljuˇcak da je granica (varijabla l u programima) mogla biti jednaka

n. Takvo rjeˇsenje zahtijeva i poziv matematiˇcke funkcije sqrt():
Rjeˇsenje (manja sloˇzenost).
1 #include <s t di o . h>
2 #include <math . h>
3
4 i nt main ( ) {
5 i nt i , n , lmt ;
6 s c anf ( ”%d” , &n ) ;
7 lmt = s qr t ( n ) ;
8 for ( i = 1; i <= lmt ; i ++)
9 i f ( ! ( n % i ) )
10 pr i nt f ( ”%d\n%d\n” , i , n / i ) ;
11 return 0;
12 }
Na poˇcetku je bilo potrebno dodati #include<math.h> zbog koriˇstenja matematiˇcke
funkcije koja radi s realnim vrijednostima. Prilikom compiliranja u komandnoj liniji, u
ovom je sluˇcaju nuˇzno dodati i opciju -lm.
Ovo rjeˇsenje je zaista manje sloˇzeno. Na primjer, za n = 16 petlja se vrti 4 umjesto 16
(u prvom rjeˇsenju) ili 8 puta (u drugom rjeˇsenju), ˇsto je ˇcetverostruko, odnosno dvostruko
ubrzanje. No, za n = 64, petlja se vrti 8 puta, umjesto starih 64 odnosno 32, ˇsto je
ubrzanje od 8, odnosno 4 puta. Dakle, dobiveno ubrzanje raste s veliˇcinom ulaza n, pa je
ovo rjeˇsenje zaista manje sloˇzeno!
Granicu

n ne moˇzemo dodatno smanjiti, ˇsto se pokazuje jednostavnim traˇzenjem
protuprimjera (npr. za n = 9 moramo izvrˇsiti provjere od 1 do 3).
Zadatak 8.5.2. Modificirajte prethodni program tako da ne koristi funkciju sqrt(), ali
da i dalje radi provjere samo za i ≤

n.
Uputa. Modificirajte uvjet petlje.
Zadatak 8.5.3. Napiˇsite dio programa koji za zadani prirodni broj n ispisuje sve njegove
proste djelitelje (svakog toˇcno jednom).
94 8. Petlje
Rjeˇsenje. Naizgled jednostavan naˇcin za napisati ovaj program je traˇzenje svih djelitelja
(kao u prethodnim zadacima), te provjera za svakoga je li prost ili nije. Takvo rjeˇsenje
ostavljamo ˇcitateljima za vjeˇzbu.
Umjesto opisanog pristupa, moˇzemo traˇziti najmanji broj x (ve´ci od 1) s kojim je n
djeljiv. Takav broj nuˇzno mora biti prost, jer kad bi postojali a > 1 i b > 1 takvi da
je x = a · b, onda bi nuˇzno bilo a, b < x i n bi bio djeljiv s a i b, ˇsto je kontradiktorno
pretpostavci da je x najmanji takav broj.
Idu´ci korak je dijeljenje n s pronadenim x dok god je to mogu´ce. Nakon toga se
vra´camo na traˇzenje idu´ceg najmanjeg djelitelja dobivenog broja. To ponavljamo dok
god ima smisla traˇziti njegove djelitelje (tj. dok god je n > 1).
1 i nt x = 2;
2 while ( n > 1) {
3 i f ( ! ( n % x ) ) {
4 pr i nt f ( ”%d\n” , x ) ;
5 while ( ! ( n % x ) ) n /= x ;
6 }
7 x++;
8 }
Sljede´ca modifikacija zadatka, iako naizgled kompliciranija, zapravo ima jednostavnije
rjeˇsenje:
Zadatak 8.5.4. Napiˇsite dio programa koji za zadani prirodni broj n ispisuje sve njegove
proste djelitelje (svakog toˇcno onoliko puta koliko se pojavljuje u rastavu broja n na proste
faktore).
Rjeˇsenje.
1 i nt x = 2;
2 while ( n > 1) {
3 while ( ! ( n % x ) ) {
4 pr i nt f ( ”%d\n” , x ) ;
5 n /= x ;
6 }
7 x++;
8 }
Zadatak 8.5.5. Napiˇsite dio programa koji za zadani prirodni broj n ispisuje sve njegove
proste djelitelje (svakog toˇcno jednom), te uz svakoga napiˇse koliko puta se pojavljuje u
rastavu broja n na proste faktore. Npr. za n = 96 = 2
5
· 3
1
program treba ispisati:
2^5
3^1
8.5. Malo o slo
ˇ
zenosti 95
Zadatak 8.5.6. Napiˇsite dio programa koji uˇcitava realni broj x i prirodni broj n, te
ispisuje koliko je x
n
.
Rjeˇsenje.
1 i nt i , n ;
2 double x , r e s = 1;
3
4 pr i nt f ( ” Unesi t e n : ” ) ; s c anf ( ”%d” , &n ) ;
5 pr i nt f ( ” Unesi t e x : ” ) ; s c anf ( ”%l g ” , &x ) ;
6 for ( i = 0; i < n ; i ++) r e s ∗= x ;
7 pr i nt f ( ”(%g)ˆ%d = %g” , x , n , r e s ) ;
Primijetimo da izraz res *= n izvrˇsavamo n puta, ˇsto znaˇci da je sloˇzenost programa
linearna. Moˇze li bolje?
Odgovor je (krajnje (ne)oˇcekivnano): moˇze. Primijenimo uzastopno kvadriranje. Na
primjer:
x
8
= ((x
2
)
2
)
2
, tj. x
2
= x · x, x
4
= x
2
· x
2
, x
8
= x
4
· x
4
,
pa imamo samo 3 mnoˇzenja (umjesto 8). Na taj naˇcin moˇzemo dobiti x
n
ako je n potencija
od 2.
ˇ
Sto ako nije?
Pogledajmo sljede´ce primjere:
n = 9 ⇒ n = 8 + 1 ⇒ x = x
8
· x
1
n = 12 ⇒ n = 8 + 4 ⇒ x = x
8
· x
4
Dakle, broj n treba prikazati kao zbroj nekih potencija broja 2. Moˇzemo li to izvesti za
svaki prirodni n?
Naravno. Upravo takav rastav ˇcini prikaz broja u binarnoj bazi! Dakle, broj n treba
prikazati u binarnom sustavu. Za prethodne primjere:
(9)
10
=
3 2 1 0
(1001)
2
⇒ x
9
= x
2
3
· x
2
0
(12)
10
=
3 2 1 0
(1100)
2
⇒ x
12
= x
2
3
· x
2
2
Vidjeli smo kako se prebrojavaju i ispisuju znamenke. Sada samo, umjesto ispisivanja
binarnih znamenki, treba te znamenke iskoristiti kao uvjet u mnoˇzenju. Preciznije, kad
god je binarna znamenka 1 mnoˇzimo rezultat s x
k
, gdje je x
k
odgovaraju´ca potencija od
x (prvo x
1
, pa x
2
, pa x
4
, pa x
8
itd.).
1 i nt n , on ;
2 double x , r e s = 1 , pot ;
3
96 8. Petlje
4 pr i nt f ( ” Unesi t e n : ” ) ; s c anf ( ”%d” , &n ) ;
5 pr i nt f ( ” Unesi t e x : ” ) ; s c anf ( ”%l g ” , &x ) ;
6 pot = x ; on = n ;
7
8 while ( n > 0) {
9 i f ( n % 2) r e s ∗= pot ;
10 pot ∗= pot ;
11 n /= 2;
12 }
13
14 pr i nt f ( ”(%g)ˆ%d = %g” , x , on , r e s ) ;
U najgorem sluˇcaju (za n = 2
neˇsto
− 1) imamo 2 puta viˇse mnoˇzenja nego n ima
znamenaka i toˇcno onoliko dijeljenja koliko n ima binarnih znamenaka, a to je log
2
n
(dokaˇzite!). Dakle, sloˇzenost ovakvog potenciranja je logaritamska, ˇsto je puno bolje od
linearne.
8.6 Promjena toka petlje
Ponekad “usred izvrˇsavanja” ˇzelimo prekinuti petlju ili “skoˇciti” natrag na uvjet. Vratimo
se na zadatak 8.1.2 gdje je trebalo provjeriti je li zadani broj prost. Petlja kojom smo
vrˇsili provjeru izgledala je ovako:
5 while ( pr os t && p < x) {
6 i f ( x % p == 0) pr os t = 0;
7 p++;
8 }
Dakle, u svakom koraku petlje, kao dio uvjeta se provjerava stanje varijable prost.
Takoder, nakon ˇsto varijabli prost zadamo vrijednost 0, program ´ce i dalje izvesti li-
niju 7 (p++;) iako je ona nepotrebna.
Prirodan naˇcin za provesti provjeru bi, opisno, bio:
5 dok ( p ni j e pr e ve l i k ) {
6 ako j e ( x d j e l j i v s p) {
7 zapamti da x ni j e pr os t
8 pr e ki ni pr ovj er u
9 }
10 povecaj p za j edan
11 }
Petlju prekidamo naredbom break. Prikazani opisni kod moˇzemo doslovno prevesti u C
liniju po liniju:
5 while ( p < x) {
6 i f ( x % p == 0) {
8.6. Promjena toka petlje 97
7 pr os t = 0;
8 break ;
9 }
10 p++;
11 }
U trenutku kad se izvrˇsi naredba break, program bezuvjetno prekida izvrˇsavanje tijela
petlje. Izvrˇsavanje programa se nastavlja nakon tijela petlje (na naredbi koja bi se nalazila
u liniji 12).
Sliˇcno, u zadatku 8.4.11 imali smo petlju:
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
5 sum = 0;
6 i f ( x) {
7 t = x ;
8 while ( t > 0) {
9 sum += ( t % 7 ) ;
10 t /= 7;
11 }
12 pr i nt f ( ”Suma znamenaka : %d\n” , sum) ;
13 }
14 } while ( x ) ;
Bilo bi daleko prirodnije jednostavno prekinuti izvrˇsavanje petlje onda kad znamo da smo
gotovi (umjesto da ve´ci dio tijela petlje “zapakiramo” u if()):
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
5 sum = 0;
6 i f ( ! x) break ;
7 t = x ;
8 while ( t > 0) {
9 sum += ( t % 7 ) ;
10 t /= 7;
11 }
12 pr i nt f ( ”Suma znamenaka : %d\n” , sum) ;
13 } while ( x ) ;
Dapaˇce, ako je x == 0, petlja ´ce prekinuti odmah u liniji 6. Ako je x != 0, onda je uvjet
u liniji 13 istinit, pa nema potrebe da ga provjeravamo. To znaˇci da liniju 13 moˇzemo
zamijeniti s:
13 } while ( 1 ) ;
No, sada nam viˇse ne treba varijabla x, pa ju ne moramo “spaˇsavati” upotrebom pomo´cne
varijable t. Konaˇcno, cijelu petlju moˇzemo zapisati ovako:
3 do {
98 8. Petlje
4 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
5 sum = 0;
6 i f ( ! x) break ;
7 while ( x > 0) {
8 sum += ( x % 7 ) ;
9 x /= 7;
10 }
11 pr i nt f ( ”Suma znamenaka : %d\n” , sum) ;
12 } while ( 1 ) ;
Naredbu break moˇzemo ˇcitati kao “skoˇci iza tijela petlje”.
Na sliˇcan naˇcin, naredba continue prekida izvrˇsavanje petlje i nastavlja:
• s inkrementom, te provjerom uvjeta (kod for() petlje) ili
• s provjerom uvjeta (kod while() i do...while petlje).
Pogledajmo zadatak:
Zadatak 8.6.1. Napiˇsite program koji uˇcitava prirodni broj n, te zatim uˇcitava joˇs n
prirodnih brojeva. Program treba ispisati sumu svih znamenaka parnih uˇcitanih brojeva
(neparne jednostavno ignorira) zapisanih u bazi 10.
Rjeˇsenje.
1 i nt n , i , x , sum;
2
3 sum = 0;
4 pr i nt f ( ” Unesi t e n : ” ) ; s c anf ( ”%d” , &n ) ;
5 for ( i = 0; i < n ; i ++) {
6 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
7 i f ( x % 2) continue ;
8 while ( x > 0) {
9 sum += ( x % 10) ;
10 x /= 10;
11 }
12 }
13 pr i nt f ( ”Suma znamenaka : %d\n” , sum) ;
Oˇcito, problem smo mogli rijeˇsiti i pomo´cu else:
5 for ( i = 0; i < n ; i ++) {
6 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
7 i f ( x % 2 ) ; el se
8 while ( x > 0) {
9 sum += ( x % 10) ;
8.6. Promjena toka petlje 99
10 x /= 10;
11 }
12 }
ili pomo´cu negiranog uvjeta:
5 for ( i = 0; i < n ; i ++) {
6 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
7 i f ( ! ( x % 2) )
8 while ( x > 0) {
9 sum += ( x % 10) ;
10 x /= 10;
11 }
12 }
Naredbe break i continue se uvijek mogu “zaobi´ci”, ali kod sloˇzenijih problema to moˇze
biti izuzetno komplicirano (mnogo if...else blokova jedan unutar drugog, te dodavanje
pomo´cnih varijabli). Kompliciranje ˇcesto dovodi do greˇsaka, pa se preporuˇca koriˇstenje
ovih naredbi kad god je to prirodno.
Ponekad koristimo “beskonaˇcne petlje”. To su, kako naziv kaˇze, petlje ˇciji je uvjet
uvijek zadovoljen. Kako svaki algoritam mora stati nakon konaˇcno mnogo koraka (prema
definiciji algoritma!), takve petlje je nuˇzno prekinuti “na silu”, upravo naredbom break.
Pogledajmo zadatak sliˇcan zadatku 8.3.1:
Zadatak 8.6.2. Napiˇsite dio programa koji uˇcitava prirodne brojeve i ispisuje njihov
produkt. Uˇcitavanje treba prekinuti kad korisnik upiˇse vrijednost 0.
Rjeˇsenje.
1 i nt prod = 1 , x ;
2
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ;
5 s c anf ( ”%d” , &x ) ;
6 i f ( x) prod ∗= x ;
7 } while ( x != 0 ) ;
8
9 pr i nt f ( ”Produkt uc i t ani h br oj eva j e %d. \ n” , prod ) ;
Petlju smo mogli i drugaˇcije napisati. Najprije opisno:
3 r adi {
4 uc i t a j x
5 ako j e x j ednak nul i , pr e ki ni pe t l j u
6 povecaj produkt
7 };
Prisjetimo se: istina je svaka vrijednost razliˇcita od nule. Obiˇcno se koristi vrijednost 1.
100 8. Petlje
C-ovski, prikazani opisni kod bi izgledao ovako:
3 do {
4 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
5 i f ( x == 0) break ;
6 prod ∗= x ;
7 } while ( 1 ) ;
ili
3 while ( 1) {
4 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
5 i f ( x == 0) break ;
6 prod ∗= x ;
7 }
ili
3 for ( ; 1; ) {
4 pr i nt f ( ” Unesi t e br oj : ” ) ; s c anf ( ”%d” , &x ) ;
5 i f ( x == 0) break ;
6 prod ∗= x ;
7 }
Ovdje to ne izgleda naroˇcito korisno, ali kod sloˇzenih uvjeta moˇze biti jako praktiˇcno. Npr.
ako imamo nekoliko uvjeta, “razbacanih” po tijelu petlje, onda ih je teˇsko objediniti, pa
je lakˇse svakome zadati da prekine petlju, a onda sam uvjet petlje “izostaviti” (tj. staviti
da je uvijek istinit).
Ako uvjet for()-petlje nije naveden, smatra se da je on istinit. Dakle, liniju 3 iz
zadnjeg prikazanog programskog isjeˇcka moˇzemo jednostavnije zapisati ovako
3 for ( ; ; ) {
Napomena 8.6.1. Svaku petlju obavezno treba nekako prekinuti! Ako uvjet ne osigurava
prekidanje petlje za sve mogu´ce poˇcetne vrijednosti varijabli, onda prekidanje izvrˇsavanja
petlje nuˇzno treba osigurati naredbom break.
Naredbe break i continue utjeˇcu samo na izvrˇsavanje najdublje petlje u kojoj se
nalaze.
Primjer 8.6.1. Programski kod
1 for ( i = 0; i < 3; i ++) {
2 for ( j = i + 1; j < 999; j ++) {
3 pr i nt f ( ” Unutrasnj a pe t l j a : i = %d , j = %d\n” , i , j ) ;
4 break ;
5 }
6 pr i nt f ( ”Vanjska pe t l j a : i = %d\n” , i ) ;
7 }
8.6. Promjena toka petlje 101
´ce ispisati:
Unutrasnja petlja: i = 0, j = 1
Vanjska petlja: i = 0
Unutrasnja petlja: i = 1, j = 2
Vanjska petlja: i = 1
Unutrasnja petlja: i = 2, j = 3
Vanjska petlja: i = 2
Dakle, tijelo unutraˇsnje for petlje (linije 3 i 4) ´ce se izvrˇsiti toˇcno jednom za svaki i,
jer ´ce naredba break prekinuti unutraˇsnju petlju odmah nakon ispisa vrijednosti. S druge
strane, linija 6 ´ce se izvrˇsiti za svaki i jer break “skaˇce iza (unutraˇsnje) petlje”, pa se
izvrˇsavanje programa (nakon break) nastavlja upravo na liniji 6.
Zadatak 8.6.3. Napiˇsite program koji uˇcitava prirodne brojeve dok ne uˇcita nulu. Pro-
gram treba ispisati produkt znamenaka (u bazi 8) svih uˇcitanih prostih brojeva.
Uputa. Petlju je dobro prekinuti pomo´cu break odmah nakon uˇcitavanja broja ako je broj
jednak nuli. Zatim treba provjeriti je li broj prost. Ako nije, treba se vratiti (pomo´cu
continue) na poˇcetak petlje. Oˇcito, sva potrebna prekidanja petlje ´ce se izvrˇsiti pomo´cu
break, pa uvjet petlje moˇze uvijek biti istinit.
Zadatak 8.6.4. Prethodni zadatak rijeˇsite bez break i continue.
Zadatak 8.6.5. Napiˇsite program koji uˇcitava prirodni broj n, te pomo´cu zvjezdica (“*”)
iscrtava pravokutni trokut katete duljine n znakova. Na primjer, za n = 4 treba ispisati:
*
**
***
****
Rjeˇsenje.
1 i nt n , i , j ;
2
3 pr i nt f ( ” Unesi t e n : ” ) ; s c anf ( ”%d” , &n ) ;
4
5 for ( i = 0; i < n ; i ++) {
6 for ( j = 0; j <= i ; j ++)
7 pr i nt f ( ”∗” ) ;
8 pr i nt f ( ”\n” ) ;
9 }
102 8. Petlje
Zadatak 8.6.6. Napiˇsite program koji uˇcitava prirodni broj n, te pomo´cu zvjezdica (“*”)
iscrtava pravokutni trokut kojem je vertikalna kateta duljine n znakova, a horizontalna
duljine 2 * n - 1 znak. Na primjer, za n = 4 treba ispisati:
*
***
*****
*******
Zadatak 8.6.7 (
ˇ
Slag na kraju). Napiˇsite program koji uˇcitava prirodni broj n, te pomo´cu
zvjezdica (“*”) iscrtava krug radijusa n znakova.
Poglavlje 9
Viˇsestruko grananje
Ponekad imamo viˇse uvjeta koji ovise o istom izrazu. Tada ulanˇcavanje if()-ova ispa-
da nespretno i nezgodno, pogotovo ako blokovi koji se izvrˇsavaju moraju imati i neke
zajedniˇcke dijelove. Zbog toga pribjegavamo upotrebi viˇsestrukog grananja.
9.1 Naredba switch()
Primjer 9.1.1. Napiˇsite dio programa koji za zadani prirodni broj n ∈ {1, 2, . . . , 365}
ispisuje na koji dan u tjednu pada n-ti dan u godini (pretpostavite da godina poˇcinje
ponedjeljkom).
Klasiˇcno rjeˇsenje, pomo´cu if() bi bilo:
1 i f ( n % 7 == 0) pr i nt f ( ” Ne dj e l j a \n” ) ; el se
2 i f ( n % 7 == 1) pr i nt f ( ” Ponedj el j ak \n” ) ; el se
3 i f ( n % 7 == 2) pr i nt f ( ”Utorak\n” ) ; el se
4 i f ( n % 7 == 3) pr i nt f ( ” Sr i j e da \n” ) ; el se
5 i f ( n % 7 == 4) pr i nt f ( ” Cetvrtak\n” ) ; el se
6 i f ( n % 7 == 5) pr i nt f ( ”Petak\n” ) ; el se
7 pr i nt f ( ”Subota\n” ) ;
ili, da se smanji koliˇcina raˇcunanja:
1 i nt pom = n % 7;
2 i f (pom == 0) pr i nt f ( ” Ne dj e l j a \n” ) ; el se
3 i f (pom == 1) pr i nt f ( ” Ponedj el j ak \n” ) ; el se
4 i f (pom == 2) pr i nt f ( ”Utorak\n” ) ; el se
5 i f (pom == 3) pr i nt f ( ” Sr i j e da \n” ) ; el se
6 i f (pom == 4) pr i nt f ( ” Cetvrtak\n” ) ; el se
7 i f (pom == 5) pr i nt f ( ”Petak\n” ) ; el se
8 pr i nt f ( ”Subota\n” ) ;
Pomo´cu switch(), rjeˇsenje izgleda ovako:
103
104 9. Vi
ˇ
sestruko grananje
1 switch ( n % 7) {
2 case 0: pr i nt f ( ” Ne dj e l j a \n” ) ;
3 break ;
4 case 1: pr i nt f ( ” Ponedj el j ak \n” ) ;
5 break ;
6 case 2: pr i nt f ( ”Utorak\n” ) ;
7 break ;
8 case 3: pr i nt f ( ” Sr i j e da \n” ) ;
9 break ;
10 case 4: pr i nt f ( ” Cetvrtak\n” ) ;
11 break ;
12 case 5: pr i nt f ( ”Petak\n” ) ;
13 break ;
14 default : pr i nt f ( ”Subota\n” ) ;
15 }
Prilikom izvrˇsavanja, raˇcunalo ulazi u prvu granu koja ima vrijednost jednaku vri-
jednosti izraza, te nastavlja dalje. Ukoliko ˇzelimo prekinuti izvrˇsavanje naredbi unutra
switch() (tj. ˇzelimo “iza´ci” iz switch()), zadajemo narebu break (jednako kao kod pet-
lji). Grana default (nije obavezna!) se izvrˇsava ako niti jedan case nema vrijednost kao
zadani izraz (neˇsto kao else kod if() petlji).
Napomena 9.1.1. Ako ne zadamo break, izvrˇsavanje prelazi u idu´cu granu!
Primjer 9.1.2. Prethodni primjer, ali bez upotrebe break:
1 switch ( n % 7) {
2 case 0: pr i nt f ( ” Ne dj e l j a \n” ) ;
3 case 1: pr i nt f ( ” Ponedj el j ak \n” ) ;
4 case 2: pr i nt f ( ”Utorak\n” ) ;
5 case 3: pr i nt f ( ” Sr i j e da \n” ) ;
6 case 4: pr i nt f ( ” Cetvrtak\n” ) ;
7 case 5: pr i nt f ( ”Petak\n” ) ;
8 default : pr i nt f ( ”Subota\n” ) ;
9 }
´ce za n = 4 ispisati:
Cetvrtak
Petak
Subota
Zadatak 9.1.1. Napiˇsite dio programa koji za zadane prirodne brojeve p ∈ {1, 2, . . . , 7} i
n ∈ {1, 2, . . . , 365 −p} ispisuje na koji dan u tjednu pada n-ti dan u godini (pretpostavite
da godina poˇcinje ponedjeljkom ako je p = 1, utorkom ako je p = 2, itd.). Ukoliko je dan
koji ispisujete utorak ili petak, program treba ispisati i idu´ci dan.
9.1. Naredba switch() 105
Rjeˇsenje.
1 switch ( ( n + p − 1) % 7) {
2 case 0: pr i nt f ( ” Ne dj e l j a \n” ) ;
3 break ;
4 case 1: pr i nt f ( ” Ponedj el j ak \n” ) ;
5 break ;
6 case 2: pr i nt f ( ”Utorak\n” ) ;
7 case 3: pr i nt f ( ” Sr i j e da \n” ) ;
8 break ;
9 case 4: pr i nt f ( ” Cetvrtak\n” ) ;
10 break ;
11 case 5: pr i nt f ( ”Petak\n” ) ;
12 default : pr i nt f ( ”Subota\n” ) ;
13 }
Zadatak 9.1.2. Rijeˇsite prethodni program bez upotrebe switch().
Ukoliko dvije grane rade toˇcno jednak posao, nabrajamo ih jednu iza druge.
Zadatak 9.1.3. Napiˇsite dio programa koji za zadani prirodni broj n ispisuje je li zadnja
dekadska znamenka broja 3
n
prost broj ili ne.
Rjeˇsenje.
1 / ∗ R a c u n a n j e n − t e p o t e n c i j e b r o \ − j a 3 ∗ /
2 pot = 1;
3 while ( n−−) pot ∗= 3;
4 / ∗ D a l i j e z a d n j a z n a m e n k a p r o s t b r o j ∗ /
5 pr i nt f ( ”Zadnja znamenka ” ) ;
6 switch ( pot % 10) {
7 case 2:
8 case 3:
9 case 5:
10 case 7: pr i nt f ( ” j e ” ) ;
11 break ;
12 default : pr i nt f ( ” ni j e ” ) ;
13 }
14 pr i nt f ( ” pr os t br oj . \ n” ) ;
ili, kra´ce:
1 / ∗ R a c u n a n j e n − t e p o t e n c i j e b r o \ − j a 3 ∗ /
2 pot = 1;
3 while ( n−−) pot ∗= 3;
4 / ∗ D a l i j e z a d n j a z n a m e n k a p r o s t b r o j ∗ /
5 pr i nt f ( ”Zadnja znamenka ” ) ;
106 9. Vi
ˇ
sestruko grananje
6 switch ( pot % 10) {
7 case 1: case 4: case 6: case 8:
8 case 9: pr i nt f ( ” ni ” ) ;
9 }
10 pr i nt f ( ” j e pr os t br oj . \ n” ) ;
Kao ˇsto vidimo, “prazne grane” moˇzemo pobrojati u jedan red.
Napomena 9.1.2. U prethodnom programskom isjeˇcku, raˇcunanje zadnje znamenke n-te
potencije broja 3 mogli smo napisati i toˇcnije:
1 pot = 1;
2 while ( n−−) pot = (3 ∗ pot ) % 10;
Zaˇsto je ovo “toˇcnije”, objaˇsnjeno je na predavanjima (overflow).
Zadatak 9.1.4. Napiˇsite sljede´ci dio koda bez upotrebe switch() (tj. samo upotrebom
if()).
1 switch ( a ) {
2 case 1: pr i nt f ( ”A” ) ;
3 case 2: pr i nt f ( ”B” ) ;
4 break ;
5 case 3: i f ( x % 2)
6 pr i nt f ( ”1” ) ;
7 el se
8 pr i nt f ( ”?” ) ;
9 case 4: break ;
10 case 5: pr i nt f ( ”C” ) ;
11 default : pr i nt f ( ”D” ) ;
12 }
Poglavlje 10
Funkcije
ˇ
Cesto neki dio kˆoda treba izvrˇsiti viˇse puta, a jedina razlika u tim izvrˇsavanjima su
vrijednosti na kojima se taj kˆod izvrˇsava. Kako ne bismo dva puta pisali isto, eventualno
uz mijenjanje naziva varijabli (ˇsto lako moˇze dovesti do greˇsaka), koristimo funkcije –
dijelove koda izdvojene u zasebne cjeline.
Funkcije mogu pozivati jedne druge, pa ˇcak i same sebe. Ove druge zovu se rekurzivne
funkcije i njih ´cemo obraditi u drugom semestru.
10.1 Jednostavne funkcije
Zadatak 10.1.1 (Euklidov algoritam). Napiˇsite program koji uˇcitava dva cijela broja
x, y ∈ Z. Program treba ispisati GCD(x, y) (najve´ci zajedniˇcki djelitelj brojeva x i y).
Rjeˇsenje. Zadatak rjeˇsavamo Euklidovim algoritmom. On se svodi na dijeljenje ve´ceg bro-
ja s manjim dok ostatak pri dijeljenju ne postane jednak nuli. Tada je rezultat dijeljenja
upravo najve´ca zajedniˇcka mjera poˇcetnih brojeva (dokaˇzite!).
1 #include <s t di o . h>
2
3 i nt main( void) {
4 i nt x , y ;
5
6 pr i nt f ( ” Uc i t aj t e x : ” ) ; s c anf ( ”%d” , &x ) ;
7 pr i nt f ( ” Uc i t aj t e y : ” ) ; s c anf ( ”%d” , &y ) ;
8
9 pr i nt f ( ”GCD(%d , %d) = ” , x , y ) ;
10
11 i f ( x < 0) x = −x ;
12 i f ( y < 0) y = −y ;
13 i f ( x < y) { i nt t = x ; x = y ; y = t ; }
14
107
108 10. Funkcije
15 while ( y) {
16 i nt t = x % y ;
17 x = y ;
18 y = t ;
19 }
20
21 pr i nt f ( ”%d\n” , x ) ;
22
23 return 0;
24 }
Zadatak 10.1.2. Bez upotrebe nizova napiˇsite program koji uˇcitava razliˇcite cijele brojeve
a, b, c ∈ Z. Program treba ispisati brojeve x, y i GCD(x, y), pri ˇcemu je
x = min
p,q∈{a,b,c}
GCD(p, q) i y = max
p,q∈{a,b,c}
GCD(p, q).
Pokuˇsajte zadatak rijeˇsiti bez upotrebe funkcija (potprograma), repliciraju´ci rjeˇsenje
prethodnog zadatka.
Rjeˇsenje. Idealno, rjeˇsenje zadatka bi izgledalo ovako (skica):
1 x = y = gcd ( a , b ) ;
2 p = gcd ( a , c ) ;
3 i f ( p < x) x = p ;
4 i f ( p > y) y = p ;
5 p = gcd ( b , c ) ;
6 i f ( p < x) x = p ;
7 i f ( p > y) y = p ;
8 pr i nt f ( ”x = %d , y = %d , gcd(%d , %d) = %d\n” ,
9 x , y , x , y , gcd ( x , y ) ) ;
No, u C-u ne postoji funkcija gcd(), ˇsto znaˇci da ili moramo viˇsestruko prepisati rje-
ˇsenje prethodnog zadatka (uz prikladnu promjenu vrijednosti varijabli) ili moramo sami
definirati funkciju gcd(). Mi ´cemo, naravno, sloˇziti svoju funkciju:
1 #include <s t di o . h>
2
3 i nt gcd ( i nt x , i nt y) {
4 i f ( x < 0) x = −x ;
5 i f ( y < 0) y = −y ;
6 i f ( x < y) { i nt t = x ; x = y ; y = t ; }
7
8 while ( y) {
9 i nt t = x % y ;
10 x = y ;
10.1. Jednostavne funkcije 109
11 y = t ;
12 }
13
14 return x ;
15 }
16
17 i nt main( void) {
18 i nt a , b , c , p , x , y ;
19
20 pr i nt f ( ” Uc i t aj t e a : ” ) ; s c anf ( ”%d” , &a ) ;
21 pr i nt f ( ” Uc i t aj t e b : ” ) ; s c anf ( ”%d” , &b ) ;
22 pr i nt f ( ” Uc i t aj t e c : ” ) ; s c anf ( ”%d” , &c ) ;
23
24 x = y = gcd ( a , b ) ;
25 p = gcd ( a , c ) ;
26 i f ( p < x) x = p ;
27 i f ( p > y) y = p ;
28 p = gcd ( b , c ) ;
29 i f ( p < x) x = p ;
30 i f ( p > y) y = p ;
31 pr i nt f ( ”x = %d , y = %d , gcd(%d , %d) = %d\n” ,
32 x , y , x , y , gcd ( x , y ) ) ;
33
34 return 0;
35 }
Funkcija se sastoji od sljede´cih dijelova:
• zaglavlje (linija 3), u kojem su redom navedeni tip vrijednosti koju funkcija vra´ca
(piˇsemo kljuˇcnu rijeˇc “void” ako funkcija ne vra´ca vrijednost), naziv funkcije, te
popis formalnih argumenata (i njihovih tipova) koje funkcija prima. Ako funkcija
ne prima nikakve vrijednosti, navode se prazne zagrade (dakle “ime_funkcije()”).
• tijelo (linije 4–14), u kojima (kao i inaˇce u programu) opisujemo ˇsto funkcija radi.
• povrat vrijednosti (linija 14), kojim prekidamo izvrˇsavanje funkcije i zadajemo
koju vrijednost ona vra´ca. Ovaj dio nije obavezan ako funkcija ne vra´ca vrijednost.
ˇ
Zelimo li negdje prekinuti izvrˇsavanje funkcije koja ne vra´ca vrijednost, pozivamo
samo return;.
Varijable x i y u funkciji gcd() su lokalne i nemaju veze s istoimenim varijablama u
glavnom programu! U njih se spremaju kopije vrijednosti varijabli s kojima je funk-
cija pozvana (npr. kod poziva gcd(a,c), varijabla x poprima vrijednost a, a varijabla y
poprima vrijednost c). Promjene tih lokalnih varijabli ne utjeˇcu na vrijednosti varijabli s
kojima je funkcija pozvana (tj. promjena vrijednosti varijabli x i y ne´ce dovesti do izmjene
vrijednosti varijabli a i c).
110 10. Funkcije
Kao ˇsto smo vidjeli u rjeˇsenju prethodnog zadatka, potprogramima smanjujemo ko-
liˇcinu pisanja i pove´cavamo preglednost programa, ˇsto direktno utjeˇce i na smanjivanje
broja greˇsaka. Rjeˇsenje prethodnog zadatka moglo se dodatno raˇsˇclaniti na funkcije, te
(uz dodatni zahvat na ispisu
1
) skratit na sljede´ci oblik:
1 #include <s t di o . h>
2
3 i nt gcd ( i nt x , i nt y) {
4 i f ( x < 0) x = −x ;
5 i f ( y < 0) y = −y ;
6 i f ( x < y) { i nt t = x ; x = y ; y = t ; }
7
8 while ( y) {
9 i nt t = x % y ;
10 x = y ;
11 y = t ;
12 }
13
14 return x ;
15 }
16
17 i nt min( x , y) {
18 return ( x < y ? x : y ) ;
19 }
20
21 i nt max( x , y) {
22 return ( x > y ? x : y ) ;
23 }
24
25 i nt main( void) {
26 i nt a , b , c , p , x , y ;
27
28 pr i nt f ( ” Uc i t aj t e a : ” ) ; s c anf ( ”%d” , &a ) ;
29 pr i nt f ( ” Uc i t aj t e b : ” ) ; s c anf ( ”%d” , &b ) ;
30 pr i nt f ( ” Uc i t aj t e c : ” ) ; s c anf ( ”%d” , &c ) ;
31
32 x = y = gcd ( a , b ) ;
33 p = gcd ( a , c ) ; x = min( x , p ) ; y = max( y , p ) ;
34 p = gcd ( b , c ) ; x = min( x , p ) ; y = max( y , p ) ;
35 pr i nt f ( ”x = %d , y = %d , gcd(%1$d , %2$d) = %d\n” ,
36 x , y , gcd ( x , y ) ) ;
37
1
Za one koji ˇzele znati viˇse: format %m$f, pri ˇcemu je m broj, a f neki od uobiˇcajenih formata (d, e, 3x
i sl.), odgovara formatu %f, ali kao vrijednost uzima m-ti parametar. Zbog toga prikazani poziv funkcije
printf() ispisuje vrijednosti varijabli x i y na dva mjesta (na mjesta prva dva %d i na mjesta gdje je
zadano %1$d i %2$d).
10.1. Jednostavne funkcije 111
38 return 0;
39 }
Da je rijeˇc o zaista kra´cem rjeˇsenju, moˇzete se uvjeriti tako da pokuˇsate rijeˇsiti modifika-
ciju zadatka koja radi s 5 varijabli (umjesto njih 3).
Pogledajte strukturu glavnog programa. U C-u, on je samo jedna od funkcija koja se
od ostalih razlikuje iskljuˇcivo po specijalnom nazivu (main())!
Zadatak 10.1.3. Napiˇsite funkciju koja kao argument uzima jedan prirodni broj n ∈ N,
a kao povratnu vrijednost vra´ca n! := 1 · 2 · · · · · n.
Rjeˇsenje. Funkcija prima argumente i vra´ca vrijednost. Zbog toga ona ne mora niˇsta niti
uˇcitavati niti ispisivati, ali ju ipak moˇzemo smatrati algoritmom!
1 long i nt f akt ( i nt n) {
2 i nt i ;
3 long i nt r e s = 1;
4
5 for ( i = 2; i <= n ; i ++) r e s ∗= i ;
6
7 return r e s ;
8 }
Funkciju smo mogli i kra´ce napisati, koriste´ci ˇcinjenicu da je varijabla n lokalna, tj. da nje-
nom promjenom ne´cemo izazvati promjenu varijable koja je pri pozivu funkcije navedena
kao argument:
1 long i nt f akt ( i nt n) {
2 long i nt r e s = 1;
3
4 while ( n > 1) r e s ∗= ( n−−);
5
6 return r e s ;
7 }
Napomena 10.1.1 (
ˇ
Ceste greˇske).
1. Ako funkcija prima neku vrijednost, onda tu vrijednost ne smijete u funkciji uˇcitavati,
jer uˇcitavanjem gubite zadanu vrijednost argumenta. Dakle, ovo je KRIVO:
1 long i nt f akt ( i nt n) {
2 long i nt r e s = 1;
3
4 s c anf ( ”%d” , &n ) ;
5
6 while ( n > 1) r e s ∗= ( n−−);
112 10. Funkcije
7
8 return r e s ;
9 }
2. Iza return nema smisla niˇsta pisati jer se to ne´ce izvrˇsiti (return prekida iz-
vrˇsavanje funkcije). Zbog toga, u sljede´cem kodu nikad ne´ce do´ci do ispisa:
1 i nt f ( i nt x) {
2 return 2 ∗ x ;
3 pr i nt f ( ”%d\n” , x ) ;
4 }
Naravno, moˇzete pomo´cu return prekinuti izvrˇsavanje funkcije samo u nekim slu-
ˇcajevima. Na primjer, idu´ca funkcija vra´ca najmanji parni broj ve´ci ili jednak x:
1 i nt f ( i nt x) {
2 i f ( x % 2 == 0) return x ;
3 x++;
4 return x ;
5 }
Istu stvar rade i sljede´ce dvije funkcije:
1 i nt g ( i nt x) {
2 i f ( x % 2 == 0) return x ;
3 return x + 1;
4 }
5 i nt h( i nt x) {
6 return ( x % 2 ? x + 1 : x ) ;
7 }
Dakle, naredbe iza return ima smisla zadavati samo ako je do njih mogu´ce do´ci bez
izvrˇsavanja samog return-a (npr. u razliˇcitim granama if()-a).
Zadatak 10.1.4. Napiˇsite funkciju koja kao argument uzima jedan prirodni broj n ∈ N,
a kao povratnu vrijednost vra´ca
(2n)!! := 2 · 4 · 6 · · · · · (2n) = 2
n
n!.
Zadatak 10.1.5. Napiˇsite funkciju koja kao argument uzima jedan prirodni broj n ∈ N,
a kao povratnu vrijednost vra´ca
(2n + 1)!! := 1 · 3 · 5 · · · · · (2n + 1).
Zadatak 10.1.6. Napiˇsite funkciju koja kao argument uzima jedan prirodni broj n ∈ N,
a kao povratnu vrijednost vra´ca
n!! := n · (n −2) · (n −4) · · · · =
¸
0≤i<
n
2
(n −2i).
10.1. Jednostavne funkcije 113
Zadatak 10.1.7. Napiˇsite funkciju koja prima jedan cjelobrojni parametar x ∈ Z, te
vra´ca njegovu apsolutnu vrijednost.
Zadatak 10.1.8. Napiˇsite funkciju koja prima jedan cjelobrojni parametar x ∈ Z, te
vra´ca 1 ako je |x| prost, odnosno 0 ako |x| nije prost.
Rjeˇsenje.
1 i nt abs i s pr i me ( i nt x) {
2 i nt i = 2;
3 i f ( x < 0) x = −x ;
4 i f ( x <= 1) return 0;
5 while ( i < x)
6 i f ( ! ( x % i ++)) return 0;
7 return 1;
8 }
U liniji 6, ako je x djeljiv s i, prekidamo izvrˇsavanje funkcije i ona vra´ca 0. U protivnom,
while() petlja nastavlja s izvrˇsavanjem. Vrijednost varijable i pove´cava se za jedan,
ali se djeljivost provjerava sa starom vrijednoˇs´cu od i (jer i pove´cavamo post-inkrement
operatorom). Dakle, u prvom koraku i poprimi vrijednost 3, ali se provjerava djeljivost
x-a s 2, u drugom koraku i postaje 4, ali se djeljivost x-a s 3 itd.
Za uˇcitani broj x, funkciju moˇzemo pozvati na sljede´ci naˇcin:
1 pr i nt f ( ”Broj |%d | %s j e pr os t . \ n” ,
2 x , abs i s pr i me ( x) ? ”” : ” ni ” ) ;
Zadatak 10.1.9. Napiˇsite funkciju koja prima jedan prirodni parametar n ∈ N, te ispisuje
sve njegove proste faktore i to svakog onoliko puta kolika mu je kratnost, tj. za
n =
¸
i
p
n
i
i
, p
i
prost, n
i
∈ N
treba svaki p
i
ispisati n
i
puta. Redoslijed ispisa nije bitan.
Rjeˇsenje. Funkcija ne vra´ca nikakvu vrijednost, pa je njen tip void. Osnovni algoritam
je ve´c prikazan u zadatku 8.5.3, pa ´cemo ovdje samo podsjetiti kako on radi.
Tvrdnja: Neka je p
i
najmanji broj (strogo ve´ci od 1) takav da je n djeljiv s p
i
, tada
je p
i
prost (dokaˇzite!).
Koriˇstenjem te tvrdnje moˇzemo sloˇziti izuzetno brz algoritam za rastav broja na proste
faktore. Najprije inicijaliziramo pomo´cnu varijablu p na najmanju vrijednost strogo ve´cu
od 1 (tj. na vrijednost 2). Zatim provjeravamo djeljivost n s p. Dok god je n djeljiv s p,
ispisujemo p, te n dijelimo s p. Ako n (viˇse) nije djeljiv s p, pove´cavamo p za jedan, kako
bismo u idu´cem koraku petlje probali za idu´ci broj. Petlju vrtimo dok god n ima prostih
faktora, tj. dok god je strogo ve´ci od 1.
114 10. Funkcije
1 void pr i nt pr i me s ( i nt n) {
2 i nt p = 2;
3 while ( n > 1) {
4 while ( ! ( n % p) ) {
5 pr i nt f ( ”%d\n” , p ) ;
6 n /= p ;
7 }
8 p++;
9 }
10 }
Zadatak 10.1.10. Napiˇsite funkciju koja prima jedan prirodni parametar n ∈ N, te
ispisuje sve njegove proste faktore, svakog toˇcno jednom.
Zadatak 10.1.11. Napiˇsite funkciju koja prima jedan prirodni parametar n ∈ N, te
ispisuje sve njegove proste faktore i uz svakog njegovu kratnost. Funkcija treba vratiti broj
razliˇcitih prostih faktora koje sadrˇzi broj n.
10.2 Varijabilni argumenti funkcija
Kod funkcija u C-u, parametri se prenose “po vrijednosti”. To znaˇci da funkcija ima
lokalnu varijablu u kojoj se nalazi kopija vrijednosti s kojom se funkcija poziva. Zbog
toga se promjene argumenata u funkciji ne odraˇzavaju na vrijednosti varijabli s kojima je
funkcija pozvana.
Primjer 10.2.1.
1 #include <s t di o . h>
2
3 void f ( i nt a ) {
4 pr i nt f ( ” Funkci j a 1: a = %d\n” , a ) ;
5 a++;
6 pr i nt f ( ” Funkci j a 2: a = %d\n” , a ) ;
7 }
8
9 i nt main( void) {
10 i nt x = 1;
11
12 pr i nt f ( ”Gl . prog . 1: x = %d\n” , x ) ;
13 f ( x ) ;
14 pr i nt f ( ”Gl . prog . 2: x = %d\n” , x ) ;
15
16 return 0;
17 }
10.2. Varijabilni argumenti funkcija 115
No, ˇsto se dogada ako u funkciju proslijedimo adresu varijable i onda pristupamo
direktno toj adresi?
Primjer 10.2.2.
1 #include <s t di o . h>
2
3 void f ( i nt ∗a ) {
4 pr i nt f ( ” Funkci j a 1: ∗a = %d\n” , ∗a ) ;
5 (∗ a)++;
6 pr i nt f ( ” Funkci j a 2: ∗a = %d\n” , ∗a ) ;
7 }
8
9 i nt main( void) {
10 i nt x = 1;
11
12 pr i nt f ( ”Gl . prog . 1: x = %d\n” , x ) ;
13 f (&x ) ;
14 pr i nt f ( ”Gl . prog . 2: x = %d\n” , x ) ;
15
16 return 0;
17 }
Primjer 10.2.1 ispisat ´ce
Gl. prog. 1: x = 1
Funkcija 1: a = 1
Funkcija 2: a = 2
Gl. prog. 1: x = 1
dok ´ce primjer 10.2.2 ispisati
Gl. prog. 1: x = 1
Funkcija 1: *a = 1
Funkcija 2: *a = 2
Gl. prog. 1: x = 2
Iako radimo naizgled istu stvar, promijenili smo varijablu koja je bila pozivni argument
funkcije. Zaˇsto? Pogledajmo ˇsto se dogada u memoriji (slike 10.1 i 10.2).
Obje slike prikazuju dijelove memorije u kojima se nalaze varijable x i a. Lijevo
od memorije su popisane memorijske lokacije (ovdje ad hoc izmiˇsljene; u stvarnosti ih
dodjeljuje raˇcunalo, bez utjecaja korisnika na stvarne vrijednosti). Bitno je da te lokacije
idu po redu, jedna za drugom.
U primjeru 10.2.1, varijabla a je tipa int i prilikom poziva funkcije poprima vrijednost
parametra x. To znaˇci da je vrijabla a kopija varijable x. Evaluiranjem izraza a++ mi
116 10. Funkcije
1234567
1234568
1234569
1234570
2473847
2473848
2473849
.
.
.
.
.
.
.
.
.
.
1
1
1234567
1234568
1234569
1234570
2473847
2473848
2473849
.
.
.
.
.
.
.
.
.
.
1
2
Nakon promjene varijable a u funkciji Odmah nakon poziva funkcije
1
a a
x x
Slika 10.1: Memorija u primjeru 10.2.1
mijenjamo vrijednost te kopije, no varijabla x ostaje nepromijenjena. Naravno, prilikom
izlaska iz funkcije, varijabla a se briˇse i promjena “nestaje”.
S druge strane, u primjeru 10.2.2, varijabla a je tipa int* (pointer na int, odnosno
adresa memorijske lokacije na kojoj se nalazi neka vrijednost tipa int). Sliˇcno prethodnom
primjeru, prilikom poziva funkcije varijabla a poprima vrijednost parametra, no ovaj put
to je &x. Podsjetimo se: operator “&” vra´ca adresu varijable koja se nalazi iza njega, pa
&x vra´ca adresu varijable x. Zbog toga, na slici 10.2 varijabla a ima vrijednost 1234568,
ˇsto je adresa varijable x. Analogno tome, izraz *a oznaˇcava memorijsku lokaciju na adresi
a, pa promjenom vrijednosti *a (izraz (*a)++) efektivno mijenjamo vrijednost varijable
x.
Napomena 10.2.1. Rijeˇc je o jednoj od najvaˇznijih stvari u C-u. Prouˇcite dobro, dok
niste apsolutno sigurni da Vam je potpuno jasno, te na raˇcunalu rijeˇsite sve zadatke iz
ovog poglavlja!
Zadatak 10.2.1.
ˇ
Sto ispisuje sljede´ci program?
1 #include <s t di o . h>
2
3 void f ( i nt ∗a , i nt b) {
4 i nt ∗c ;
5 c = &b ;
6 (∗ a)++; b++; (∗ c)++;
7 }
10.2. Varijabilni argumenti funkcija 117
1234567
1234568
1234569
1234570
2473847
2473848
2473849
.
.
.
.
.
.
.
.
.
.
1
1234567
1234568
1234569
1234570
2473847
2473848
2473849
.
.
.
.
.
.
.
.
.
.
Odmah nakon poziva funkcije
1234568 1234568
2
x (=*a)
Nakon promjene varijable *a u funkciji
1234568
a a
x
Slika 10.2: Memorija u primjeru 10.2.2
8
9 i nt main( void) {
10 i nt a = 1 , b = 10 , c = 100;
11
12 pr i nt f ( ”a = %d , b = %d , c = %d\n” , a , b , c ) ;
13 f (&a , b ) ;
14 pr i nt f ( ”a = %d , b = %d , c = %d\n” , a , b , c ) ;
15
16 return 0;
17 }
Rjeˇsenje. Program ispisuje
a = 1, b = 10, c = 100
a = 2, b = 10, c = 100
Iako imamo izraz (*c)++ koji je sliˇcan izrazu (*a)++, on ne´ce izmijeniti niti varijablu c
iz glavnog programa (jer s njom nema veze), niti varijablu b iz glavnog programa, jer je
c pointer na varijablu b iz funkcije, a ona sama je kopija varijable b iz glavnog programa!
Zbog toga izraz (*c)++ radi isto ˇsto i b++ – mijenja lokalnu kopiju varijable b iz glavnog
programa.
Zadatak 10.2.2. Napiˇsite funkciju koja omogu´cuje zamjenu vrijednosti dva realna broja.
Napomena 10.2.2 (
ˇ
Cesta greˇska). Dio programa koji ne zamjenjuje dvije varijable,
ali se ˇcesto – greˇskom – pojavljuje u kolokvijima i zada´cama:
118 10. Funkcije
1 x = y ;
2 y = x ;
U trenutku kad je raˇcunalo izvrˇsilo naredbu x = y, obje varijable ´ce poprimiti vrijednost
koju je na poˇcetku imala varijabla y, pa ´ce originalna vrijednost varijable x biti izgubljena.
Naredba y = x pridruˇzuje varijabli y novu vrijednost varijable x, ˇsto je vrijednost koju y
ionako ve´c ima od prije.
Postoje jezici (npr. ASM – ne Assembler!) u kojima prikazana konstrukcija zaista
mijenja vrijednosti dvije varijable. No, u “klasiˇcnim” jezicima to ne vrijedi.
Rjeˇsenje (ispravno). Potrebna nam je pomo´cna varijabla istog tipa kao x i y (potrebno
ju je deklarirati na poˇcetku bloka u kojem se nalazi zamjena!):
1 double pomocna = x ;
2 x = y ;
3 y = pomocna ;
Funkciju za zamjenu dva realna broja moˇzemo sloˇziti pomo´cu varijabilnih parametara,
pri ˇcemu funkcija ne treba vra´cati nikakvu vrijednost (tj. njen povratni tip je void):
1 void swap( double ∗x , double ∗y) {
2 double temp ;
3 temp = ∗x ;
4 ∗x = ∗y ;
5 ∗y = temp ;
6 }
Primijetimo da je varijabla temp “obiˇcni” double, tj. nije pointer na double. Kad bi
ona bila pointer na double, znaˇcilo bi da – kao i x i y – pokazuje na neku memorijsku
lokaciju u kojoj se nalazi neˇsto tipa double. No, za razliku od x i y, nemamo ni jednu
´celiju na koju bi temp pokazivala, pa bi kod izvrˇsavanja doˇslo do greˇske. Viˇse o ovome
bit ´ce reˇceno u poglavlju o dinamiˇckim varijablama.
Napomena 10.2.3 (
ˇ
Cesta greˇska). To ˇsto je varijabilni parametar pointer i dalje ne
znaˇci da moˇzemo njega mijenjati tako da promjena afektira parametar s kojim je funkcija
pozvana. Moˇzemo mijenjati iskljuˇcivo ono na ˇsto varijabilni parametar pokazuje! Na
primjer, sljede´ca funkcija ne´ce napraviti niˇsta:
1 void f ( double ∗x , double ∗y) {
2 double ∗temp ;
3 temp = x ;
4 x = y ;
5 y = temp ;
6 }
10.2. Varijabilni argumenti funkcija 119
Preciznije, ona ´ce zamijeniti privremene pointere x i y, ali ne i vrijednosti ´celija na koje
oni pokazuju. Nakon izvrˇsavanja funkcije, pointeri x i y se gube, pa njihova zamjena ne
utjeˇce na odgovaraju´ce varijable iz glavnog programa.
Zadatak 10.2.3. Napiˇsite funkciju koja preko varijabilnog parametra poniˇstava pokazivaˇc
na cijeli broj, tj. postavlja ga na vrijednost NULL.
Rjeˇsenje. Princip je isti kao i do sada, ali sintaksa moˇze djelovati zbunjuju´ce. Ovdje
ˇzelimo mijenjati varijablu koja je tipa int* (pointer na int). To znaˇci da varijablini
parametar mora biti tipa int** (pointer na pointer na int).
1 void n u l l i f y ( i nt ∗∗x) {
2 ∗x = NULL;
3 }
Zadatak 10.2.4. Napiˇsite funkciju shift() koja prima tri cijela broja, te ih cirkularno
“pomiˇce” u desno na naˇcin da tre´cem pridijeli vrijednost drugog, drugom vrijednost prvog
i prvom vrijednost tre´ceg.
Uputa. Ovo je, u osnovi, malo modificirani swap().
Zadatak 10.2.5. Napiˇsite funkciju koja prima tri argumenta: prirodni broj n ∈ N, te
pointere x i y na prirodne brojeve. Funkcija treba na´ci najmanji i najve´ci prosti faktor
broja n, te ih preko parametara x i y vratiti u glavni program. Sama funkcija ne vra´ca
nikakvu vrijednost (tj. ona je tipa void).
Zadatak 10.2.6. Napiˇsite funkciju koja za zadani prirodni broj n ∈ N vra´ca sumu i
produkt svih prirodnih brojeva strogo manjih od n.
Uputa. Funkcija ne moˇze vratiti viˇse od jedne vrijednosti, pa je zadatak potrebno rijeˇsiti
pomo´cu varijablinih parametara.
120 10. Funkcije
Poglavlje 11
Nizovi (polja)
Nizovi (polja ili indeksirane varijable) su varijable koje u sebi sadrˇze viˇse vrijednosti istog
tipa. Deklariramo ih navodenjem tipa vrijednosti i “duljine niza”, tj. broja vrijednosti
koliko najviˇse moˇzemo pospremiti u niz.
11.1 Uvod
Primjer 11.1.1. Nizove x od (najviˇse) 17 cijelih brojeva i y od (najviˇse) 19 realnih brojeva
deklariramo na sljede´ci naˇcin:
1 i nt x [ 1 7 ] ;
2 double y [ 1 9 ] ;
Napomena 11.1.1. U deklaraciji niza, npr. int x[n], duljina (u ovom primjeru n)
mora biti zadana konstanta, a nikako ne varijabla ili izraz ˇcija vrijednost nije jednoznaˇcno
odredena u trenutku compiliranja!
Pojedinim vrijednostima pristupamo navodenjem imena varijable i indeksa.
Napomena 11.1.2. Indeksi “kre´cu” od nule i moraju biti strogo manji od broja elemenata
niza!
Na primjer, za niz int x[5] indeksi kojima smijemo pristupati su 0, 1, 2, 3 i 4, ali ne
i 5 (ili bilo koji broj ve´ci od 5). Takoder, ne smijemo pristupati niti negativnim indeksima.
Primjer 11.1.2. Sljede´ci dio programa postavlja tre´ci element varijable x na vrijednost
13, ispisuje prvi element varijable y, te uˇcitava sedmi element varijable x:
1 x [ 2 ] = 13;
2 pr i nt f ( ”%g” , y [ 0 ] ) ;
3 s c anf ( ”%d” , &x [ 6 ] ) ;
121
122 11. Nizovi (polja)
Nizove moˇzemo deklarirati i tako da ih odmah inicijaliziramo (navedemo poˇcetne vri-
jednosti njihovih elemenata).
Primjer 11.1.3.
1 i nt a [ 1 7 ] = {1 , 3 , 7};
2 i nt b [ ] = {1 , 3 , 7};
Varijable a i b razlikuju se u duljini: a je niz sa 17 elemnata od koji prva tri imaju
vrijednosti 1, 3 i 7 (respektivno), dok su ostale vrijednosti nula; b je niz od tri elementa
(ponovno s vrijednostima 1, 3 i 7 respektivno). Ovaj primjer identiˇcan je (do na dodanu
varijablu i) sljede´cem kodu:
1 i nt a [ 1 7 ] , b [ 3 ] , i ;
2 a [ 0 ] = 1; a [ 1 ] = 3; a [ 2 ] = 7;
3 for ( i = 3; i < 17; i ++) a [ i ] = 0;
4 b [ 0 ] = 1; b [ 1 ] = 3; b [ 2 ] = 7;
Napomena 11.1.3. Ako nizu nije zadana poˇcetna vrijednost, njegovi elementi ne´ce
imati vrijednost nula, nego ´ce ta vrijednost biti sluˇcajna (kao i kod “obiˇcnih” varijabli kad
ih neinicijaliziramo)!
Primjer 11.1.4.
1 i nt x [ 1 7 ] ;
2 i nt y [ 1 7 ] = {0};
Nakon izvrˇsavanja ovog dijela programa, varijabla x ´ce biti niz od 17 cijelih brojeva nepoz-
nate vrijednosti, dok ´ce varijabla y biti niz od 17 cijelih brojeva koji svi imaju vrijednost
nula.
Napomena 11.1.4. Op´cenito, nizove ne moˇzemo odjednom ispisati ili uˇcitati:
1 i nt x [ 1 7 ] ;
2 s c anf ( ” . . . ” , &x ) ;
3 pr i nt f ( ” . . . ” , x ) ;
nego moramo raditi sa svakim pojedinim ˇclanom niza (npr. pomo´cu for()-petlje). Iznimka
su nizovi znakova (tzv. stringovi) koje ´cemo naknadno obraditi.
Zadatak 11.1.1. Napiˇsite program koji uˇcitava prirodni broj n ≤ 20, te n prirodnih
brojeva. Nakon uˇcitavanja, brojeve treba ispisati u obrnutom redoslijedu.
Rjeˇsenje. Ovdje ´cemo upotrijebiti unsigned int, kako bismo pokazali da kod unsigned
tipova treba dodatno pripaziti.
1 #include <s t di o . h>
2
3 i nt main( void) {
4 unsigned i nt n , x [ 2 0 ] ;
11.1. Uvod 123
5 i nt i ;
6 pr i nt f ( ” Unesi t e n : ” ) ;
7 s c anf ( ”%u” , &n ) ;
8 i f ( n > 0) {
9 for ( i = 0; i < n ; i ++) {
10 pr i nt f ( ” Unesi t e x[%d ] : ” , i ) ;
11 s c anf ( ”%u” , &x [ i ] ) ;
12 }
13 pr i nt f ( ” I s p i s br oj eva u obrnutom r e do s l i j e du : \ n” ) ;
14 for ( i = n − 1; i >= 0; i −−)
15 pr i nt f ( ”%u\n” , x [ i ] ) ;
16 } el se {
17 pr i nt f ( ” Odabral i s t e unos nul a broj eva , ” ) ;
18 pr i nt f ( ”pa j a nemam s t o r a d i t i . . . \ n” ) ;
19 }
20 return 0;
21 }
Napomena 11.1.5. Da je tip varijable i u prethodnom programu bio unsigned int,
uvjet for()-petlje bio bi uvijek istinit. Mogu´ce je i definirati varijablu i tako da bude
tipa unsigned int, no onda moramo izmijeniti for()-petlju (naravno, na naˇcin da daje
jednaki ispis). Na primjer:
14 for ( i = 1; i <= n ; i ++)
15 pr i nt f ( ”%u\n” , x [ n − i ] ) ;
ili
14 for ( i = n ; i > 0; i −−)
15 pr i nt f ( ”%u\n” , x [ i − 1 ] ) ;
Ispis iz prethodnog zadatka, izveden u jednoj liniji uz zareze izmedu brojeva, moˇzemo
napraviti ovako:
1 pr i nt f ( ” I s p i s br oj eva u obrnutom r e do s l i j e du : %u” ,
2 x [ n−1] ) ;
3 for ( i = n − 2; i >= 0; i −−) pr i nt f ( ” , %u” , x [ i ] ) ;
4 pr i nt f ( ”\n” ) ;
ili, pomo´cu while()-petlje (i bez pomo´cne varijable i):
1 pr i nt f ( ” I s p i s br oj eva u obrnutom r e do s l i j e du : %u” ,
2 x[−−n ] ) ;
3 while ( n) pr i nt f ( ” , %u” , x[−−n ] ) ;
4 pr i nt f ( ”\n” ) ;
124 11. Nizovi (polja)
Zadatak 11.1.2. Napiˇsite dio programa koji za zadani prirodni broj n ispisuje njegove
znamenke “ispravnim” redoslijedom (od lijeve prema desnoj).
Rjeˇsenje koje smo prije vidjeli:
1 while ( n > 0) {
2 pr i nt f ( ”%d\n” , n % 10) ;
3 n /= 10;
4 }
ispisuje znamenke u “pogreˇsnom” redoslijedu (od desne prema lijevoj). Da bismo dobili
“ispravni” redoslijed, znamenke broja smjeˇstamo u niz, te ga ispisujemo unatrag. No,
prilikom deklaracije niza potrebno je utvrditi koliko niz mora biti dugaˇcak?
Mogu´ce je precizno izraˇcunati najve´ci mogu´ci broj znamenaka (neovisno o raˇcunalu na
kojem se program compilira), no to zahtijeva dodatna znanja, pa ´cemo samo pretpostaviti
da broj n ima manje od 100 znamenaka.
Rjeˇsenje.
1 i nt znam[ 1 0 0 ] , i = 0;
2 while ( n > 0) {
3 znam[ i ++] = n % 10;
4 n /= 10;
5 }
6 while ( i ) pr i nt f ( ”%d\n” , znam[−−i ] ) ;
Zadatak 11.1.3. Napiˇsite dio programa koji uˇcitava cijele brojeve dok ne uˇcita nulu
ili 17 brojeva. Potrebno je ispisati indeks i vrijednost broja koji ima najve´cu apsolutnu
vrijednost (bez koriˇstenja funkcija iz stdlib.h, tj. bez koriˇstenja funkcije abs() i sliˇcnih).
Rjeˇsenje.
1 i nt x [ 1 7 ] , n , i , max = 0 , maxi = 0;
2
3 for ( n = 0; n < 17; n++) {
4 s c anf ( ”%d” , &x [ n ] ) ;
5 i f ( ! x [ n ] ) break ;
6 }
7 for ( i = 0; i < n ; i ++) {
8 i nt abs = ( x [ i ] < 0 ? −x [ i ] : x [ i ] ) ;
9 i f ( abs > max) {
10 max = abs ;
11 maxi = i ;
12 }
13 }
14 pr i nt f ( ”Index : %d ; Vr i j ednos t : %d\n” , maxi , x [ maxi ] ) ;
11.1. Uvod 125
Zadatak 11.1.4. Napiˇsite program koji uˇcitava prirodne brojeve dok ne uˇcita nulu. Za
svaku znamenku od 0 do 9 program treba ispisati koliko se puta pojavila (u svim uˇcitanim
brojevima zajedno, ne raˇcunaju´ci nulu kojom se prekida uˇcitavanje).
Rjeˇsenje.
1 #include <s t di o . h>
2
3 i nt main( void) {
4 i nt zn [ 1 0 ] = {0} , i = 0;
5 i nt x ;
6
7 while ( 1) {
8 pr i nt f ( ” Uc i t aj t e br oj #%d : ” , ++i ) ;
9 s c anf ( ”%d” , &x ) ;
10 i f ( ! x) break ;
11 while ( x) {
12 zn [ x % 10]++;
13 x /= 10;
14 }
15 }
16
17 for ( i = 0; i < 10; i ++)
18 pr i nt f ( ”%d : %d\n” , i , zn [ i ] ) ;
19
20 return 0;
21 }
Zadatak 11.1.5. Rijeˇsite prethodni zadatak bez upotrebe nizova!
Zadatak 11.1.6. Napiˇsite dio programa koji uˇcitava n realnih brojeva (n < 19 je zadan).
Potrebno je ispisati indeks i vrijednost broja koji je najudaljeniji (ima najve´cu apsolutnu
razliku) od svog sljedbenika. Ako takvih ima viˇse, ispiˇsite samo prvog.
Rjeˇsenje.
1 double x [ 1 8 ] , max = 0;
2 i nt i , maxi = 0;
3
4 for ( i = 0; i < n ; i ++)
5 s c anf ( ”%l g ” , &x [ i ] ) ;
6 for ( i = 0; i < n − 1; i ++) {
7 double r a z l i k a = x [ i ] − x [ i +1] ;
8 i f ( r a z l i k a < 0) r a z l i k a = −r a z l i k a ;
126 11. Nizovi (polja)
9 i f ( r a z l i k a > max) {
10 max = r a z l i k a ;
11 maxi = i ;
12 }
13 }
14 pr i nt f ( ”Index : %d ; Vr i j ednos t : %g\n” , maxi , x [ maxi ] ) ;
Zadatak 11.1.7. Promijenite prethodno rjeˇsenje tako da ako traˇzenih brojeva ima viˇse,
program ispiˇse zadnjeg.
Uputa. Prethodnom rjeˇsenju je dovoljno dodati toˇcno jedan znak. Naravno, smijete to
rijeˇsiti i “kompliciranije”.
11.2 Nizovi kao funkcijski argumenti
Napomena 11.2.1 (Ekvivalencija polja i pointera). U C-u je niz (polje) ekvivalentan
pointeru na nulti element tog polja, tj. vrijedi:
p ⇔ &p[0]
ˇ
Stoviˇse, vrijedi i op´cenitije:
p + i ⇔ &p[i]
tj.
*(p + i) ⇔ p[i]
Viˇse rijeˇci o ovome bit ´ce u poglavlju o dinamiˇckim nizovima. Ono ˇsto nama za sada
treba je ˇcinjenica da se niz proslijeden kao argument funkcije ponaˇsa jednako kao pointer.
To znaˇci da ako smo funkciji proslijedili niz niz i izvrˇsimo pridruˇzivanje
p[0] = 17;
to je jednako kao da smo napisali
*p = 17;
ˇsto znaˇci da ne mijenjamo varijablu p nego ono na ˇsto ona pokazuje. Zbog toga, promjena
´ce se odraziti i na “originalni” niz u glavnom programu.
Dapaˇce, kad “poˇsaljemo” niz u funkciju, zapravo se u memoriji kopira samo adresa nul-
tog elementa niza, dok sam niz ostaje nepromijenjen u memoriji. Zato su svi elementi
takvog niza varijabilni argumenti funkcije!
11.2. Nizovi kao funkcijski argumenti 127
Niz, kao argument funkcije, navodimo jednako kao i u deklaraciji varijable u koju
pohranjujemo niz, osim ˇsto moˇzemo izostaviti duljinu niza (upravo zato jer ta deklaracija
ne alocira cijeli niz, nego samo jedan pointer).
Zadatak 11.2.1. Napiˇsite funkciju koja prima niz realnih brojeva, te vra´ca sumu njegovih
elemenata.
Rjeˇsenje. Niz je odreden elementima i duljinom. Kad se u zadatku kaˇze da funkcija
prima niz nekakvih podataka, onda se obiˇcno podrazumijeva da zadajemo dva argumenta:
sam niz i prirodni broj koji predstavlja njegovu duljinu! Duljinu ne prosljedujemo kao
argument ako ona nije potrebna (sljede´ci zadatak).
1 double sum( double ni z [ ] , i nt n) {
2 double s = 0;
3 i nt i ;
4 for ( i = 0; i < n ; i ++) s += ni z [ i ] ;
5 return s ;
6 }
Varijabla n je obiˇcni argument (nije niti niz niti pointer), pa ju smijemo mijenjati bez
posljedica po odgovaraju´cu varijablu s kojom je funkcija pozvana. Zbog toga (i zbog
komutativnosti zbrajanja) funkciju moˇzemo i ovako napisati:
1 double sum( double ni z [ ] , i nt n) {
2 double s = 0;
3 while ( n−− > 0) s+= ni z [ n ] ;
4 return s ;
5 }
Zadatak 11.2.2. Napiˇsite funkciju koja prima niz cijelih brojeva i cjelobrojne argumente
i i x. Funkcija treba postaviti vrijednost i-tog elementa niza na x. Napiˇsite i program za
testiranje funkcije.
Rjeˇsenje. Ovdje je potrebno neˇsto napraviti na nekom elementu niza, ˇsto ne ovisi o duljini
niza (ne piˇse da treba provjeriti ispravnost parametra i, tj. da je on nenegativan i strogo
manji od duljine niza). Zbog toga nam ovdje ne treba duljina niza kao argument funkcije.
Oˇcito, funkcija ne mora vratiti nikakvu vrijednost.
Da bismo testirali funkciju, potrebno je dva puta ispisati niz (prije i nakon poziva
funkcije). Zato ´cemo ispis niza smjestiti u zasebnu funkciju (print_niz()). Takoder,
kad samo testiramo funkciju, ne moramo uˇcitavati brojeve; moˇzemo ih zadati kao dio
programa.
1 #include <s t di o . h>
2
3 void s e t ( i nt ni z [ ] , i nt i , i nt x) {
128 11. Nizovi (polja)
4 ni z [ i ] = x ;
5 }
6
7 void pr i nt ni z ( i nt ni z [ ] , i nt n) {
8 i nt i ;
9
10 pr i nt f ( ” El ementi ni za : %d” , ni z [ 0 ] ) ;
11 for ( i = 1; i < n ; i ++) pr i nt f ( ” , %d” , ni z [ i ] ) ;
12 pr i nt f ( ”\n” ) ;
13 }
14
15 i nt main( void) {
16 i nt n = 5 , x [ ] = {17 , 19 , 23 , 29 , 31};
17
18 pr i nt ni z ( x , n ) ;
19 s e t ( x , 3 , 17) ;
20 pr i nt ni z ( x , n ) ;
21
22 return 0;
23 }
Na slici 11.1 moˇzete vidjeti skicu memorije prilikom poziva funkcije set(), uz zanema-
rivanje veliˇcina memorijskih lokacija (u stvarnosti, ´celije su razliˇcitih veliˇcina; mi ovdje,
zbog jednostavnosti, uzimamo veliˇcinu 1).
Zadatak 11.2.3. Napiˇsite funkcije za traˇzenje minimuma i maksimuma niza realnih bro-
jeva.
Rjeˇsenje. “Klasiˇcno” rjeˇsenje:
1 double min( double ni z [ ] , i nt n) {
2 i nt i ;
3 double r e s = ni z [ 0 ] ;
4 for ( i = 1; i < n ; i ++)
5 i f ( ni z [ i ] < r e s ) r e s = ni z [ i ] ;
6 return r e s ;
7 }
8
9 double max( double ni z [ ] , i nt n) {
10 i nt i ;
11 double r e s = ni z [ 0 ] ;
12 for ( i = 1; i < n ; i ++)
13 i f ( ni z [ i ] > r e s ) r e s = ni z [ i ] ;
14 return r e s ;
15 }
Rjeˇsenje se moˇze napisati i malo kompaktnije:
11.2. Nizovi kao funkcijski argumenti 129
.
.
.
.
.
.
.
.
.
.
2473847
1234564
2473849
2473848
1234570
1234569
1234568
1234566
1234565
1234564
1234563
.
.
.
.
.
.
.
.
.
.
1234564
1012345
1012344
1012343
niz
niz[0]
29
23
19
17
31
niz[2]
niz[3]
niz[4]
niz[1]
x
Slika 11.1: Prikaz memorije prilikom poziva funkcije set() u rjeˇsenju zadatka 11.2.2
1 double min( double ni z [ ] , i nt n) {
2 double r e s = ni z[−−n ] ;
3 while ( n−−) i f ( ni z [ n ] < r e s ) r e s = ni z [ n ] ;
4 return r e s ;
5 }
6
7 double max( double ni z [ ] , i nt n) {
8 double r e s = ni z[−−n ] ;
9 while ( n−−) i f ( ni z [ n ] > r e s ) r e s = ni z [ n ] ;
10 return r e s ;
11 }
Oba rjeˇsenja su podjednako dobra (uˇsteda od jedne cjelobrojne varijable je zanemariva).
Primijetite da oba rjeˇsenja pretpostavljaju da je n > 0, tj. da niz nije prazan. Kad
bi niz bio prazan, minimum i maksimum ne bi bili definirani, a zadatak niˇsta ne govori o
tom sluˇcaju.
Zadatak 11.2.4. Napiˇsite funkcije min() i max() tako da primaju joˇs jedan parametar
x tipa double. Funkcije trebaju vra´cati minimum (odnosno maksimum) niza, osim za
130 11. Nizovi (polja)
prazan niz za kojeg trebaju vratiti vrijednost x.
Zadatak 11.2.5. Napiˇsite funkciju koja prima niz realnih brojeva. Funkcija treba vratiti
sumu elemenata niza, te – pomo´cu varijabilnih parametara – najmanji i najve´ci element
niza. Pri tome smijete koristiti funkcije iz zadatka 11.2.3.
Za vjeˇzbu, moˇzete bilo koji od zadataka iz predhodnih poglavlja o programiranju
pretoˇciti u jednu ili ˇcak viˇse funkcija.
11.3 Hornerov algoritam
Zadatak 11.3.1. Napiˇsite dio programa koji za zadani niz realnih brojeva a duljine n+1
(n je takoder zadan) i za zadani realni broj x ispisuje vrijednost polinoma
p(x) =
n
¸
i=0
a
i
x
i
= a
0
+ a
1
x + a
2
x
2
+· · · + a
n
x
n
.
Oˇcito, ali loˇse rjeˇsenje je:
Rjeˇsenje.
1 double p = 0;
2 i nt i , j ;
3 for ( i = 0; i <= n ; i ++) {
4 double pot = 1;
5 for ( j = 0; j < i ; j ++) pot ∗= x ;
6 p += a [ i ] ∗ pot ;
7 }
8 pr i nt f ( ”p(%g ) = %g\n” , x , p ) ;
Ovo rjeˇsenje ima daleko previˇse mnoˇzenja. Npr. x
3
raˇcunamo za svaki indeks i ≥ 3.
Donekle bolje rjeˇsenje je:
Rjeˇsenje.
1 double p = 0 , pot = 1;
2 i nt i , j ;
3 for ( i = 0; i <= n ; i ++) {
4 p += a [ i ] ∗ pot ;
5 pot ∗= x ;
6 }
7 pr i nt f ( ”p(%g ) = %g\n” , x , p ) ;
11.3. Hornerov algoritam 131
Iako ima puno manje mnoˇzenja, ovo rjeˇsenje joˇs uvijek nije dovoljno dobro zbog nu-
meriˇcke nestabilnosti (potencije mogu biti jako velike, pa se javlja overflow ili underflow).
Daleko bolje rjeˇsenje moˇzemo dobiti izluˇcivanjem zajedniˇckih potencija iz dijelova poli-
noma:
p(x) = a
0
+ a
1
x + a
2
x
2
+ a
3
x
3
+ a
4
x
4
+· · · + a
n−1
x
n−1
+ a
n
x
n
= a
0
+ x(a
1
+ a
2
x + a
3
x
2
+ a
4
x
3
+· · · + a
n−1
x
n−2
+ a
n
x
n−1
)
= a
0
+ x(a
1
+ x(a
2
+ a
3
x + a
4
x
2
+· · · + a
n−1
x
n−3
+ a
n
x
n−2
))
= a
0
+ x(a
1
+ x(a
2
+ x(a
3
+ a
4
x +· · · + a
n−1
x
n−4
+ a
n
x
n−3
)))
= a
0
+ x(a
1
+ x(a
2
+ x(a
3
+ x(a
4
+· · · + x(a
n−1
+ xa
n
) . . . ))
Sada, po koracima, moˇzemo raˇcunati:
p
0
= a
n
p
1
= a
n−1
+ xp
0
p
2
= a
n−2
+ xp
1
p
3
= a
n−3
+ xp
2
. . .
p
n−1
= a
1
+ xp
n−2
p
n
= a
0
+ xp
n−1
,
pa je p(x) = p
n
. Opisani postupak zove se Hornerov algoritam.
Hornerov algoritam.
1 p = 0;
2 for ( i = n ; i >= 0; i −−)
3 p = p ∗ x + a [ i ] ;
4 pr i nt f ( ”p(%g ) = %g\n” , x , p ) ;
Zadatak 11.3.2. Napiˇsite dio programa koji uˇcitava realni broj x, te za zadani niz a
duljine 2*n ispisuje vrijednost p
1
(x) · p
2
(x) gdje je
p
1
(x) = a
0
+ a
2
x + a
4
x
2
+· · · + a
2n−2
x
n−1
p
2
(x) = a
1
+ a
3
x + a
5
x
2
+· · · + a
2n−1
x
n−1
Rjeˇsenje. Pomo´cu dvije primjene Hornerovog algoritma raˇcunamo p
1
(x) i p
2
(x), a zatim
dobivene vrijednosti mnoˇzimo.
1 s c anf ( ”%g” , &x ) ;
2 p1 = 0;
132 11. Nizovi (polja)
3 for ( i = 2 ∗ n − 2; i >= 0; i −= 2)
4 p1 = p1 ∗ x + a [ i ] ;
5 p2 = 0;
6 for ( i = 2 ∗ n − 1; i >= 1; i −= 2)
7 p2 = p2 ∗ x + a [ i ] ;
8 pr i nt f ( ”p1(%g ) ∗ p2(%g ) = %g\n” , x , x , p1 ∗ p2 ) ;
Primijetimo da oba polinoma moˇzemo raˇcunati u istoj petlji:
1 s c anf ( ”%g” , &x ) ;
2 p1 = 0;
3 p2 = 0;
4 for ( i = 2 ∗ n − 1; i >= 1; i −= 2) {
5 p1 = p1 ∗ x + a [ i − 1 ] ;
6 p2 = p2 ∗ x + a [ i ] ;
7 }
8 pr i nt f ( ”p1(%g ) ∗ p2(%g ) = %g\n” , x , x , p1 ∗ p2 ) ;
ili
1 s c anf ( ”%l g ” , &x ) ;
2 p1 = 0;
3 p2 = 0;
4 for ( i = n − 1; i >= 0; i −−) {
5 p1 = p1 ∗ x + a [ 2 ∗ i ] ;
6 p2 = p2 ∗ x + a [ 2 ∗ i + 1 ] ;
7 }
8 pr i nt f ( ”p1(%g ) ∗ p2(%g ) = %g\n” , x , x , p1 ∗ p2 ) ;
Napomena 11.3.1. U posljednja dva rjeˇsenja prethodnog zadatka, vrijednost polinoma
raˇcunamo u istoj for()-petlji jer polinomi imaju jednak broj koeficijenata. Da nije tako,
morali bismo svakoga raˇcunati u zasebnoj petlji jer se petlja “vrti” onoliko puta koliko
polinom ima koeficijenata.
Zadatak 11.3.3. Napiˇsite funkciju koja kao parametre prima realni broj x, niz realnih
brojeva a i cijeli broj n, pri ˇcemu je niz a duljine 2*(n+1). Funkcija treba Hornerovim
algoritmom izraˇcunati i vratiti vrijednost p
1
(x) + p
2
(x) gdje je
p
1
(x) = a
0
+ a
1
x + a
2
x
2
+· · · + a
n
x
n
p
2
(x) = a
n+1
+ a
n+2
x + a
n+3
x
2
+· · · + a
2n+1
x
n
Rjeˇsenje.
1 double p( double x , double a [ ] , i nt n) {
2 double p1 = 0 , p2 = 0;
3 for ( i = n ; i >= 0; i −−) {
11.3. Hornerov algoritam 133
4 p1 = p1 ∗ x + a [ i ] ;
5 p2 = p2 ∗ x + a [ i + n + 1 ] ;
6 }
7 return p1 + p2 ;
8 }
Zadatak 11.3.4. Napiˇsite dio programa koji uˇcitava realni broj x, te za zadani niz a
duljine m+n+2 ispisuje vrijednost p
1
(x) −p
2
(x) gdje je
p
1
(x) = a
0
+ a
1
x + a
2
x
2
+· · · + a
n
x
n
p
2
(x) = a
n+1
+ a
n+2
x + a
n+3
x
2
+· · · + a
m+n+1
x
n
Op´cenito, probleme s Hornerovim algoritmom je najlakˇse rijeˇsiti svodenjem polinoma
na oblik
r(x) ·
f(n)
¸
i=0
a
g(i)
h(x)
i
,
tj. preslagivanjem polinoma na naˇcin da potencije argumenta (ovdje je to h(x)) idu redom
od nule (bez “preskakanja” potencija). Tada programski isjeˇcak koji raˇcuna vrijednost
polinoma izgleda ovako:
p = 0;
for (i = f(n); i >= 0; i--)
p = p * h(x) + a[g(i)];
p = p * r(x);
pri ˇcemu za r(x), f(n), g(i) i h(x) treba uvrstiti stvarne formule.
Primjer 11.3.1.
1.
¸
n
i=0
a
i
x
n−i
=
¸
n
i=0
a
n−i
x
i
Dakle: r(x) = 1, f(n) = n, g(i) = n − i, h(x) = x, pa Hornerov algoritam izgleda
ovako:
1 p = 0;
2 for ( i = n ; i >= 0; i −−)
3 p = p ∗ x + a [ n − i ] ;
2.
¸
n
i=0
a
i
x
i+1
= x ·
¸
n
i=0
a
i
x
i
Dakle: r(x) = x, f(n) = n, g(i) = i, h(x) = x, pa Hornerov algoritam izgleda
ovako:
1 p = 0;
2 for ( i = n ; i >= 0; i −−)
3 p = p ∗ x + a [ i ] ;
4 p ∗= x ;
134 11. Nizovi (polja)
3.
¸
n
i=2
a
2·i
x
2·i+1
=
¸
n−2
i=0
a
2·(i+2)
x
2·(i+2)+1
= x
5
·
¸
n−2
i=0
a
2i+4
(x
2
)
i
Dakle: r(x) = x
5
, f(n) = n − 2, g(i) = 2i + 4, h(x) = x
2
, pa Hornerov algoritam
izgleda ovako:
1 p = 0;
2 for ( i = n − 2; i >= 0; i −−)
3 p = p ∗ ( x ∗ x) + a [ 2 ∗ i + 4 ] ;
4 p ∗= x ∗ x ∗ x ∗ x ∗ x ;
ili
1 p = 0;
2 for ( i = n − 2; i >= 0; i −−)
3 p = p ∗ ( x ∗ x) + a [ 2 ∗ i + 4 ] ;
4 for ( i = 0; i < 5; i ++) p ∗= x ;
Zadatak 11.3.5. Napiˇsite program koji uˇcitava prirodne brojeve m i n takve da je m+n <
100, te m+n+1 realnih brojeva (a
i
)
m+n
i=0
. Program treba ispisati koliko je p(a
0
), pri ˇcemu
je
p(x) =
¸
m
i=1
a
i
x
i
¸
m+n
i=m+1
a
i
x
i−m
.
Na primjer, za m=3, n=2 i niz brojeva a[] = {2,3,5,7,11,13} program treba ispisati
1.10811, jer je
p(2) =
3 · 2 + 5 · 2
2
+ 7 · 2
3
11 · 2 + 13 · 2
2
=
6 + 20 + 56
22 + 52
=
82
74
=
41
37
= 1.10811.
Zadatak 11.3.6. Napiˇsite program koji uˇcitava prirodne brojeve m i n takve da je m+n <
100, te m+n+1 realnih brojeva (a
i
)
m+n
i=0
. Program treba ispisati koliko je p(a
m
), pri ˇcemu
je
p(x) =
¸
m−1
i=0
a
i
x
i
¸
m+n
i=m+1
a
i
x
i−m
.
Na primjer, za m=3, n=2 i niz brojeva a[] = {2,3,5,7,11,13} program treba ispisati
0.37535, jer je
p(7) =
2 · 7
0
+ 3 · 7
1
+ 5 · 7
2
11 · 7
1
+ 13 · 7
2
=
2 + 21 + 245
77 + 637
=
268
714
= 0.37535.
Zadatak 11.3.7. Napiˇsite program koji uˇcitava prirodni broj n, te n
2
+1 realnih brojeva
(a
i
)
n
2
i=0
. Program treba ispisati koliko je p(a
n
2), pri ˇcemu je
p(x) =
n−1
¸
i=0
n·(i+1)−1
¸
j=n·i
a
j
x
j−n·i
.
11.4. Sortiranje 135
Na primjer, za n=3 i niz brojeva
a[] = {2, 0.3, 0.5, 2, 0.3, 0.5, -2, 3, -7, 0.7}
program treba ispisati -20.07, jer je
p(0.7) = (2 + 0.3 · 0.7 + 0.5 · 0.7
2

(2 + 0.3 · 0.7 + 0.5 · 0.7
2

(−2 + 3 · 0.7 −7 · 0.7
2
)
= 2.455 · 2.455 · (−3.33) = −20.06999325
≈ −20.07.
Zadatak 11.3.8. Napiˇsite program koji uˇcitava prirodni broj n, te n + 1 realnih brojeva
(a
i
)
n
i=0
. Program treba ispisati koliko je p(a
0
), pri ˇcemu je
p(x) =
n−1
¸
i=0
i+1
¸
j=1
a
j
x
j−1
.
Na primjer, za n=3 i niz brojeva a[] = {0.7, 2, 0.3, 0.5} program treba ispisati
10.8511, jer je
p(0.7) = 2 · (2 + 0.3 · 0.7) · (2 + 0.3 · 0.7 + 0.5 · 0.7
2
) = 2 · 2.21 · 2.455 = 10.8511.
11.4 Sortiranje
Da bismo u nekom nizu mogli ˇsto brˇze prona´ci neki podatak (ili utvrditi da ga u nizu
nema), korisno je poredati elemente niza po nekom kriteriju (npr. po veliˇcini). Osnovna
operacija koja nam pri tome treba je zamjena vrijednosti dviju varijabli, ˇsto je obradeno
u zadatku 10.2.2.
Nadalje, treba nam prerasporedivanje elemenata niza.
Zadatak 11.4.1. Napiˇsite dio programa koji uˇcitani niz realnih brojeva x duljine n inver-
tira (poreda tako da mu elementi idu obrnutim redoslijedom: x
n−1
, x
n−2
, . . . , x
1
, x
0
).
U rjeˇsenju smijete koristiti funkciju swap() iz zadatka 10.2.2.
Rjeˇsenje (pogreˇsno). Zamjenjujemo i-ti element s lijeva i i-ti element s desna:
1 i nt i ;
2 for ( i = 0; i < n ; i ++) swap(&x [ i ] , &x [ n−1−i ] ) ;
Ovakva zamjena ´ce dva puta zamijeniti svaki par (x
i
, x
n−1−i
) elemenata, ˇsto znaˇci da ´ce
niz na kraju ostati nepromijenjen!
Rjeˇsenje. Zamjenu i-tog elementa s lijeva i i-tog elementa s desna treba napraviti samo
u jednoj polovici niza:
136 11. Nizovi (polja)
1 i nt i ;
2 for ( i = 0; i < n/2; i ++) swap(&x [ i ] , &x [ n−1−i ] ) ;
ili, ako uzmemo u obzir ekvivalentnost nizova i pointera u C-u:
1 i nt i ;
2 for ( i = 0; i < n/2; i ++) swap( x+i , x+n−1−i ) ;
Bez koriˇstenja funkcije swap(), rjeˇsenje izgleda ovako:
1 i nt i ;
2 for ( i = 0; i < n/2; i ++) {
3 double temp = x [ i ] ;
4 x [ i ] = x [ n−1+i ] ;
5 x [ n−1+i ] = temp ;
6 }
Sada smo oboruˇzani s dovoljno znanja da moˇzemo poredati elemente niza po veliˇcini.
Zadatak 11.4.2. Napiˇsite program koji uˇcitava broj n ≤ 1719, te niz od n cijelih brojeva.
Brojeve treba sortirati uzlazno po veliˇcini, te ispisati sortirani niz.
Primijetimo da je niz (x
i
)
n−1
i=0
sortiran ako i samo ako vrijedi:
∀i, j : (i < j) ⇒ x
i
≤ x
j
.
Dakle, potrebno je “protrˇcati” po svim parovima indeksa i i j takvima da je i < j i
provjeriti jesu li x
i
i x
j
u ispravnom poretku. Ako nisu, potrebno ih je zamijeniti.
Rjeˇsenje.
1 #include <s t di o . h>
2
3 i nt main( void) {
4 i nt ni z [ 1 7 1 9 ] ;
5 i nt n , i , j ;
6
7 pr i nt f ( ” kol i ko el emenata ima ni z ? ” ) ;
8 s c anf ( ”%d” , &n ) ;
9 for ( i = 0; i < n ; i ++) {
10 pr i nt f ( ” une s i t e %d . br oj : ” , i + 1 ) ;
11 s c anf ( ”%d” , &ni z [ i ] ) ;
12 }
13
14 for ( i = 0; i < n − 1; i ++)
15 for ( j = i + 1; j < n ; j ++)
16 i f ( ni z [ i ] > ni z [ j ] ) {
11.4. Sortiranje 137
17 i nt temp = ni z [ i ] ;
18 ni z [ i ] = ni z [ j ] ;
19 ni z [ j ] = temp ;
20 }
21
22 pr i nt f ( ” s o r t i r a n i ni z : \ n” ) ;
23 for ( i = 0; i < n ; i ++)
24 pr i nt f ( ” %d\n” , ni z [ i ] ) ;
25
26 return 0;
27 }
Prikazani algoritam se zove “klasiˇcni sort”. Preciznije, rijeˇc je o “loˇsoj” varijanti tog
sorta, jer se radi previˇse zamjena za svaki element niza. Puno je bolje prvo na´ci najmanji
element niza u dijelu niza s indeksima od i do n − 1, pa onda njega zamijeniti s i-tim
elementom niza (pogledati predavanja):
1 for ( i = 0; i < n − 1; i ++) {
2 i nt temp ;
3 i nt mi ni ;
4 mi ni = i ;
5 for ( j = i + 1; j < n ; j ++)
6 i f ( ni z [ mi ni ] > ni z [ j ] ) mi ni = j ;
7 temp = ni z [ i ] ;
8 ni z [ i ] = ni z [ mi ni ] ;
9 ni z [ mi ni ] = temp ;
10 }
ili joˇs malo bolje (ne radi zamjenu elementa sa samim sobom):
1 for ( i = 0; i < n − 1; i ++) {
2 i nt mi ni ;
3 mi ni = i ;
4 for ( j = i + 1; j < n ; j ++)
5 i f ( ni z [ mi ni ] > ni z [ j ] ) mi ni = j ;
6 i f ( mi ni > i ) {
7 i nt temp = ni z [ i ] ;
8 ni z [ i ] = ni z [ j ] ;
9 ni z [ j ] = temp ;
10 }
11 }
Zadatak 11.4.3. Rijeˇsite prethodni zadatak tako da niz sortirate silazno (od najve´ceg
broja prema najmanjem).
Uputa. Dovoljno je izmijeniti jedan znak u prethodnom rjeˇsenju.
138 11. Nizovi (polja)
Zadatak 11.4.4. Napiˇsite dio programa koji uˇcitava prirodni broj n < 1317, te niz od
n cijelih brojeva. Brojeve treba sortirati silazno po sumi znamenaka, te ispisati sortirani
niz.
Rjeˇsenje.
1 i nt x [ 1 3 1 6 ] ;
2 i nt n , i , j ;
3
4 pr i nt f ( ” Kol i ko el emenata ima ni z ? ” ) ;
5 s c anf ( ”%d” , &n ) ;
6
7 for ( i = 0; i < n ; i ++) {
8 pr i nt f ( ” Unesi t e %d . br oj : ” , i + 1 ) ;
9 s c anf ( ”%d” , &x [ i ] ) ;
10 }
11 for ( i = 0; i < n − 1; i ++) {
12 / ∗ S u m a z n a m e n a k a e l e m e n t a x [ i ] ∗ /
13 i nt suma1 = 0 ,
14 x1 = ( x [ i ] < 0 ? −x [ i ] : x [ i ] ) ;
15 while ( x1 > 0) {
16 suma1 += x1 % 10;
17 x1 /= 10;
18 }
19 for ( j = i + 1; j < n ; j ++) {
20 / ∗ S u m a z n a m e n a k a e l e m e n t a x [ j ] ∗ /
21 i nt suma2 = 0 ,
22 x2 = ( x [ j ] < 0 ? −x [ j ] : x [ j ] ) ;
23 while ( x2 > 0) {
24 suma2 += x2 % 10;
25 x2 /= 10;
26 }
27 / ∗ U s p o r e d b a s u m a z n a m e n a k a b r o j e v a x [ i ] i x [ j ] ∗ /
28 i f ( suma1 < suma2) {
29 / ∗ Z a m j e n a x [ i ] i x [ j ] ∗ /
30 i nt temp = x [ i ] ;
31 x [ i ] = x [ j ] ;
32 x [ j ] = temp ;
33 / ∗ S a d a x [ i ] i m a s u m u z n a m e n a k a s u m a 2 ∗ /
34 suma1 = suma2 ;
35 }
36 }
37 }
38
39 pr i nt f ( ” So r t i r a ni ni z : \ n” ) ;
40 for ( i = 0; i < n ; i ++)
11.4. Sortiranje 139
41 pr i nt f ( ” %d\n” , x [ i ] ) ;
Primijetimo da se mijenja samo uvjet zamjene (usporedujemo sume, a ne same brojeve),
dok sama zamjena ostaje nepromijenjena (i dalje zamjenjujemo elemente niza)!
Prilikom raˇcunanja suma znamenaka gledali smo apsolutne vrijednosti elemenata niza
jer za negativne vrijednosti operator % vra´ca negativne vrijednosti, ˇsto bi dalo pogreˇsan
rezultat!
Ovdje imamo dva puta napisan praktiˇcki isti kod (onaj za raˇcunanje zbroja znamena-
ka). To je puno lakˇse rijeˇsiti upotrebom funkcije koja ´ce zbrojiti znamenke broja i vratiti
tu vrijednost:
1 #include <s t di o . h>
2
3 i nt suma znamenaka ( i nt x) {
4 i nt suma = 0;
5 i f ( x < 0) x = −x ;
6 while ( x > 0) {
7 suma += x % 10;
8 x /= 10;
9 }
10 return suma ;
11 }
12
13 i nt main( void) {
14 i nt x [ 1 3 1 6 ] ;
15 i nt n , i , j ;
16
17 pr i nt f ( ” Kol i ko el emenata ima ni z ? ” ) ;
18 s c anf ( ”%d” , &n ) ;
19 for ( i = 0; i < n ; i ++) {
20 pr i nt f ( ” Unesi t e %d . br oj : ” , i + 1 ) ;
21 s c anf ( ”%d” , &x [ i ] ) ;
22 }
23
24 for ( i = 0; i < n − 1; i ++) {
25 i nt suma1 = suma znamenaka ( x [ i ] ) ;
26 for ( j = i + 1; j < n ; j ++) {
27 i f ( suma1 < suma znamenaka ( x [ j ] ) ) {
28 / ∗ Z a m j e n a x [ i ] i x [ j ] ∗ /
29 i nt temp = x [ i ] ;
30 x [ i ] = x [ j ] ;
31 x [ j ] = temp ;
32 / ∗ S a d a x [ i ] i m a s u m u z n a m e n a k a k o j u j e
33 p r i j e i m a o x [ j ] . D a k l e , t r e b a a z u r i r a t i
34 s t a n j e v a r i j a b l e s u m a 1 . ∗ /
35 suma1 = suma znamenaka ( x [ i ] ) ;
140 11. Nizovi (polja)
36 }
37 }
38 }
39
40 pr i nt f ( ” So r t i r a ni ni z : \ n” ) ;
41 for ( i = 0; i < n ; i ++)
42 pr i nt f ( ” %d\n” , x [ i ] ) ;
43
44 return 0;
45 }
Napomena 11.4.1. Suma znamenaka ´ce se za ve´cinu brojeva raˇcunati mnogo puta. Na
ˇzalost, ovo moˇzemo izbje´ci samo uvodenjem pomo´cnog niza, ˇsto je ˇcesto nepoˇzeljno (i
zabranjeno u zadacima) zbog pove´cane potroˇsnje memorije.
Zadatak 11.4.5. Rijeˇsite prethodni zadatak uvodenjem pomo´cnog niza u kojem ´cete
ˇcuvati sume znamenaka elemenata poˇcetnog niza tako da se te sume raˇcunaju toˇcno jed-
nom za svaki broj.
Uputa. Pazite da prilikom zamjene treba zamjenjivati elemente oba niza!
Primijetimo da je niz (x
i
)
n−1
i=0
sortiran ako i samo ako vrijedi:
i ∈ {0, 1, . . . , n −2} ⇒ x
i
≤ x
i+1
.
Drugim rijeˇcima, sortiranje moˇzemo provesti tako da usporedujemo samo susjedne ele-
mente niza. Algoritam za sortiranje koji koristi ovo svojstvo zove se Bubble sort.
Zadatak 11.4.6. Napiˇsite dio programa koji uzlazno sortira zadani niz a s n realnih
brojeva primjenom Bubble sorta.
Ono ˇsto trebamo raditi je “protrˇcati” nizom i zamijeniti svaka dva susjedna elementa
koji nisu u dobrom poretku. Na taj naˇcin ´cemo donekle ispraviti niz, ali ga, na ˇzalost,
ne´cemo u potpunosti sortirati. “Trˇcanje” je potrebno raditi dok god niz ne postane
sortiran, tj. dok god ne “protrˇcimo” kroz niz bez i jedne zamjene.
Bubble sort.
1 i nt nered ;
2 do {
3 nered = 0;
4 for ( i = 0; i < n − 1; i ++)
5 i f ( a [ i ] > a [ i +1] ) {
6 double temp = a [ i ] ;
7 a [ i ] = a [ i + 1 ] ;
11.5. Pretra
ˇ
zivanje 141
8 a [ i + 1] = temp ;
9 nered = 1;
10 }
11 } while ( nered ) ;
Primijetimo da ´ce ve´c u prvom prolazu najve´ci element niza do´ci na zadnje mjesto (jer
je ve´ci od svih, pa ´ce se stalno raditi zamjene). Dakle, njega viˇse ne moramo provjeravati.
Zbog toga moˇzemo malo smanjiti obim posla koji raˇcunalo mora obaviti:
Malo brˇzi Bubble sort.
1 i nt nered ;
2 i nt z adnj i = n ;
3 do {
4 nered = 0;
5 zadnj i −−;
6 for ( i = 0; i < z adnj i ; i ++)
7 i f ( a [ i ] > a [ i +1] ) {
8 double temp = a [ i ] ;
9 a [ i ] = a [ i + 1 ] ;
10 a [ i + 1] = temp ;
11 nered = 1;
12 }
13 } while ( nered ) ;
Iz ovog rjeˇsenja je oˇcito i koliko puta ´ce se izvrˇsavati tijelo for() petlje u najgorem
sluˇcaju: u prvom koraku while()-petlje n −1 put, u drugom n −2 puta, . . . , u zadnjem
koraku jednom. Dakle, ukupno:
(n −1) + (n −2) +· · · + 2 + 1 =
n(n −1)
2
ˇsto znaˇci da i ovaj algoritam, sliˇcno klasiˇcnom sortu, ima kvadratnu sloˇzenost. Ipak, ta
sloˇzenost se postiˇze u najgorem i u prosjeˇcnom sluˇcaju, ali u idealnom sluˇcaju (kad je
niz ve´c sortiran), algoritam samo n −1 puta izvrˇsava if() (i provjeru uvjeta i inkrement
for()-petlje), te tri puta pridruˇzivanje (zadnji = n, nered = 0 i zadnji--) i jednom
provjeru uvjeta do...while petlje. Ukupno, sloˇzenost (u idealnom sluˇcaju!) je samo
linearna, ˇsto je ipak brˇze od klasiˇcnog sortiranja.
11.5 Pretraˇzivanje
Zadatak 11.5.1. Neka je uˇcitan niz cijelih brojeva x duljine n. Napiˇsite dio programa
koji ´ce provjeriti nalazi li se u nizu x zadani cijeli broj y. Ako se nalazi, potrebno je
142 11. Nizovi (polja)
ispisati njegov indeks; u protivnom treba ispisati odgovaraju´cu poruku.
Rjeˇsenje. “Trˇcimo” po svim elementima niza. Ako nademo y, prekidamo “trˇcanje”. Na-
kon petlje provjeravamo jesmo li iz petlje izaˇsli jer je indeks “izletio” iz niza (tj. postao
prevelik). Ako je, znaˇci da nismo naˇsli traˇzeni broj; u protivnom, broj se nalazi na indeksu
na kojem smo prekinuli petlju:
1 i nt i ;
2 for ( i = 0; i < n ; i ++)
3 i f ( x [ i ] == y) break ;
4 i f ( i < n)
5 pr i nt f ( ”Broj %d s e nal az i u ni zu i ima i ndeks %d\n” ,
6 y , i ) ;
7 el se
8 pr i nt f ( ”Broj %d s e ne nal az i u ni zu . \ n” , y , i ) ;
Zadatak 11.5.2. Neka je uˇcitan uzlazno sortirani niz cijelih brojeva x duljine n. Na-
piˇsite dio programa koji ´ce provjeriti nalazi li se u nizu x zadani cijeli broj y. Ako se
nalazi, potrebno je ispisati njegov indeks; u protivnom treba ispisati odgovaraju´cu poruku.
Oˇcito, ovaj zadatak moˇzemo rijeˇsiti jednako kao i prethodni, no moˇzemo i efikasnije,
koriˇstenjem podatka da je niz (uzlazno) sortiran. Osnovna ideja je iskoristiti sljede´cu
ˇcinjenicu (koja vrijedi za sortirane nizove):
x < a
i
⇒ (∀j ≥ i : x < a
j
)
x > a
i
⇒ (∀j ≤ i : x > a
j
)
Dakle, prvi “sumnjivi” element niza, tj. onaj koji provjeravamo, nalazi se u sredini
(ima indeks ⌊
n
2
⌋). Ako je to element niza koji traˇzimo, problem je rijeˇsen. Ako nije, onda
– ovisno o tome je li taj element ve´ci ili manji od traˇzenog broja – znamo da se traˇzeni
broj ne nalazi u prvih ili u zadnjih ⌊
n
2
⌋ + 1 elemenata niza. U svakom sluˇcaju, odjednom
smo “rijeˇsili” barem pola niza.
Korak algoritma koji pretraˇzuje elemente niza od indeksa lijevi do indeksa desni
moˇzemo zapisati opisno:
• srednji =
lijevi+desni
2
• Ako je x = a
srednji
:
Broj je naden ⇒ STOP
• Ako je x < a
srednji
≤ a
srednji+1
≤ . . . :
Broj se ne nalazi desno od srednjeg, pa u idu´cem koraku ne treba gledati niˇsta od
11.5. Pretra
ˇ
zivanje 143
sadaˇsnjeg srednjeg na desno. Drugim rijeˇcima, nova desna granica je prethodnik
sadaˇsnjeg srednjeg, tj.
desni = srednji −1
• Ako je x > a
srednji
≥ a
srednji−1
≥ . . . :
Broj se ne nalazi lijevo od srednjeg, pa u idu´cem koraku ne treba gledati niˇsta prije
sadaˇsnjeg srednjeg (niti njega). Drugim rijeˇcima, nova lijeva granica je sljedbenik
sadaˇsnjeg srednjeg, tj.
lijevi = srednji + 1
Ovaj postupak ponavljamo dok ne nademo broj ili dok lijevi ne postane ve´ci od desnog
(jer je tada dio niza koji gledamo prazan).
Poˇcetne vrijednosti lijevog i desnog su poˇcetni prvi i zadnji indeks niza, tj. nula i
n −1.
Rjeˇsenje.
1 i nt l i j e v i = 0 , des ni = n − 1 , s r e dnj i ;
2
3 while ( l i j e v i <= des ni ) {
4 s r e dnj i = ( l i j e v i + des ni ) / 2;
5 i f ( x == a [ s r e dnj i ] ) break ;
6 i f ( x < a [ s r e dnj i ] )
7 des ni = s r e dnj i − 1;
8 el se
9 l i j e v i = s r e dnj i + 1;
10 }
11 i f ( l i j e v i <= des ni )
12 pr i nt f ( ”Broj %d s e nal az i u ni zu i ima i ndeks %d\n” ,
13 x , s r e dnj i ) ;
14 el se
15 pr i nt f ( ”Broj %d s e ne nal az i u ni zu . \ n” , x ) ;
Napomena 11.5.1. Prikazani algoritam zovemo binarno pretraˇzivanje i moˇzemo ga
primijeniti kad god imamo niz koji je sortiran po istom kriteriju po kojem vrˇsimo traˇzenje.
Inaˇce, potrebno je primijeniti klasiˇcno pretraˇzivanje (ono s poˇcetka ovog poglavlja).
Klasiˇcno pretraˇzivanje op´cenito nesortiranih nizova ima linearnu sloˇzenost, dok binar-
no pretraˇzivanje ima logaritamsku sloˇzenost. Kao ilustraciju razlike ova dva algoritma,
zamislite kako biste u telefonskom imeniku naˇsli neku osobu kad ne biste uzeli u obzir da
je imenik abecedno sortiran, nego biste prezimena pretraˇzivali po redu.
Zadatak 11.5.3. Neka je uˇcitan silazno sortirani niz cijelih brojeva x duljine n. Napi-
ˇsite dio programa koji ´ce provjeriti nalazi li se u nizu x zadani cijeli broj y. Ako se nalazi,
potrebno je ispisati njegov indeks; u protivnom treba ispisati odgovaraju´cu poruku.
144 11. Nizovi (polja)
Ponekad traˇzimo sve elemente koji odgovaraju nekom kriteriju. Tada nam sortiranost
niza, u pravilu, ne pomaˇze.
Zadatak 11.5.4. Napiˇsite dio programa koji uˇcitava prirodni broj n ≤ 1719 i niz x od n
realnih brojeva. Program treba izraˇcunati aritmetiˇcku sredinu niza i ispisati sve elemente
niza koji su strogo manji od aritmetiˇcke sredine.
Podsjetnik s predavanja. Aritmetiˇcku sredinu niza definiramo formulom:
AS(a) =
¸
n−1
i=0
a
i
n
=
a
0
+ a
1
+· · · + a
n−1
n
,
a raˇcunamo ju tako da “protrˇcimo” kroz cijeli niz, zbrojimo sve elemente i na kraju
dobivenu sumu podijelimo s brojem elemenata.
Rjeˇsenje.
1 double x [ 1 7 1 9 ] , as = 0;
2 i nt n , i ;
3
4 pr i nt f ( ” Kol i ko el emenata ima ni z ? ” ) ;
5 s c anf ( ”%d” , &n ) ;
6
7 for ( i = 0; i < n ; i ++) {
8 pr i nt f ( ” Unesi t e %d . br oj : ” , i + 1 ) ;
9 s c anf ( ”%l g ” , &x [ i ] ) ;
10 as += x [ i ] ; / ∗ o d m a h r a c u n a m o s u m u e l e m e n a t a n i z a ∗ /
11 }
12 as /= n ; / ∗ s u m u j o s t r e b a p o d i j e l i t i s n ∗ /
13 / ∗ ” T r c i m o ” p o n i z u i i s p i s u j e m o e l e m e n t e k o j i s u ∗ /
14 / ∗ m a n j i o d a r i t m e t i c k e s r e d i n e ∗ /
15 for ( i = 0; i < n ; i ++)
16 i f ( x [ i ] < as ) pr i nt f ( ”%g\n” , x [ i ] ) ;
Zadatak 11.5.5. Sliˇcno zadatku 11.1.6: Napiˇsite dio programa koji uˇcitava n realnih bro-
jeva (n < 19 je zadan). Potrebno je ispisati indeks i vrijednost broja koji je najudaljeniji
(ima najve´cu razliku) od svog sljedbenika. Ako takvih ima viˇse, ispiˇsite sve.
Uputa. Ova modifikacija nije jednostavna kao ona od zadatka 11.1.7. Ovdje je potrebno
napraviti dvije petlje: jednu koja ´ce traˇziti max i drugu koja ´ce ispisati sve one brojeve
ˇcija je udaljenost od sljedbenika jednaka max.
Zadatak 11.5.6. Napiˇsite program koji u niz uˇcitava cijele brojeve dok god ne uˇcita nulu
(ili dok ne uˇcita 616 brojeva). Program treba ispisati indekse onih elemenata niza kojima
je prva znamenka manja od zadnje.
11.6. Dodavanje i brisanje elemenata 145
Zadatak 11.5.7 (
ˇ
Slag na kraju). Napiˇsite program koji u niz uˇcitava prirodne brojeve dok
god ne uˇcita prost broj (ili dok ne uˇcita 616 brojeva). Program treba ispisati one elemente
niza kojima je suma znamenka prost broj ve´ci od 17.
11.6 Dodavanje i brisanje elemenata
Ponekad je potrebno u nizove dodati nove ili izbrisati neke od starih elemenata. To se,
naravno, moˇze rjeˇsavati kreiranjem pomo´cnih nizova, no takva rjeˇsenja su ˇcesto memo-
rijski zahtjevna i komplicirana za izvodenje. Dodavanje i brisanje elemenata moˇzemo
jednostavno raditi na postoje´cim nizovima.
11.6.1 Dodavanje elemenata
Dodavanje elemenata smo ve´c vidjeli u onoj najjednostavnijoj formi: uˇcitavanje (svaki
uˇcitani broj dodajemo na kraj do tada uˇcitanog niza). No, ponekad elemente treba
dodati na poˇcetak ili drugdje.
Zadatak 11.6.1. Napiˇsite dio programa koji ´ce u uˇcitani niz x cijelih brojeva dodati broj
17 ispred prvog neparnog broja. Duljina niza pohranjena je u varijabli n.
Rjeˇsenje. Dodavanje radimo u dva koraka. Prvo je potrebno na´ci prvi neparni broj, a
zatim – ako takav postoji – sve elemente iza njega treba pomaknuti za jedno mjesto udesno
i broj n pove´cati za 1.
1 / ∗ T r a z e n j e p r v o g n e p a r n o g ∗ /
2 for ( i = 0; i < n ; ++i )
3 i f ( x [ i ] % 2) break ;
4
5 i f ( i < n) {
6 / ∗ P o m i c a n j e s v i h i z a i − t o g ∗ /
7 for ( j = n−1; j >= i ; −−j )
8 x [ j +1] = x [ j ] ;
9 / ∗ S m a n j i m o n ∗ /
10 ++n ;
11 / ∗ Z a p i s u j e m o n o v i e l e m e n t ∗ /
12 x [ i ] = 17;
13 }
Primijetite: ako u nizu nema neparnih brojeva, niz ´ce ostati nepromijenjen.
Napomena 11.6.1. Prilikom pomicanja elemenata udesno vaˇzno je da petlja po varijabli
j ide s desna nalijevo. Sljede´ce pomicanje je pogreˇsno jer ´ce “pregaziti” sve elemente
iza i-tog (pokuˇsajte za niz 2, 3, 4, 5):
146 11. Nizovi (polja)
6 / ∗ P o m i c a n j e s v i h i z a i − t o g ∗ /
7 for ( j = i ; j < n ; ++j )
8 x [ j +1] = x [ j ] ;
Zadatak 11.6.2. Napiˇsite dio programa koji ´ce u uˇcitani niz x cijelih brojeva dodati broj
17 iza prvog neparnog broja. Duljina niza pohranjena je u varijabli n.
Rjeˇsenje. Rjeˇsenje je identiˇcno prethodnom, uz jedinu razliku u petlji za pomak udesno
(linija 7) i zadavanju vrijednosti 17 (linija 12).
1 / ∗ T r a z e n j e p r v o g n e p a r n o g ∗ /
2 for ( i = 0; i < n ; ++i )
3 i f ( x [ i ] % 2) break ;
4
5 i f ( i < n) {
6 / ∗ P o m i c a n j e s v i h i z a i − t o g ∗ /
7 for ( j = n−1; j > i ; −−j )
8 x [ j +1] = x [ j ] ;
9 / ∗ S m a n j i m o n ∗ /
10 ++n ;
11 / ∗ Z a p i s u j e m o n o v i e l e m e n t ∗ /
12 x [ i +1] = 17;
13 }
Alternativno, mogli smo samo prije ubacivanja (tj. prije linije 6 ili 7) pove´cati vrijednost
varijable i za 1 i u potpunosti primijeniti rjeˇsenje prethodnog zadatka.
Zadatak 11.6.3. Napiˇsite dio programa koji ´ce u uˇcitani niz x cijelih brojeva dodati
brojeve 17 i 19
a) ispred
b) iza
c) i ispred i iza
prvog neparnog broja. Duljina niza pohranjena je u varijabli n.
Zadatak 11.6.4. Napiˇsite dio programa koji ´ce u uˇcitani niz x cijelih brojeva dodati
brojeve 17 i 19
a) ispred
b) iza
c) i ispred i iza
zadnjeg neparnog broja. Duljina niza pohranjena je u varijabli n.
11.6. Dodavanje i brisanje elemenata 147
Uputa. Jedino ˇsto se mijenja je dio programa koji traˇzi referentni ˇclan. Petlja u liniji 2
rjeˇsenja zadatka 11.6.1 treba i´ci unatrag (od n −1 do 0).
Zadatak 11.6.5. Napiˇsite dio programa koji ´ce u uˇcitani niz x cijelih brojeva dodati
brojeve 17 i 19
a) ispred
b) iza
c) i ispred i iza
tre´ceg neparnog broja. Duljina niza pohranjena je u varijabli n.
Uputa. Jedino ˇsto se mijenja je dio programa koji traˇzi referentni ˇclan. U petlju u liniji
2 rjeˇsenja zadatka 11.6.1 treba dodati brojaˇc koji se pove´cava sa svakim pronadenim
neparnim brojem. Petlja se prekida kad taj brojaˇc dostigne vrijednost 3.
Zadatak 11.6.6. Napiˇsite dio programa koji ´ce u uˇcitani niz x cijelih brojeva dodati broj
2x
k
ispred svakog neparnog broja x
k
. Duljina niza pohranjena je u varijabli n.
Rjeˇsenje. Ovaj bismo zadatak mogli rijeˇsiti viˇsestrukim ponavljanjem rjeˇsenja zadatka
11.6.1, no takvo rjeˇsenje bilo bi komplicirano i sporo. Umjesto toga, zadatak ´cemo rijeˇsiti
jednim prolazom kroz cijeli niz, prepisuju´ci elemente na njihova nova mjesta.
Kroz niz je potrebno prolaziti s desna na lijevo, kao i kod pomicanja elemenata za
jedno mjesto (iz istog razloga koji je objaˇsnjen u napomeni 11.6.1). Postavlja se pitanje
odakle krenuti? Da bismo to znali, potrebno je prvo izraˇcunati novu duljinu niza.
1 #include <s t di o . h>
2
3 void i s p i s ( i nt x [ ] , i nt n) {
4 i nt i ;
5 pr i nt f ( ”%d” , x [ 0 ] ) ;
6 for ( i = 1; i < n ; ++i )
7 pr i nt f ( ” , %d” , x [ i ] ) ;
8 pr i nt f ( ”\n” ) ;
9 }
10
11 i nt main( void) {
12 i nt x [ 1 7 1 9 ] , n , n2 , i , j , br dodani h = 0;
13
14 pr i nt f ( ” Unesi t e dul j i nu ni za : ” ) ;
15 s c anf ( ”%d” , &n ) ;
16
17 for ( i = 0; i < n ; ++i ) {
18 pr i nt f ( ” Unesi t e %d . cl an ni za : ” , i +1);
148 11. Nizovi (polja)
19 s c anf ( ”%d” , &x [ i ] ) ;
20 }
21
22 pr i nt f ( ”\ nPr i j e dodavanja : ” ) ;
23 i s p i s ( x , n ) ;
24
25 / ∗ R a \ v { c } u n a n j e n o v e d u l j i n e n i z a ∗ /
26 for ( i = 0; i < n ; ++i )
27 i f ( x [ i ] % 2 == 1) ++br dodani h ;
28 n2 = n + br dodani h ;
29
30 / ∗ D o d a v a n j e n o v i h e l e m e n a t a ∗ /
31 j = n2 − 1;
32 for ( i = n − 1; i >= 0; −−i ) {
33 x [ j ] = x [ i ] ;
34 −−j ;
35 i f ( x [ i ] % 2 == 1) {
36 x [ j ] = 2 ∗ x [ i ] ;
37 −−j ;
38 }
39 }
40 n = n2 ;
41
42 pr i nt f ( ”Nakon dodavanja : ” ) ;
43 i s p i s ( x , n ) ;
44
45 return 0;
46 }
11.6.2 Brisanje elemenata
Zadatak 11.6.7. Napiˇsite dio programa koji iz uˇcitanog niza x cijelih brojeva briˇse prvi
parni broj. Duljina niza pohranjena je u varijabli n.
Napomena 11.6.2 (
ˇ
Ceste greˇske). Elemente koje ˇzelimo obrisati nije dovoljno zamijeniti
s nulom, jer je to samo zamjena elemenata drugom vrijednoˇs´cu, a broj elemenata u nizu
ostaje nepromijenjen.
Takoder, nije dovoljno niti samo ispisati niz bez elemenata koje ˇzelimo obrisati, jer se
samim ispisom niz uop´ce ne mijenja i ti elementi i dalje ostaju njegovi ˇclanovi.
Rjeˇsenje zadatka 11.6.7. Sliˇcno rjeˇsenju zadatka 11.6.1, brisanje radimo u dva koraka.
Prvo je potrebno na´ci prvi parni broj, a zatim – ako takav postoji – sve elemente iza
njega treba pomaknuti za jedno mjesto ulijevo i broj n smanjiti za 1.
11.6. Dodavanje i brisanje elemenata 149
1 / ∗ T r a z e n j e p r v o g p a r n o g ∗ /
2 for ( i = 0; i < n ; ++i )
3 i f ( x [ i ] % 2 == 0) break ;
4
5 i f ( i < n) {
6 / ∗ P o m i c a n j e s v i h i z a i − t o g ∗ /
7 while ( i +1 < n) {
8 x [ i ] = x [ i +1] ;
9 ++i ;
10 }
11 / ∗ S m a n j i m o n ∗ /
12 −−n ;
13 }
Zadatak 11.6.8. Napiˇsite dio programa koji iz uˇcitanog niza x cijelih brojeva briˇse zadnji
parni broj. Duljina niza pohranjena je u varijabli n.
Zadatak 11.6.9. Napiˇsite dio programa koji iz uˇcitanog niza x cijelih brojeva briˇse prvi
parni broj i idu´ca dva elementa iza njega. Duljina niza pohranjena je u varijabli n.
Napomena 11.6.3. Pripazite postoje li traˇzena dva elementa niza. Na primjer, ako je
prvi parni broj u nizu predzadnji element, onda iza njega postoji samo jedan element niza,
pa ´ce ukupni broj obrisanih elemenata biti dva, a ne tri.
Zadatak 11.6.10. Napiˇsite program koji uˇcitava prirodni broj n ≤ 1719 i niz x od n
realnih brojeva. Program treba iz niza obrisati sve elemente koji su strogo manji od arit-
metiˇcke sredine svih elemenata niza, te ispisati tako nastali niz i novu aritmetiˇcku sredinu
niza.
Rjeˇsenje. Ovaj zadatak moˇzemo rijeˇsiti viˇsestrukim ponavljanjem rjeˇsenja prethodnog
zadatka, no to znaˇci da ´cemo mnogo elemenata pomicati viˇse puta po jedno mjesto, ˇsto
je sporo.
Zato ovakvo brisanje (linije 35–44) radimo, kao i kod viˇsestrukog dodavanja u zadatku
11.6.6, na naˇcin da po redu ˇcitamo sve elemente (indeks i). One koje ne treba obrisati,
prepisujemo na nove pozicije te pove´cavamo odgovaraju´ci indeks (j) kako bi bio spreman
za zapisivanje idu´ceg broja. Za elemente koje treba obrisati, pamtimo koliko je obrisanih
(varijabla br_obrisanih), ali ne mijenjamo indeks j.
Na kraju je potrebno smanjiti vrijednost u varijabli n koja drˇzi duljinu niza.
1 #include <s t di o . h>
2 #include <s t dl i b . h>
3
4 void pr o vj e r i n ( i nt n) {
5 / ∗ a r i t m e t i c k a s r e d i n a n i j e d e f i n i r a n a z a p r a z n e n i z o v e ∗ /
150 11. Nizovi (polja)
6 i f ( n == 0) {
7 pr i nt f ( ”Niz j e prazan . ” ) ;
8 e xi t ( 0 ) ;
9 }
10 }
11
12 double ar s r ( double ni z [ ] , i nt n) {
13 i nt i ;
14 double sum = 0;
15 for ( i = 0; i < n ; ++i ) sum += ni z [ i ] ;
16 return sum / n ;
17 }
18
19 i nt main( void) {
20 double x [ 1 7 1 9 ] , as ;
21 i nt n , i , j = 0 , br obr i s ani h = 0;
22
23 pr i nt f ( ” Unesi t e dul j i nu ni za : ” ) ;
24 s c anf ( ”%d” , &n ) ;
25 pr o vj e r i n ( n ) ;
26
27 for ( i = 0; i < n ; ++i ) {
28 pr i nt f ( ” Unesi t e %d . cl an ni za : ” , i +1);
29 s c anf ( ”%l f ” , &x [ i ] ) ;
30 }
31
32 as = ar s r ( x , n ) ;
33 pr i nt f ( ” Ari tmeti cka s r e di na p r i j e br i s anj a : %g\n” , as ) ;
34
35 / ∗ B r i s a n j e ∗ /
36 for ( i = 0; i < n ; ++i ) {
37 i f ( x [ i ] < as ) {
38 ++br obr i s ani h ;
39 continue ;
40 }
41 i f ( i > j ) x [ j ] = x [ i ] ;
42 ++j ;
43 }
44 n −= br obr i s ani h ;
45
46 pr o vj e r i n ( n ) ;
47
48 as = ar s r ( x , n ) ;
49 pr i nt f ( ” Ari tmeti cka s r e di na nakon br i s anj a : %g\n” , as ) ;
50 pr i nt f ( ”%g” , x [ 0 ] ) ;
51 for ( i = 1; i < n ; ++i )
11.6. Dodavanje i brisanje elemenata 151
52 pr i nt f ( ” , %g” , x [ i ] ) ;
53 pr i nt f ( ”\n” ) ;
54
55 return 0;
56 }
Kod viˇsestrukog dodavanja kroz niz prolazimo slijeva na desno. Utoliko je brisanje jednos-
tavnije od dodavanja jer nije potrebno unaprijed izraˇcunati novu duljinu niza (v. rjeˇsenje
zadatka 11.6.6).
Zadatak 11.6.11. Napiˇsite program koji uˇcitava prirodni broj n ≤ 1719 i niz x od n
realnih brojeva. Program treba iz niza obrisati sve elemente kojima je index izmedu 7 i
19, te ispisati tako nastali niz.
Zadatak 11.6.12. Napiˇsite program koji uˇcitava prirodni broj n ≤ 1719 i niz x od n
realnih brojeva. Program treba iz niza obrisati sve elemente kojima je index prost broj, te
ispisati tako nastali niz.
Zadatak 11.6.13. Napiˇsite program koji uˇcitava prirodni broj n ≤ 1719 i niz x od n
realnih brojeva. Program treba iz niza obrisati sve elemente kojima je index neka potencija
broja 2, te ispisati tako nastali niz.
Zadatak 11.6.14. Napiˇsite program koji uˇcitava prirodni broj n ≤ 1719 i niz x od n
realnih brojeva. Program treba iz niza obrisati sve elemente koji su strogo ve´ci od svog
prvog susjeda slijeva, te ispisati tako nastali niz.
Napomena 11.6.4. Pripazite odakle ˇcitate niz, jer prvi element niza nema lijevih susjeda.
Zadatak 11.6.15. Napiˇsite funkciju koja prima niz realnih brojeva, te iz njega briˇse
najmanji element. Ako se taj pojavljuje u nizu viˇse puta, treba obrisati samo najljevijeg
od njih.
Rjeˇsenje. Podsjetimo se: niz je odreden s dva podatka, ˇsto znaˇci da funkcija mora primiti
barem dva argumenta (polje i duljinu niza). Prilikom brisanja elemen(a)ta, potrebno
je smanjiti duljinu niza, te ju nekako vratiti u glavni program. To moˇzemo napraviti ili
preko povratne vrijednosti funkcije ili preko varijabilnih argumenata. Prvi naˇcin je obiˇcno
jednostavniji, no nije primjenjiv kad funkcija mora vratiti joˇs neku vrijednost.
Kao ˇsto znamo, polja se uvijek prenose kao varijabilni argumenti, pa njih moˇzemo
mijenjati bez posebnih “zahvata”.
1 void b r i s i ( double x [ ] , i nt ∗n) {
2 double min ;
3 i nt i , j ;
4 / ∗ A k o j e n i z p r a z a n , n e m a m o s t o r a d i t i ∗ /
5 i f ( n == 0) return ;
6 / ∗ T r a z i m o n a j m a n j i e l e m e n t n i z a ∗ /
7 min = x [ 0 ] ;
152 11. Nizovi (polja)
8 for ( i = 1; i < ∗n ; ++i )
9 i f ( x [ i ] < min) min = x [ i ] ;
10 / ∗ B r i s e m o p r v o p o j a v l j i v a n j e n a j m a n j e g e l e m e n t a n i z a ∗ /
11 for ( i = 0; i < ∗n ; ++i ) {
12 i f ( x [ i ] == min) {
13 for ( j = i +1; j < ∗n ; ++j ) x [ j −1] = x [ j ] ;
14 −−(∗n ) ;
15 return ;
16 }
17 }
18 }
Primjer poziva funkcije:
1 double x [ 1 7 1 9 ] ;
2 i nt n ;
3 . . .
4 b r i s i ( x , &n ) ;
Ista funkcija bez varijabilnih argumenata izgleda ovako:
1 i nt b r i s i ( double x [ ] , i nt n) {
2 double min ;
3 i nt i , j ;
4 / ∗ A k o j e n i z p r a z a n , n e m a m o s t o r a d i t i ∗ /
5 i f ( n == 0) return 0;
6 / ∗ T r a z i m o n a j m a n j i e l e m e n t n i z a ∗ /
7 min = x [ 0 ] ;
8 for ( i = 1; i < n ; ++i )
9 i f ( x [ i ] < min) min = x [ i ] ;
10 / ∗ B r i s e m o p r v o p o j a v l j i v a n j e n a j m a n j e g e l e m e n t a n i z a ∗ /
11 for ( i = 0; i < n ; ++i ) {
12 i f ( x [ i ] == min) {
13 for ( j = i +1; j < n ; ++j ) x [ j −1] = x [ j ] ;
14 −−n ;
15 return n ;
16 }
17 }
18 }
Primjer poziva funkcije:
1 double x [ 1 7 1 9 ] ;
2 i nt n ;
3 . . .
4 n = b r i s i ( x , n ) ;
Ovakvo rjeˇsenje ne´ce biti primjenjivo u zadatku 11.6.18.
11.6. Dodavanje i brisanje elemenata 153
Zadatak 11.6.16. Napiˇsite funkciju koja prima niz realnih brojeva, te iz njega briˇse
najmanji element. Ako se taj pojavljuje u nizu viˇse puta, treba obrisati samo najdesnijeg
od njih.
Uputa. Rjeˇsenje je jednako prvom iz zadatka 11.6.15, uz promjenu smjera unutraˇsnje
petlje kod brisanja (linija 13).
Zadatak 11.6.17. Napiˇsite funkciju koja prima niz realnih brojeva, te iz njega briˇse
najmanji element. Ako se taj pojavljuje u nizu viˇse puta, treba obrisati sve njih.
Uputa. Rjeˇsenje je jednako prvom iz zadatka 11.6.15, uz brisanje naredbe return u liniji
15.
Zadatak 11.6.18. Napiˇsite funkciju koja prima niz realnih brojeva, te iz njega briˇse
najmanji element. Ako se taj pojavljuje u nizu viˇse puta, treba obrisati sve njih. Funkcija
kao povratnu vrijednost treba vratiti broj obrisanih elemenata.
Indeks
algoritmi, 59
binarno traˇzenje, 142
brojanje znamenaka, 125
brzo potenciranje, 95
Bubble sort, 140
djelitelji, 93
Euklidov, 107
Hornerov, 131
Hornerov (op´ci oblik), 133
klasiˇcni sort, 136
produkt brojeva, 99
prosti djelitelji, 93, 113
prosti djelitelji (uz kratnost), 94
provjera je li broj prost, 113
sort, 136
suma brojeva, 82
suma znamenaka, 88
brojevni sustavi, 1
ˇceste greˇske, 9, 11
direktno pretvaranje izmedu baza b
n
1
i
b
n
2
, 4
on-line vjeˇzbalica, 6
pretvaranje iz dekadske baze, 3
pretvaranje u dekadsku bazu, 2
raˇcunske operacije, 6
ˇceste greˇske
1 + 1 = 2 u raˇcunu sudova, 27
broj 1 nije ni prost ni sloˇzen, 29
brojevni sustavi, 9
C-ovski zapis “a > b, c”, 76
funkcije, 111
nizovi, 148
petlja u petlji, 89
pridruˇzivanje u uvjetima, 76
raˇcun sudova, 36
specijalni znakovi, 72
traˇzenje baze, 11
varijabilni argumenti funkcija, 118
zamjena varijabli, 117
disjunktivna normalna forma, 24
formati, 67
formule za pojednostavljivanje logiˇckih izra-
za, 27
funkcije
ˇceste greˇske, 111, 117, 118
nizovi kao argumenti, 126
grananje
ˇceste greˇske, 76
switch(), 103
jezik, 41
komentari, 66
konaˇcni
automat, 40
jezik, 41
konjunktivna normalna forma, 24
nizovi
ˇceste greˇske, 148
inicijalizacija, 122
normalne forme
disjunktivna, 24
konjunktivna, 24
on-line sadrˇzaj
brojevni sustavi, 6
provjera jednakosti formula raˇcuna su-
dova, 29
154
INDEKS 155
vjeˇzbalica za normalne forme, 26
operatori, 71
ˇceste greˇske, 72
dekrement, 74
inkrement, 74
op=, 73
operatori raˇcuna sudova (opisno), 20
operatori raˇcuna sudova (pomo´cu tablice is-
tinitosti), 20
palindrom, 15, 53
petlje
break, 96
continue, 98
“crtanje”, 101
ˇceste greˇske, 89
do...while(), 82
for(), 81
while(), 79
program
osnovni dijelovi, 61
raˇcun sudova
ˇceste greˇske, 27, 29, 36
De Morganove formule, 21
formule za pojednostavljivanje, 27
negacija implikacije, 21
obrat po kontrapoziciji, 21
on-line provjera jednakosti formula, 29
operatori (opisno), 20
operatori (pomo´cu tablice istinitosti), 20
regularni izraz, 41, 42
oznake, 42
regularni jezik, 41
sklopovi
osnovni, 30
poluzbrajalo, 31
potpuno zbrajalo, 32
verzije s viˇse ulaza, 31
zbrajanje binarnih brojeva, 34
sud, 19
tablica istinitosti, 19
varijable, 20
tipovi podataka
nizovi, 121
osnovni, 65
traˇzenje najve´ceg cijelog broja, 84

Sadrˇaj z
1 Brojevni sustavi 1.1 1.2 1.3 Pretvaranje brojeva medu bazama . . . . . . . . . . . . . . . . . . . . . . . Raˇunske operacije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c 1 2 6

Traˇenje baze . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 z 19

2 Raˇun sudova c 2.1 2.2 2.3 2.4 2.5 2.6

Tablice istinitosti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Normalne forme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Pojednostavljivanje logiˇkih izraza . . . . . . . . . . . . . . . . . . . . . . . 27 c Osnovni sklopovi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 Poluzbrajalo i potpuno zbrajalo . . . . . . . . . . . . . . . . . . . . . . . . 31 Dodatni zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 39

3 Konaˇni automati i regularni izrazi c 3.1 3.2

Konaˇni automati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 c Regularni izrazi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 59

4 Uvod u algoritme i osnovni program 4.1 4.2 4.3

Tko “programira”? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Osnovni program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Ispis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 65

5 Varijable 5.1 5.2

Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 Joˇ o formatima . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 s 71

6 Osnovne raˇunske operacije c 6.1

Uvod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 i

. . .while()-petlja . . . . . . . 126 11. . . . . . . . . . . . . . . . . . . . . . .2 Nizovi kao funkcijski argumenti . . . . . .5 8. . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Uvod . . 91 z Promjena toka petlje . . . . 130 11. . . . . . . . . . . . . . 135 11. .4 Sortiranje . . . 145 11. . . 81 do. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 11. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 Naredba switch() . . . . . . . . . . . . . . .6. . . . . . .2 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6 Dodavanje i brisanje elemenata . .6 while()-petlja . . . . . . . . . . . . . . 82 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1 8. . . . . . . . . . . . . . . . . . . . . .1 Jednostavne funkcije . . . . . . . . . . . . . . . . . . . . . . .2 Pridruˇivanje . . . . . . . . . . . . . . . . . . . . .ii ˇ SADRZAJ 6. . . . . . . . . . .5 Pretraˇivanje . . . . . . . . . . . . .4 8. . . . . . . . . . . . . . .. . . . .2 Varijabilni argumenti funkcija . . . . . . 83 Malo o sloˇenosti .1 7. 141 z 11. . . . . . . . . . . . . . . . . . . . . . . . .1 Dodavanje elemenata . . . .2 Obiˇno grananje . . 77 79 8 Petlje 8. . . . . . 148 . . . . 79 for()-petlja . . . . . . . . 96 103 9 Viˇestruko grananje s 9. . . . . . . . . . . . . . . . . . . . . .2 Brisanje elemenata . . . . . . . . .3 8. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 107 10 Funkcije 10. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .3 Hornerov algoritam . . . . . . . . . . . . . . . . . . 107 10. . . . . . . . . 114 11 Nizovi (polja) 121 11. . . . . . . . . . . . . . . . . . . . 145 11. . . . . . 72 z 75 7 Grananje 7. 75 c Uvjetni operator . .6. . . . . . . . .

1. te dobijamo broj 10. 7. 14. upotrebz c ljavamo i 6 dodatnih. B. a posljednju opet vra´amo na nulu i tako dobijemo 20. pa pove´avamo prvu. devet). 5. npr. Oznaka “F” ´e predstavljati c broj petnaest. nastavljamo: 11. Sada viˇe nemamo znamenaka. 6. Iako tako izgleda. 3. prikazi nekih brojeva (17 i 2007). 13. c 16. 5. 15. Kad nam ponovno ponestane znamenaka. 12. ovdje nismo preskoˇili brojeve. kad napic ˇemo “17”. 4. Naime. 8. Moˇemo koristiti i 16 znamenaka. 15. Oznaka “12” u bazi 10 predstavlja broj dvanaest. pa na s prelazimo na dvoznamenkaste brojeve: 10. ta ista oznaka (“12”) u bazi osam predstavlja broj deset. s prelazimo na dvoznamenkaste brojeve: na prvo mjesto stavljamo znamenku 1. uz uobiˇajenih deset (od 0 do 9). Postupak nastavljamo dok c god je potrebno. (10)10 = (12)8 = (A)16 . 17. U tom sluˇaju. 1 . C. to je prikaz nekog broja na odredeni naˇin. oznaka “B” broj jedanaest itd. D. Kako dalje? Poˇto nemamo dodatnih znamenaka. E i F. Naime. s Da bismo znali u kojoj je bazi neki broj. 4. 19. iza “7” dolazi “10” (a znamo da iza sedam dolazi osam). 6. 17. Ponovno nam nedostaju znamenke. Napomena 1.Poglavlje 1 Brojevni sustavi Brojimo: 0. 14. 1. oznaka c c “A” predstavlja broj deset. prvu znamenku pove´amo za c jedan. 3. MMVII s c s i sl. koje oznaˇavamo slovima A. zatim imamo “11” (tj. a zadnju znamenku postavljamo na najmanju mogu´u vrijednost (nula). 18. 16. 2. ako brojimo po redu. Poc novno brojimo kao i do sada. pa ´e oznaka “10” zapravo oznaˇavati broj ˇesnaest. 9. 12. 13. Tada. 2. Takav prikaz zovemo c c s “prikaz brojeva u heksadecimalnoj bazi” (ili “u bazi ˇesnaest”). 7.0. dok drugu vra´amo c c na nulu: 20. Kao i malo prije. zapisujemo ga na sljede´i naˇin: c c (broj)baza . deset). mijenjaju´i samo posljednju znamenku: 11. Opisani naˇin zapisivanja brojeva zovemo “prikaz brojeva u dekadskoj c bazi” (ili “u bazi deset”). no. pa “12” (tj.1. jednako kao ˇto su XVII. Kako bismo brojali kad bi nam netko zabranio upotrebu znamenaka 8 i 9? Krenimo istom logikom: 0. Ovakav zapis zovemo “prikaz brojeva u oktalnoj bazi” (ili “u bazi osam”).

d) (101001000)4 . i=0 Na taj naˇin dobijamo o kojem je broju rijeˇ. Zadatak 1. c) (101001000)2 = 1 · 28 + 1 · 26 + 1 · 23 = 256 + 64 + 8 = 328. ternarnom. ˇto znaˇi da ono c s c broji 0. oktalnom. 1. d) (101001000)4 = 1 · 48 + 1 · 46 + 1 · 43 = 65536 + 4096 + 64 = 69696. Pretvorite u bazu 10 sljede´e brojeve: c a) (13)16 b) (123)4 c) (101001000)2 Rjeˇenje. zapis u dekadskoj bazi. Brojevni sustavi Baza 2 3 8 10 16 Jedan (1)2 (1)3 (1)8 (1)10 (1)16 Dva (10)2 (2)3 (2)8 (2)10 (2)16 Tri (11)2 (10)3 (3)8 (3)10 (3)16 ˇ Cetiri (100)2 (11)3 (4)8 (4)10 (4)16 Sedamnaest Dvije tisu´e i sedam c (10001)2 (122)3 (21)8 (17)10 (11)16 (11111010111)2 (2202100)3 (3727)8 (2007)10 (7D7)16 Tablica 1. c c Primijetite da uvrˇtavanjem baze b = 10 dobijamo upravo “uobiˇajenu” interpretaciju s c zapisa po znamenkama. a1 a0 )b . U tablici 1 prikazani su primjeri prikaza nekih brojeva u binarnom. 10.1. . b) (123)4 = 1 · 42 + 2 · 41 + 3 · 40 = 16 + 8 + 3 = 27. . . Zapis broja a u bazi b oznaˇavamo s c ˇto moˇemo raspisati: s z n a = an bn + an−1 bn−1 + · · · + a1 b1 + a0 b0 = ai b i . tj. . 11. Raspisujemo po definiciji: s a) (13)16 = 1 · 161 + 3 · 160 = 16 + 3 = 19.2 1. binarni zapis). 100.1 Pretvaranje brojeva medu bazama a = (an an−1 .. 1.1. dekadskom i heksadecimalnom sustavu.1: Primjeri prikaza nekih brojeva u raznim brojevnim sustavima Raˇunalo koristi sustav sa samo dvije znamenke (tzv.

Postupak je prikazan na slici 1. c 13 = 3 4 + 1 3=0 4+3 1 0 3 (13) = (31) 10 4 Slika 1.1. Pretvorite broj a u bazu b. b = 13 7=1·4+3 3 1=0·4+1 3 0 1 Rjeˇenje: (31)10 = (133)4 .1: Pretvaranje (13)10 u bazu 4 (rezultat je (31)4 ) Zadatak 1.2. b = 4 b) a = 123. te zapisivanjem unatrag c c svih ostataka pri dijeljenju.1.1. Pretvaranje brojeva medu bazama 3 Prikaz broja a u bazi b dobijamo uzastopnim dijeljenjem a s b. pri ˇemu je: c a) a = 31. b = 16 Rjeˇenje. s a) 31 = 7 · 4 + 3 c) a = 1719. pri ˇemu je konaˇni rezultat (“(31)4 ”) oznaˇen sivom bojom. s c) 1719 = 132 · 13 + 3 132 = 10 · 13 + 2 3 10 = 0 · 13 + 10 2 0 A (= 10) Rjeˇenje: (123)10 = (A23)13 . s b) 123 = 7 · 16 + 11 7 = 0 · 16 + 7 B (= 11) 0 7 Rjeˇenje: (123)10 = (7B)16 .1. s Pretvaranje broja iz baze b1 = 10 u bazu b2 = 10 obiˇno radimo u dva koraka: c .

Pretvorimo broj iz baze b1 u bazu 10. Zadatak 1. c s ˇ Primjer 1. pri ˇemu svaku znamenku u poˇetnom zapisu zamjenjujemo s n1 znamenaka. postoji greˇka u postupku!). b2 = 8 Rjeˇenje. pri ˇemu je: c a) a = 1719. Pretvaranja medu bazama rade se kao u rjeˇenjima prethodna dva zadatka. . 2. Pretvorite broj a iz baze b1 u bazu b2 . . Dobiveni zapis dijelimo u grupice od po n2 znamenaka s desna na lijevo (ako nam za najlijeviju grupu ponestane znamenaka. 2.1. b1 = 5. n1 = 3 (jer je c 3 4 8 = 2 ) i n2 = 4 (jer je 16 = 2 ). ako postoje b. . . . na poˇetak dopiˇemo nule). ako ne ispadne. Po koracima: 1. . Neka je zapis broja a u bazi b1 dan s a = (an an−1 . b1 = 11. Zelimo broj (3701)8 pretvoriti u bazu 16. Tako dobijemo: c s |(an )b |(an−1 )b | . s s Ovdje navodimo samo rjeˇenja s medukorakom (prikazom broja u bazi 10): s a) (1719)11 = (2198)10 = (3012)9 b) (1311)5 = (206)10 = (316)8 Broj a iz baze b1 u bazu b2 moˇemo izvesti direktno. Svaku grupu znamenaka a′i zasebno pretvorimo u bazu b2 (od svake mora nastati toˇno jedna znamenka u bazi b2 .1. c c 3. 3701 −→ |011|111|000|001| 2. Pretvorimo broj iz baze 10 u bazu b2 .1. |a′1 |a′0 |. 1. a1 a0 −→ |(an )b |(an−1 )b | . n1 .3. . . pri ˇemu smo samo regrupirali postoje´e znamenke (nema nikakve konverzije). Brojevni sustavi 1. b2 = 9 b) a = 1311. n2 ∈ N takvi z n1 n2 da je b1 = b i b2 = b . |(a1 )b |(a0 )b |. . Oˇito je b = 2. a1 a0 )b1 .4 1. Svaku pojedinu znamenku pretvaramo iz baze b1 u bazu b: an an−1 . na poˇetak dopisujemo c nule. . |011|111|000|001| = 011111000001 −→ |0111|1100|0001| . Ako c c zapis znamenke ai u bazi b ima manje od n1 znamenaka. |(a1 )b |(a0 )b | −→ |a′k |a′k−1 | .

1. Bez pretvaranja u dekadski sustav. c Zadatak 1. Pretvaranje brojeva medu bazama 5 3. korak −→ |03|13| = (37)16 ili c 2 |11|01|11| −→ |0011|0111| = (37)16 n =4 b) (313)4 (313)4 b=4. popunite praznine: a) (17)8 = ( b) (313)4 = ( c) (1412)9 = ( d) (256)25 = ( Rjeˇenje. n1 = n i 2 n2 = 1). ako je b2 = bn . b=3. Zadatak 1. Popunite praznine: a) (17)16 = ( b) (314)8 = ( c) (1412)5 = ( d) (121)3 = ( e) (DEDA)16 = ( f ) (321)9 = ( )27 )9 )7 = ( )3 )17 = ( )2 )2 = ( )11 )3 .5.4.n1 =2 −→ |02|10|11| = (21011)5 (preskaˇemo korake 2 i 3 jer je n2 = 1). jer je (110)3 = 1 · 32 + 1 · 31 = 9 + 3 = 12 = (C)27 . n1 = 1 i c 1 c c n2 = n). preskaˇemo drugi i tre´i korak (jer je onda b1 = b.n1 =2 n =3 d) (256)25 b=5. (1100)2 = (12)10 = (C)16 i (1)2 = (1)16 . Ako je pak b1 = bn . Rjeˇenje: (3701)8 = (7C1)16 . s Naravno.1. jer je (111)2 = (7)16 . s a) (17)8 b=2.n1 =3 )16 )16 )27 )5 −→ 2 |001|111| −→ |0000|1111| = (F )16 2 preskaˇemo 1.1.n1 =1 b=2.n1 =2 −→ n =2 −→ n =4 2 c) (1412)9 −→ |01|11|01|02| −→ |001|110|102| = (1CB)27 .1. tada preskaˇemo prvi korak (jer je onda b2 = b. |0111|1100|0001| −→ 7C1.

oduzimati. a rjeˇenje moˇete provjeriti na sluˇbenoj stranici kolegija: s z z http://degiorgi. c . pri tome pazite da sve znamenke broja moraju biti strogo manje od baze u kojoj je broj zapisan!).hr/prog1/apps/brsust. izvodenjem operacija. Jedan naˇin je pretvaranjem u dekadsku bazu.2. Sve operacije se rade analogno c onima u dekadskom sustavu. no mogu´e je i direktno. Brojevni sustavi Zadatke b). mnoˇiti i dijeliti bez obzira na to u kojoj z z su bazi zapisani. te dobijamo: x + y = (35)10 = (100011)2 . moˇemo zbrajati. te c pretvaranjem u polaznu bazu.1. s a) (17)16 = (16)17 = (212)3 b) (314)8 = (11001100)2 c) (1412)5 = (11101000)2 = (1A1)11 d) (121)3 = (17)9 e) (DEDA)16 = (325220)7 = (2220020222)3 f) (321)9 = (9J)27 Ovakve zadatke moˇete si i sami zadavati (odredite broj i baze izmedu kojih ga ˇelite z z prebaciti. Traˇimo zbroj. Ako su brojevi prikazani s razliˇitim bazama. Primjer 1. Pretvaranjem lako dobijemo da su to x = (30)10 i y = (5)10 . x : y = (6)10 = (110)2 .6 1.2 Raˇunske operacije c Brojeve. Rjeˇenje. Izraˇunajmo vrijednost tih izraza bez pretvaranja u dekadsku bazu. x − y = (25)10 = (11001)2 .2. razliku.php 1.1. naravno. potrebno c je jednog od njih (ili oba) pretvoriti u neku bazu.math. ne radimo za 10 nego za b. Raˇunske operacije moˇemo izvrˇavati samo na brojevima koji su pric z s kazani u istom brojevnom sustavu. Napomena 1. d) i f ) rijeˇite na oba naˇina (i direktno i pomo´u pretvaranja u dekadsku s c c bazu). preporuˇljivo u onu u kojoj treba biti c zapisan rezultat. x · y = (150)10 = (10010110)2 . uz tu razliku da “1 dalje” i sl. produkt i kvocijent brojeva x = (11110)2 i y = z (101)2 .

ali = (1)10 + (1)10 = (2)10 = (10)2 . Zato. taj dio se ne primje´uje. tj. nego moˇe biti i viˇe. dapaˇe. npr. npr. izraz (1)2 + (1)2 daje “rezultat 1 i 1 dalje”. (10)2 − (1)2 . No. samo treba paziti jer nemamo nuˇno samo 1 z c z dalje. U binarnoj bazi. razlika: Kad oduzimamo ve´u znamenku od manje. Oduzimamo kao i u dekadskoj bazi. 11110 + 101 100011 2. Dakle. 4. princip je jednak onome iz dekadskog sustava. Racunske operacije 7 1. Dapaˇe. produkt: Mnoˇenje se obavlja sliˇno zbrajanju. Time dobijamo oduzimanje jednoznamenkastog broja od dvoznamenkastog. uz “pamtimo 1” koji zatim oduzmemo od idu´e znac menke): 11110 101 −1 11001 3.2. ako ve´ imamo “1 c dalje”. kvocijent: Ponovno. potrebno je “pogoditi” kvocijent c z . jedini koraci koc ji ˇine razliku su mnoˇenje i oduzimanje. (0)2 − (1)2 . rezultat zbrajanja 1 + 1 u bazi 2 je “nula i jedan dalje”.ˇ 1. potrebno je “posuditi” 1 c od lijeve znamenke. samo ˇto “posudenih” 1 ne daje 10 nego 2 (pa s 0 − 1 daje rezultat 2 − 1 = 1. zbroj: Primijetite: (0)2 + (0)2 (1)2 + (0)2 (0)2 + (1)2 (1)2 + (1)2 111 = (0)2 i = (1)2 i = (1)2 . nema z s c c niti klasiˇnog mnoˇenja (jer mnoˇimo samo s nulom ili jedinicom). potrebno je c z z paziti na potpisivanje i ispravno zbrojiti sve rezultate: 11110 · 101 1111 11110 0 11110 10010110 Primijetite: (1)2 + (1)2 + (1)2 = (10)2 + (1)2 = (11)2 .

ˇto daje negativan s rezultat. z Zadatak 1. Tada je c potrebno izraˇunati (14)8 − (5)8 = (12)10 − (5)10 = (7)10 = (7)8 . razliku. . 11 7347 + 155 7524 2.8 1. . s 1. Rjeˇenje. zbroj: Vrijedi: (7)8 + (5)8 = (7)10 + (5)10 = (12)10 = 1 · 8 + 4. Brojevni sustavi poˇetka djeljenika s djeliteljem.1. c z te se rezultat oduzima od poˇetka djeljenika. ˇto daje (10)10 = 1 · 8 + 2. Zbog toga jepotrebno “posuditi” 1 od tre´e znamenke s desna. Izraˇunajte zbroj. a1 a0 0)b . Ako je dobiveni rezultat nenegativan i c s c strogo manji od djelitelja. na primjer. “Spuˇtamo” idu´u c znamenku djeljenika i nastavljamo postupak: 11110 : 101 = 110 111 −101 101 00 0 −101 −0 Napomena 1. a1 a0 )b · b = (an an−1 . 7347 − 155 −1 7172 . Zatim se djelitelj mnoˇi s “pogodenim” rezultatom. Pri tome “posudec nu” jedinicu treba oduzeti od znamenke od koje je “posudena”. Nakon toga imamo (1)8 + (4)8 + (5)8 (tih “1 dalje” zbrojeno s predzadnje dvije znamenke). tj. . produkt i kvocijent brojeva x = (7347)8 i y = c (155)8 bez pretvaranja u dekadsku bazu. . razlika: Kod oduzimanja predzadnjih znamenaka imamo: (4)8 − (5)8 . .2.2. Tako. znaˇi da je kvocijent dobro pogoden. . a1 a0 )b · (10)b = (an an−1 . mnoˇenje s 2 u binarnoj bazi radimo dopisivanjem nule na kraj. pa je rezultat takvog zbrajanja 4 i “1 dalje”. rezultat 2 i “1 dalje”. Za svaku bazu b vrijedi: (an an−1 .2. s Analogno dalje.

x : y = (35)10 = (43)8 . kvocijent: 7347 : 155 = 43 734 −664 507 0 −507 Provjere radi. ˇto pokazuje da su dobiveni rezultati toˇni. Prilikom raˇunanja u raznim nedekadskim bazama.3 (Ceste greˇke). 7 · 5 = (35)10 = (43)8 → 3 2. moˇemo obaviti po koraciz z ma: 1. na primjer (7347)8 s 5.2. lako vidimo da je x = (7347)8 = (3815)10 i y = (155)8 = (109)10 . produkt: Mnoˇenje s jednom znamenkom. 4 · 5 = (20)10 = (24)8 . dodajemo joˇ “2 dalje” iz prethodnog koraka. pa je s konaˇni rezultat (17)8 + (3)8 = (22)8 → 2 c · 155 7347 45203 45203 1454133 4. od zadnjeg prema prc vom: (7347)8 · (5)8 = (45|2|0|3)8 = (45203)8 7347 1111 3. 7 · 5 = (35)10 = (43)8 . pa je s konaˇni rezultat (43)8 + (2)8 = (45)8 c Konaˇni rezultat dobijemo slaganjem rezultata po koracima. x · y = (415835)10 = (1454133)8 . . dodajemo joˇ “3 dalje” iz prethodnog koraka. s c ˇ Napomena 1. Racunske operacije 9 3.ˇ 1. ovome joˇ treba pribrojiti “4 dalje” (prva znamenka iz s prethodnog koraka). ˇto za rezultat daje (24)8 + (4)8 = (30)8 → 0 s 4. s c pripazite na ˇeste greˇke primjenjivanja uobiˇajenih pravila iz dekadskog sustava! Na c s c primjer: x − y = (3706)10 = (7172)8 .2. pa imamo: x + y = (3924)10 = (7524)8 . 3 · 5 = (15)10 = (17)8 .

ako dobijete rezultat poput (678)8 ili (73)5 . nego (5F)16 (= (95)10 ). b − 1}.2. u stvari oktalni! z Zadatak 1. onda za svaki i ∈ {0.2. 1. no on je. . 1. sve znamenke broja prikazanog u bazi b moraju biti nenegativne i c strogo manje od b! Na primjer. . . Izraˇunajte bez pretvaranja u druge baze: c a) (123)4 + (231)4 b) (1234)5 + (2341)5 + (3412)5 + (4123)5 c) (BABA)16 + (DEDA)16 d) (624)8 − (555)8 e) (147AD)15 − (EEEE)15 f ) (DEDA)16 − (BABA)16 g) (505)6 · (23)6 h) (314)8 · (72)8 i) (BABA)16 · (9A)16 j) (111011010)3 : (110)3 k) (7170)9 : (120)9 l) (F1FA)16 : (293)16 . . (x)b · (y)b i (x)b : (y)b ne smijete prvo izraˇunati kao da su x c i y dekadski brojevi. c • Izraze ne smijete niti samo evaluirati kao da su dekadski brojevi! Na primjer. on je besmislen i samim tim pogreˇan. a1 a0 )b . pa zatim rezultat pretvoriti u bazu b. (28)16 + (37)16 nije (65)16 (= (101)10 ). . nego morate ili raˇunati c direktno u bazi b (kako je opisano) ili pretvoriti u dekadsku bazu! Na primjer. . . jer ´e rezultat biti z c (10101)2 (toˇan rezultat je (101)2 ). Na primjer. Brojevni sustavi • Izraze (x)b ± (y)b . s • Paˇljivo proˇitajte zadatak i pazite koja je baza zadana. (10)2 + (11)2 ne moˇemo proglasiti za 21 i onda pretvoriti u bazu 2.10 1. Drugim rijeˇima. . • Ako je zapis broja u bazi b dan s (an an−1 . . broj (10110101)8 z c moˇe izgledati kao binarni broj. . n} mora vrijediti: ai ∈ {0.

1.3. Traˇenje baze z

11

Rjeˇenje. s a) (123)4 + (231)4 = (1020)4 b) (1234)5 + (2341)5 + (3412)5 + (4123)5 = (22220)5 c) (BABA)16 + (DEDA)16 = (19994)16 d) (624)8 − (555)8 = (47)8 e) (147AD)15 − (EEEE)15 = (47AE)15 f) (DEDA)16 − (BABA)16 = (2420)16 g) (505)6 · (23)6 = (20503)6 h) (314)8 · (72)8 = (27070)8 i) (BABA)16 · (9A)16 = (7053E4)16 j) (111011010)3 : (110)3 = (1002121)3 k) (7170)9 : (120)9 = (58)9 l) (F1FA)16 : (293)16 = (5E)16

Kao i s pretvaranjem brojeva izmedu razliˇitih brojevnih sustava, zadatke s raˇunanjem c c z z z u odredenoj bazi moˇete sami sastaviti, a rezultate moˇete provjeriti na sluˇbenoj stranici kolegija: http://degiorgi.math.hr/prog1/apps/brsust.php. Rezultate moˇete provjeriti i “na ruke”, pretvaranjem u dekadsku bazu. z Napomena 1.2.4. Ukoliko Vam na kolokviju ostane dovoljno vremena, za provjeru rijeˇite zadatke s raˇunskim operacijama na zasebnom papiru i s pretvaranjem u dekadski s c sustav. Ukoliko se rezultati ne poklapaju, znaˇi da postoji greˇka (ona moˇe biti i u origic s z nalnom i u kontrolnom raˇunanju)! c

1.3

Traˇenje baze z

Ponekad se u zadacima traˇi baza b u kojoj vrijedi neko svojstvo. U pravilu, takve zadatke z rjeˇavamo raspisom po definiciji (tj. pretvaranjem u dekadsku bazu). Pri tome treba paziti s da x + ai i x · ai , gdje su x i ai jednoznamenkasti nenegativni brojevi, ne moraju viˇe biti s jednoznamenkasti, kao i da x − ai i ai − x ne moraju viˇe biti nenegativni. Takoder, s korisno je dobivena rjeˇenja uvrstiti u poˇetne uvjete i tako provjeriti jesu li dobra. s c ˇ Napomena 1.3.1 (Ceste greˇke). s

12

1. Brojevni sustavi

• Sve dobivene baze moraju biti strogo ve´e od 1. Na primjer, brojevi −17, 0, 1 i sl. c nisu dobre baze brojevnih sustava. • Baza zapisa svakog broja mora biti strogo ve´a i od svih znamenaka tog broja. c • Baza, naravno, mora biti cijeli broj,√ kao i sve znamenke. Drugim rijeˇima, ako c s dobijete da je neka baza, na primjer, 5, to rjeˇenje morate odbaciti kao nezadovoljavaju´e. c • Pazite ˇto je baza, jer ona ne mora nuˇno biti varijabla b, nego moˇe biti i neka s z z druga varijabla ili ˇak neki izraz. Na primjer, ako imamo zadan broj (123)b+7 za c koji mora vrijediti neko svojstvo, tada mora biti b + 7 > 3, tj. b > −4. U takvom zadatku b = −3 moˇe (ali i ne mora) biti dobro rjeˇenje, jer je baza b + 7, a ne b. z s Zadatak 1.3.1. U kojoj bazi b je broj (123)b trostruko ve´i od broja (21)b , a u kojoj je c trostruko ve´i od broja (25)b ? c Rjeˇenje. Raspisujemo po definiciji: s (123)b = 3 · (21)b 1 · b + 2 · b + 3 = 3 · (2 · b + 1) = 6 · b + 3 b2 − 4b = 0 b(b − 4) = 0
2

Kandidati za rjeˇenja su b1 = 0 i b2 = 4. No, iz zadatka vidimo da mora biti b > 3, pa b1 s ne moˇe biti rjeˇenje. Za kraj, uvrˇtavamo rjeˇenje b = 4 u uvjet zadatka: z s s s (123)4 = 42 + 2 · 4 + 3 = 16 + 8 + 3 = 27 = 3 · 9 = 3 · (21)4 . Zakljuˇujemo da je b = 4 jedino rjeˇenje prvog dijela zadatka. c s Rijeˇimo sada drugi dio zadatka (na isti naˇin): s c (123)b = 3 · (25)b 1 · b + 2 · b + 3 = 3 · (2 · b + 5) = 6 · b + 15 b2 − 4b − 12 = 0 (b − 6)(b + 2) = 0
2

Kandidati za rjeˇenja su b1 = 6 i b2 = −2. No, iz zadatka vidimo da mora biti b > 5, pa s b2 ne moˇe biti rjeˇenje. Za kraj, uvrˇtavamo rjeˇenje b = 6 u uvjet zadatka: z s s s (123)6 = 62 + 2 · 6 + 3 = 36 + 12 + 3 = 51 = 3 · 17 = 3 · (25)6 . Zakljuˇujemo da je b = 6 jedino rjeˇenje drugog dijela zadatka. c s

1.3. Traˇenje baze z

13

U oba sluˇaja u prethodnom zadatku mogli smo jednostavno utvrditi donju granicu c za b (4 u prvom dijelu, odnosno 6 u drugom dijelu) i onda uvrˇtavanjem u uvjet zadatka s provjeravati kandidate za rjeˇenja: 4, 5, 6,. . . U oba sluˇaja bismo odmah pogodili rjeˇenja, s c s jer su ona jednaka donjim granicama. Ipak, takav pristup nikako nije dobar. Kao prvo, za pogodeno rjeˇenje treba dokazati s da je jedino. Kao drugo, rjeˇenje moˇe biti puno ve´e od donje granice i pogadanje moˇe s z c z potroˇiti mnogo vremena. s Zadatak 1.3.2 (Pismeni ispit iz “Uvoda u raˇunarstvo”, 28. 11. 2005). Nadite sve b-ove c takve da je (123)2b+3 = (501)b Rjeˇenje. Raspisujemo po definiciji: s (123)2b+3 = (501)b 1 · (2b + 3) + 2 · (2b + 3) + 3 = 5b2 + 1 4b2 + 16b + 18 = 5b2 + 1 b2 − 16b − 17 = 0 (b − 17)(b + 1) = 0
2

Kandidati za rjeˇenja su b1 = 17 i b2 = −1. Zbog uvjeta nenegativnosti, b2 ne moˇe s z biti rjeˇenje. S druge strane, mora vrijediti 2b + 3 > 3 i b > 5. Lako se vidi da b = 17 s zadovoljava oba uvjeta. Za kraj, uvrˇtavamo rjeˇenje b = 17 u uvjet zadatka: s s (123)2·17+3 = (123)37 = 372 + 2 · 37 + 3 = 1369 + 74 + 3 = 1446 = 5 · 172 + 1 = (501)17 .

Zakljuˇujemo da je b = 17 jedino rjeˇenje zadatka. c s

Zadatak 1.3.3 (Pismeni ispit iz “Uvoda u raˇunarstvo”, 14. 2. 2005). Nadite sve b-ove c takve da je (321)b + (321)b+1 + (321)b+2 = (840)b+3 . Rjeˇenje. Raspisujemo po definiciji: s (321)b + (321)b+1 + (321)b+2 = (840)b+3 9b2 + 24b + 24 = 8b2 + 52b + 84 b2 − 28b − 60 = 0 (b − 30)(b + 2) = 0

Kandidati za rjeˇenja su b1 = 30 i b2 = −2. Zbog uvjeta nenegativnosti, b2 ne moˇe biti s z rjeˇenje. S druge strane, mora vrijediti b > 3, b + 1 > 3, b + 2 > 3 i b + 3 > 8. Lako se vidi s da b = 30 zadovoljava sve te uvjete. Za kraj, uvrˇtavamo rjeˇenje b = 30 u uvjet zadatka: s s (321)30 + (321)30+1 + (321)30+2 = (321)30 + (321)31 + (321)32 = 2761 + 2946 + 3137 = 8844 = (840)33 . Zakljuˇujemo da je b = 30 jedino rjeˇenje zadatka. c s

s s Zadatak 1.6. Zbog toga odbacujemo b2 . raspisom po definiciji dobijamo da je jedino rjeˇenje b = 24. 6. No. Za koji b vrijedi (101010)b = (10101)b+1 ? Rjeˇenje.3. Rjeˇenje. Zadatak rjeˇavamo analogno prethodnom. 2005).3.14 1.5 (Pismeni ispit iz “Uvoda u raˇunarstvo”.3. s s s Zadatak 1. Za koje b vrijedi (123)b = (321)b−12 ? Rjeˇenje. Raspisom po definiciji dobijemo: s (123)b = (321)b−12 b + 2b + 3 = 3(b − 12)2 + 2(b − 12) + 1 = 3b2 − 70b + 409 2b2 − 72b + 406 = 0 b2 − 36b + 203 = 0 (b − 29)(b − 7) = 0 2 Kandidati za rjeˇenja su b1 = 29 i b2 = 7.7. s (101010)b = (10101)b+1 b5 + b3 + b = (b + 1)4 + (b + 1)2 + 1 = b4 + 4b3 + 6b2 + 4b + 1 + b2 + 2b + 1 + 1 (b − 3)(b2 + b + 1)2 = 0 . a uvrˇtavanjem b = 29 (primijetimo: s s b − 12 = 17) u formulu zadatka dobijamo: (123)29 = (902)10 = (321)17 . Rjeˇenje.4 (Pismeni ispit iz “Uvoda u raˇunarstvo”. Nadite sve b-ove c takve da je (101)b + (101)b+2 + (101)b+4 = (271)b+6 . 27. 2005). c s Zadatak 1.3. ˇto ukupno daje b > 15. pa je konaˇno (i jedino) rjeˇenje zadatka b = 29. Brojevni sustavi Zadatak 1. iz zadatka vidimo da mora vrijediti: s b > 3 i b − 12 > 3. Ponovno. 31. Jedino rjeˇenje je b = 23. Nadite sve b-ove c takve da je (131)b + (131)b+2 + (131)b+4 + (131)b+6 = (360)b+8 . 8.

x < b − 1. x < b ∪ 2 {((b − 1)1)b } ∪ (x(x + 1))b . no rjeˇavanje se ponovno svodi na raspis po defiz z s niciji i provjeravanje svih potrebnih uvjeta: Zadatak 1. pa (zato jer je (11)b · a palindrom). zakljuˇujemo: y = 1. gdje je c = x + y − b. Uvjet moˇe biti i naizgled sloˇeniji. 5. Imamo sljede´e sluˇajeve: 1. Provjerom uvjeta c = 0 dobijemo: c 0 = c = x + y − b = b − 1 + 1 − b = 0. 616. dobiveno spajanjem rjeˇenja i uvjeta svih sluˇajeva. 7. . x + 1 = b ⇒ (11)b · a = (10cy)b . x < b − 1. s Konaˇno rjeˇenje zadatka.3. x ≥ pa je dobiveno rjeˇenje a = ((b − 1)1)b dobro. x + y ≥ b ⇒ 0 ≤ x + y − b < 2 · b. tj. pa je y dobra znamenka). 2. c = 0. ABBA i sl. x + 1 < b (tj. Na primjer: 11. Oznaˇimo traˇeni broj s a = (xy)b = x · b + y.8 (Pismeni ispit iz “Uvoda u raˇunarstvo”.1. Za koje dvoznamenkaste brojeve (xy)b vrijedi da je (xy)b · (11)b palindrom (u ovisnosti o parametru b)? Palindrom je niz znakova (ili znamenaka) koji se jednako ˇita s lijeva na desno i s c desna na lijevo. Neka je zadana c baza b ∈ N. u svim brojevnim sustavima). ˇto znaˇi da je na poˇetku izraza jedna znamenka). Rjeˇenje. Tada je s c z (11)b · a = x · b2 + (x + y) · b + y c c (za svaki b. 2006). pa broj – rastavljen na znamenke – izgleda ovako: (x + 1) · b2 + (x + y − b) · b + y. Traˇenje baze z 15 Jedino realno rjeˇenje jednadˇbe je b = 3.3. x + y < b ⇒ (11)b · a = (x(x + y)y)b ⇒ x = y < b 2 2. Ponovno imamo dva sluˇaja: c 1. je: c s s c a ∈ (xx)b . Uvrˇtavanjem u formulu zadatka dobijamo: s z s (101010)3 = (273)10 = (10101)4 . s c c Tada je y = x + 1 (ˇto je manje od b. s (b − 1) 2 .

Rjeˇenje. . . Dva ´emo pokazati u sljede´im c c c zadacima: Zadatak 1. te provjerimo vrijedi li i za j. Primjer ove tvrdnje je djeljivost s 9 u dekadskom sustavu. Broj zapisan u bazi b je djeljiv s brojem b − 1 (tj. i=0 Primijetimo: pa je bi − 1 djeljivo s b − 1. s (x)j−1 b Pretpostavimo da tvrdnja vrijedi za sve i < j. .10. b y ∈ N0 . istinitost s tvrdnje je oˇita. moˇemo uvesti oznaku z (x)j−1 = yb + x. Dokaz provodimo indukcijom. Za i = 1.3. . te neka je b = 2(2k + 1) paran prirodni broj takav da b z je 2 neparan.9. Dokaˇite da tada broj b +1 2 prikazan u bazi b ima zadnju znamenku b 2 i bi − 1 = (b − 1) · (bi−1 + bi−2 + · · · + 1). Uvedimo oznaku: x = 2 + 1. a0 )b . Neka je k ∈ N0 . ˇto je upravo suma znamenaka broja a zapisanog u bazi b.3. Zakljuˇujemo da je a djeljiv s b − 1 ako i samo ako je s b − 1 c n djeljivo i i=0 ai . Kako za tvrdnja vrijedi (po pretpostavci). + 1 za sve i > 0.16 1. Za i = 2 imamo: c x2 = b2 b b b2 b +1 = +b+1= + + +1 2 4 4 2 2 b+2 2(2k + 1) + 2 = ·b+x= · b + x = (k + 1)b + x. b Rjeˇenje. 4 4 2 ˇto pokazuje da je zadnja znamenka broja x2 prikazanog u bazi b upravo x. Brojevni sustavi Neka svojstva dekadskog sustava vrijede i op´enitije. Neka je zadan broj s a = (an an−1 . Tada je n n n n a= i=0 n ai · b i = i=0 ai · b i − n ai + i=0 i=0 ai = i=0 ai · (bi − 1) + ai . Primjer ove tvrdnje je znamenka 6 u dekadskom sustavu (jer je 10 = 2(2 · 2 + 1)). s Zadatak 1. s najve´om znamenkom c u bazi b) ako i samo ako je njegova suma znamenaka djeljiva s b − 1.

xn − y n = (x + y)(xn−1 − xn−2 y + · · · + xy n−1 − y n−1 ). Zadatak 1. Traˇenje baze z 17 Vrijedi: (x)j = (x)j−1 · (x)b = (yb + x) · x = xyb + x2 b b = xyb + (k + 1)b + x = (xy + k + 1)b + x. jer posljednja znamenka od proizvoljnog xi (za i ≥ 1) z c ovisi samo o posljednjoj znamenci od x. Broj a = (an an−1 . nego i za z sve djelitelje od b − 1 (npr. c c Tvrdnja moˇe biti i op´enitija. . to znaˇi da tvrdnja vrijedi za sve i ∈ N. Rjeˇenje. ako je broj zapisan u bazi b). n (n−1)/2 n paran. ali moˇe i direktno. .3. ˇto znaˇi da tvrdnja vrijedi i c s c b za j.3. .3. Zadatak 1. s z primjenom sljede´ih identiteta: c xn + y n = (x + y)(xn−1 − xn−2 y + · · · − xy n−1 + y n−1 ). djeljivost s 3 u dekadskoj bazi). n neparan. takoder djeljiv s b + 1.9 ne vrijedi samo za b − 1. da broj ima parno mnogo znamenaka). . ˇime smo pokazali da je posljednja znamenka (x)j zaista x. Prema principu matematiˇke indukcije. Tada je a= i=0 (n−1)/2 ai b = i=0 2i i (a2i b2i + a2i+1 b2i+1 ) (n−1)/2 2i+1 = i=0 (n−1)/2 (a2i b + a2i+1 b 2i ) + (a2i − a2i+1 ) − (n−1)/2 2i+1 i=0 (a2i − a2i+1 ) = i=0 (n−1)/2 (a2i (b + 1) + a2i+1 (b − 1)) − i=0 (a2i − a2i+1 ) (a2i − a2i+1 ) (n−1)/2 = i=0 (a2i (b + 1)pi + a2i+1 (b + 1)qi ) − (n−1)/2 (n−1)/2 i=0 = (b − 1) i=0 (a2i pi + a2i+1 qi ) − i=0 = (a2i − a2i+1 ). Pretpostavimo da je n neparan (tj. s (11)b ) ako i samo ako je broj n i=0 (−1)n ai = a0 − a1 + a2 − a3 + . ako su zadovoljeni uvjeti tvrdnje iz b c zadatka. a0 ) zapisan u bazi b je djeljiv s brojem b + 1 (tj.1. Tvrdnju je jednostavno dokazati upotrebom kongruencija.3. Pn i=0 (−1) na i . i-ta potencija svakog broja sa zadnjom znamenkom 2 + 1 imat ´e opet zadnju b znamenku 2 + 1 (naravno.12. Dakle. Dokaˇite da tvrdnja zadatka 1.11.

Brojevni sustavi pri ˇemu su pi i qi ostaci nakon izluˇivanja b + 1 iz b2i + 1 i b2i+1 − 1 (respektivno). broj s neparno mnogo znamenaka (n paran) moˇemo promatrati i kao broj z s jednom znamenkom viˇe. Ako je n paran (tj. s Primjer ove tvrdnje je djeljivost s 11 u dekadskom sustavu. Ti c c ostaci su cijeli brojevi.18 1. prema formulama za rastavljanje xn + y n i xn − y n . . c te na preostalih n − 1 znamenaka primjenjujemo prethodni rezultat: n n−1 a= i=0 ai b = an + i=0 (n−2)/2 i ai b i (n−2)/2 = (b − 1) i=0 (a2i pi + a2i+1 qi ) + an − i=0 P = n (−1)n ai i=0 (a2i − a2i+1 ) . onda iz broja a izdavajamo vode´u znamenku. n − 1 je neparan). Alternativno. tako da definiramo an+1 := 0.

Nakon njih dolaze c implikacija i. Za koje vrijednosti a i b je formula a + b istinita? 19 . te od njih slaˇemo sloˇene izjave pomo´u logiˇkih c z z c c operatora. Na primjer: z • 17 + 19 = 36 (sud.1. tablicom istinitosti. jer ne iskazuje tvrdnju ˇiju bismo c z c istinitost mogli provjeriti) Jednostavne sudove zamjenjujemo sudovnim varijablama (najˇeˇ´e ih oznaˇavamo vec sc c likim ili malim latiniˇnim slovima). ⊤) i 0 (laˇ. nakon nje. ekvivalencija. dok god ne znamo koliki je x) ˇ • Popocat´petl je aktivni vulkan u Cileu (sud. Uz varijable. piˇite zagrade! s 2. tj. ⊥).1. te zatim c operator disjunkcije i iskljuˇivo ILI (oni imaju jednake prioritete). istinit) • 17 > 19 (sud. c Operator negacije ima najve´i prioritet.1. imamo i dvije konstante: 1 (istina. • Ho´u li uspjeti poloˇiti ovaj kolegij? (nije sud. false.1 Tablice istinitosti Istinitost pojedine formule moˇemo jednostavno provjeriti tzv. true. koja je ili c c z istinita ili laˇna. z Operatori koje obiˇno koristimo prikazani su u tablici 2. z Zadatak 2. Ako niste sigurni koji su prioriteti operatora. laˇan) z • 17 > x (nije sud. laˇan. Popocat´petl se nalazi u Meke z e siku).Poglavlje 2 Raˇun sudova c Sud ili izjava je svaka (smislena) reˇenica ˇiju istinitost moˇemo utvrditi. zatim dolazi operator konjukcije.

formula a + b je istinita ako je a istinit ili b laˇan. Pri tome.20 ˇ 2. tablicu 2.1. Racun sudova Naziv hrv.1: Opisi nekih logiˇkih operatora c Rjeˇenje. AND OR NOT XOR Simboli ·. ∧ +. Tablica istinitosti za k varijabli ima 2k redaka. a b 0 0 0 1 1 0 1 1 a+b a·b a a⇒b a⇔b a⊕b 0 1 1 1 0 0 0 1 1 1 0 0 1 1 0 1 1 0 0 1 0 1 1 0 Tablica 2.2: Logiˇki operatori c Napomena 2. I ILI NE iskljuˇivo c ILI engl. najlakˇe je prvi stupac popuniti s 2k−1 nula. ∨ a. Iz pric z c loˇene tablice istinitosti odmah vidimo da vrijedi: z (a ⇔ b) = a ⊕ b. c c a b b a+b 1 0 1 1 0 0 1 0 1 0 1 0 1 1 1 0 Dakle. ¬a ⊕ Opis a · b je istina ako i samo ako su i a i b istiniti a + b je istina ako i samo ako je a istinit ili b istinit (ili oba) a je istina ako i samo ako je a laˇ z a ⊕ b je istina ako i samo ako je ili a istinit ili b istinit (ali ne oba) Tablica 2. Tablicu istinitosti slaˇemo navodenjem svih kombinacija vrijednosti varijabli a s z i b. te s 2k−1 jedinica. z Logiˇke operatore moˇemo zadati pomo´u tablice istinitosti (v. drugi s .1). te raˇunanjem vrijednosti formule za svaku kombinaciju: c Tijekom postupka. na primjer b.1 (Varijable u tablici istinitosti). preporuˇljivo je raˇunati i podizraze.

1.3. tablica istinitosti imat ´e 24 = 16 redaka s c c (ovdje rastavljeno u 8 + 8 redaka): a b c d a+b c+d f 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 1 1 1 1 0 1 1 1 0 1 1 1 0 0 0 0 0 1 1 1 a b c d a+b c+d f 1 0 0 0 1 0 0 1 1 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1 1 Zadatak 2. Uputa.1.1.2. Tablice istinitosti 21 stupac s 2k−2 nula i 2k−2 jedinica. Pomo´u tablica istinitosti dokaˇite sljede´e vaˇne identitete: c z c z a) De Morganove formule: a + b = a · b. b) Negacija implikacije: a ⇒ b = a · b. Sloˇite tablicu istinitosti za izraz z f = (a + b) · (c + d). z Zadatak 2. Kako ovdje imamo ˇetiri varijable.1. idu´i opet s dvostruko c manjim grupicama nula i jedinica itd. . a · a = 0. Zadatak 2. a · b = a + b. Rjeˇenje. te opet 2k−2 nula i 2k−2 jedinica. c) Obrat po kontrapoziciji: (a ⇒ b) = (b ⇒ a) d) (a ⇔ b) = (a ⇒ b) · (b ⇒ a).4.2. U stupcu posljednje varijable trebaju ispasti nule i jedinice naizmjence. Sloˇite tablicu istinitosti za varijablu a (trebala bi imati dva retka). Dokaˇite: z a + a = 1.

zanima nas kad je s c c izjava ⇔ p. Ovdje nas ne zanima kad je neka izjava istinita. osim srijedom kada samo c z laˇe.5. T. Poˇinjemo uvodenjem pomo´nih varijabli: s c a = “Juˇer sam govorio istinu” c b = “Lagat ´u sutra” c Zanima nas kad se istinitost od p poklapa s istinitoˇ´u od a · b. Drugim rijeˇima. Koje dane u tjednu on moˇe re´i: z z c a) “Juˇer sam govorio istinu i lagat ´u sutra”? c c b) “Prekjuˇer sam lagao. Politiˇar N. a danas i sutra govorit ´u istinu”? c c c) “Ako nisam lagao juˇer. prekosutra ´u lagati”. priˇa. lagat ´u sutra”? c c d) “Ako danas i sutra govorim istinu. nego kad se podudara s onime s ˇto N. Racun sudova Rjeˇenje. gdje je p istina sve dane osim srijede (kad je laˇ). T. prekosutra ´u govoriti istinu”. (Nema Takvog) nikada ne laˇe. z Zadatak 2.1. z c Je li izjava pod d) negacija izjave pod e)? Rjeˇenje. Pokazat ´emo da vrijede De Morganove formule: s c a b a+b a+b a b a·b a·b a·b a+b 0 0 0 1 1 0 1 1 0 1 1 1 1 0 0 0 1 1 1 0 0 1 0 0 1 0 0 0 0 0 0 1 1 1 1 0 1 1 1 0 Istinitost ostalih tvrdnji provjerite za vjeˇbu. z c Rijeˇimo zadatak pod a).22 ˇ 2. sc Dan a b pon 1 0 uto sri ˇet c pet 1 1 1 0 0 0 1 0 p a · b p ⇔ (a + b) 1 1 0 1 1 1 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 sub 1 0 ned 1 0 . c e) “Ako danas i sutra laˇem.

(a ⇒ b) = a + b. b) srijeda i petak. z (a ⊕ b) = (a + b) · (a + b). Normalne forme 23 Dakle. Ostale operacije (implikacija. srijeda i ˇetvrtak c d) ponedjeljak i utorak e) svi dani osim srijede (jer je lijeva strana inkluzije – “danas i sutra (dva uzastopna dana) laˇem” – uvijek laˇna. dok je u srijedu izjava laˇna (a on srijedom laˇe). Dokaˇite da se svaka formula raˇuna sudova moˇe prikazati samo pomo´u z c z c negacije (operator NE). da sve formule raˇuna sudova moˇemo prikazati pomo´u negacije i c z c samo konjukcije ili samo disjunkcije.2 Normalne forme Zadatak 2. s 2. z Ostale tvrdnje provjerite za vjeˇbu.1. Kako dobiti formulu ako je zadana tablica istinitosti? Postoji viˇe naˇina. (a ⊕ b) = a · b + a · b. c) utorak. pa je inkluzija uvijek istinita). a na kraju (posljednji stupac) provjeravamo kad se njena istinitost poklapa s istinitoˇ´u tvrdnji koje taj dan govori N. sc jer on istinu moˇe re´i svaki dan osim srijede. tj. (a ⇔ b) = a · b + a · b. za rjeˇenje bi imala “svi dani osim ponedjeljka i utorka”. iskljuˇivo ILI) prikazat ´emo na taj s c c naˇin: c (a ⇒ b) = a · b + a · b + a · b.2. Primijetite da. Rjeˇenja su: z s a) utorak i srijeda.2. (a ⇔ b) = (a + b) · (a + b). jer je u utorak izjava istinita (a on utorkom govori c s istinu).2. izjava je laˇna. konjukcije (operator I) i disjunkcije (operator ILI). z z Iz priloˇenog je jasno i da izjave pod d) i pod e) nisu jedna drugoj negacije. Za vjeˇbu provjerite ispravnost navedenih formula. u tablici pratimo kad je formula a · b istinita. a z z z on bi trebao govoriti istinu. s c . Ostale dane. pa zato takvu izjavu ne moˇe dati. moˇemo eliminirati i sve disjunkcije z ili sve konjukcije. Zbog toga z c z c z je konaˇno rjeˇenje: utorak i srijeda. T. primjenom De Morganovih pravila. Rjeˇenje. Izjava koja bi z bila negacija izjavi pod d). a srijedom moˇe re´i samo laˇ. ekvivalencija.

a2 . . U tablici istinitosti gledamo sve retke koji sadrˇe jedinicu (istinu) u rezultatu. . . vn . Racun sudova Algoritam 2. . . . . v1 v2 . . . . . . . . gdje je k broj nula u stupcu koji odgovara izrazu f u tablici istinitosti. v j = 0 . 0 .24 ˇ 2.2. Reci su oblika: z a1 . gdje je bj = aj . an . . . an . v j = 0 . . . . .2. v j = 1 aj . . . . .1 (Konjunktivna normalna forma). a2 . . v1 v2 . gdje je bj = aj . . negiramo varijable koje imaju vric jednost jedan (ostale ne mijenjamo). . v j = 1 aj . . .2 (Disjunktivna normalna forma). f . U tablici istinitosti gledamo sve retke koji sadrˇe nulu (laˇ) u rezultatu. . vn . . . . “zbrajamo” te varijable (i negirane i nepromijenjene). . . . Za svaki takav redak kreiramo izraz: Bi = b1 + b2 + · · · + bn . . . Reci su oblika: z z a1 . . . z Algoritam 2. Disjunktivna normalna forma (DNF) izraza f je B1 + B2 + · · · + Bk . . te radimo “umnoˇak” tako dobivenih “suma”. Za svaki takav redak kreiramo izraz: Bi = b1 · b2 · · · · · bn . f . . . . Pojednostavljeno reˇeno: gledamo nule u rezultatu. . 1 . Konjunktivna normalna forma (KNF) izraza f je B1 · B2 · · · · · Bk . . .

do na poretke operanada. Analogno. 2 i 4). pa ih – prema algoritmu 2. za tre´i redak imamo: c Konaˇno rjeˇenje je: c s B3 = a · b.1 pomo´u normalnih formi.2. c s Rjeˇenje zadatka 2. varijabla a ima vrijednost 1. pa je konaˇno rjeˇenje c s (a ⇒ b) = a + b.2. 0 1 3. (a ⇒ b) = (a · b) + (a · b) + (a · b).2. to je B1 jedini u konjunktivnoj normalnoj formi c za a ⇒ b. Da bismo rijeˇili zadatak. potrebno je s prvo sloˇiti tablicu istinitosti za operatore implikacije. varijabla a ima vrijednost nula (pa ju negiramo). Izz c nimno. s . te radimo “zbroj” tako dobivenih “produkata”. U drugom retku. a varijabla b ima vrijednost 0. dok varijabla b ima vrijednost 1 (pa ostaje nepromijenjena). U prvom retku. Disjunktivnu normalnu formu za formulu a ⇒ b dobijemo promatranjem redaka koji sadrˇe jedinice (to su reci 1. trebamo negirati varijablu a i varijablu b ostaviti nepromijenjenu. U tom retku. 1 1 a⇒b a⇔b a⊕b 1 1 0 1 1 0 0 1 0 1 1 0 Konjunktivnu normalnu formu za formulu a ⇒ b dobijemo promatranjem tre´eg retka c (jer se samo u njemu nalazi nula u stupcu koji odgovara formuli a ⇒ b). B2 = a · b. i varijabla a i varijabla b imaju z vrijednost nula. Dakle. negiramo varijable koje imaju c vrijednost nula (ostale ne mijenjamo). ˇto znaˇi da je s c B1 = a · b. te zbrojiti dobiveno: B1 = a + b. ekvivalencije i iskljuˇivog ILI.2. Pojednostavljeno reˇeno: gledamo jedinice u rezultatu.2 – negiramo. Prema algoritmu 2.1. 0 0 2. 1 0 4. Kako se nula nalazi samo u tre´em retku. Normalne forme 25 gdje je k broj jedinica u stupcu koji odgovara izrazu f u tablici istinitosti.2. Na sliˇan naˇin rijeˇite formule a ⇔ b i a ⊕ b (rjeˇenja. oznaˇit ´emo i brojeve redaka (prvi stupac) za potrebe objaˇnjavanja postupka: c c s a b 1. c c s s moraju biti jednaka onima iz originalnog rjeˇenja zadatka). “mnoˇimo” te varijable (i negirane i nepromijez njene).

U zadatku ne piˇe koju normalnu formu treba napisati (dapaˇe. pa je lakˇe napisati konjunktivnu norc s s malnu formu: g = (a + b + c) · (a + b + c). ne piˇe niti da s s c s trebaju biti normalne forme). Racun sudova Napomena 2. pa moˇemo birati.2.3). c c c • ukupni broj B-ova u konjunktivnoj i disjunktivnoj normalnoj formi bit ´e takoder c n 2 .2. ako se oˇekuje i pojednostavljivanje izraza (poglavlje 2. Napisat ´emo obje c normalne forme za f : KNF: f = (a + b + c) · (a + b + c) · (a + b + c) · (a + b + c).26 ˇ 2. ako je mogu´e birati koju normalnu formu koristiti. Izrazu g odgovaraju dvije nule i ˇak ˇest jedinica. Napomena 2. • tablica istinitosti imat ´e 2n redaka (ne raˇunaju´i naslovni redak). a disjunktivnu ako ima malo nula. Ipak. g i h odredene sljede´om s c tablicom istinitosti (zbog preglednosti je podijeljena je u dva dijela): a b c 0 0 0 0 0 1 0 1 0 0 1 1 f g h 1 1 0 1 1 0 0 0 1 1 1 0 a b c 1 0 0 1 0 1 1 1 0 1 1 1 f g h 0 1 0 0 1 1 0 0 0 1 1 0 Rjeˇenje.2.2. pa je lakˇe napisati disjunktivnu c s s normalnu formu: h = a · b · c + a · b · c.pl . dobro c je koristiti konjunktivnu ako ima malo jedinica. ˇesto je praktiˇnije koristiti c c c disjunktivnu normalnu formu jer kod nje nije potrebno “izmnoˇiti” elemente u zagradama.hr/prog1/apps/knfdnf. Primijetite: ako imamo n varijabli. DNF: f = a · b · c + a · b · c + a · b · c + a · b · c. Generalno.2.math. Izrazu h odgovara ˇak ˇest nula i samo dvije jedinice.1. Napiˇite formule raˇuna sudova za izraze f . Za izraz f je svejedno koju normalnu z formu izaberemo jer tom izrazu odgovara jednag broj jedinica i nula. z c Zadatak 2. Interaktivnu vjeˇbalicu za normalne forme moˇete na´i na adresi z z c http://degiorgi.

4.4). a+b=b+a a+0=a a+1=1 a+a=a ¯ a=a a·b=b·a a·0=0 2. ¯=0 1 a+a=1 ¯ a+a·b=a+b ¯ a+b = a·¯ ¯ b a+a·b=a a + b · c = (a + b) · (a + c) ¯=1 0 a · (¯ + b) = a · b a a·b = a+¯ ¯ b a · (a + b) = a a·a=0 ¯ a·a=a (a + b) · (¯ + c) · (b + c) = (a + b) · (¯ + c) a a Tablica 2. formule moˇemo znaˇajno pojedz c nostaviti.1. a + (b + c) = (a + b) + c a · (b · c) = (a · b) · c a·1=a 6. Pojednostavite formule raˇuna sudova: c a) f = a · b · c + a · b · c + a · b · c.ˇ 2. zadatak 7.3. s Neke od formula koje mogu pomo´i prilikom pojednostavljivanja logiˇkih izraza navec c dene su u tablici 2. logiˇki izraz moˇe predstavs z c z z z ljati uvjet koji neki program treba izvrˇiti (v. ˇto je izuzetno vaˇno u primjenama. U raˇunu sudova NE VRIJEDI 1 + 1 = 2. a·b+a·c+b·c=a·b+a·c ¯ ¯ . 1. logiˇki izraz moˇe predstavljati c c z i elektroniˇki sklop koji treba sastaviti. U praksi. Pojednostavljivanje logickih izraza 27 2. ve´u potroˇnju energije. ˇto povlaˇi ve´u cijenu.3 pomo´u tablica istinitosti. a · (b + c) = a · b + a · c 8.1 (Cesta greˇka). 13. Kompliciraniji sklop (koji je rezultat komplicirac nijeg izraza) ima viˇe elemenata. Takoder.3. Primjenom jedz nostavnih identiteta (poput De Morganovih pravila).2.1. Dokaˇite formule iz tablice 2. pa njegova sloˇenost moˇe s znaˇajno usporiti ili ubrzati izvodenje programa. 3. 5.3.3 Pojednostavljivanje logiˇkih izraza c Formule izraˇene u normalnim formulama u pravilu su komplicirane. ve´ina elektroniˇkih sklopova (iznimka je DRAM) sastoji se od NAND-vrata c c (NOT AND) i NOR-vrata (NOT OR) s tri ili viˇe ulaza. 10. 9. 7. sporije s s c c c s c c izvodenje operacija i ve´i konaˇni sklop.3. ˇtoviˇe. 12. Na primjer. s c s s u raˇunu sudova 2 uop´e nema nikakvo znaˇenje! c c c Zadatak 2. z c Zadatak 2.3.3: Neke formule za pojednostavljivanje logiˇkih izraza c ˇ Napomena 2. 11.

ne mora svaki sumand sadrˇavati sve varijable). d) k = a · b · (a + b) + a · b · b + a. 10) = a · (b + c). tj. Racun sudova b) g = a · b · c + a · b · c + a · b · c + a · b · c. . Op´enito. b) Primijetimo: g = f + a · b · c i b + c = b + c + b · c. Sada imamo: g = f + a · b · c = a · (b + c) + a · b · c = a · (b + c + b · c) + a · b · c = a · (b + c) + a · b · c + a · b · c = a · (b + c) + (a + a) · b · c = a · (b + c) + b · c. formule je najlakˇe pojednostaviti tako da ih se svede na disjunktivnu formu c s (ne nuˇno normalnu.28 ˇ 2. Moˇemo i direktno: z g =a·b·c+a·b·c+a·b·c+a·b·c = (a + a) · b · c + a · b · c + a · b · c =b·c+a·b·c+a·b·c = (b + a · b) · c + a · b · c = (a + b) · c + a · b · c = a · c + b · c + a · b · c = a · (c + b · c) + b · c = a · (b + c) + b · c = a · b + a · c + b · c. Zatim se spretnim z z izluˇivanjem i sliˇnim pravilima (v. s a) Poˇinjemo izluˇivanjem zajedniˇkog podizraza (a·c) iz prva dva elementa disjunkcije: c c c f =a·b·c+a·b·c+a·b·c = a · c · (b + b) + a · b · c =1 =a·c+a·b·c=a·( c+b·c ) =b+c (pr.3) formula pojednostavljuje. tablicu 2. c) h = c · a + c · b · c · a + c + b. c c Rjeˇenje.

3. te “mnoˇenjem” zagrada: c z k = a · b · (a + b) + a · b · b + a =a·b =0 = a · b · a + a · b · b +(a + b) · (a · b) =a·b+a·a·b+b·a·b=a·b+a·b =0 = (a + a) · b = b. Najprije slaˇemo tablicu istinitosti: s z x2 x1 x0 (x2 x1 x0 )2 f 0 0 0 0 0 0 1 1 0 1 0 1 0 1 2 3 0 0 0 0 x2 x1 x0 (x2 x1 x0 )2 f 1 1 1 1 0 0 1 1 0 1 0 1 4 5 6 7 1 (4 = 2 · 2) 0 0 1 (6 = 2 · 3) . konaˇna formula ne mora sadrˇavati sve varijable. Pojednostavite z z c c dobiveni izraz! ˇ Napomena 2. Broj 1 nije ni prost ni sloˇen! s z Rjeˇenje. Kao ˇto vidimo. Zbog toga kao rjeˇenje uzimamo formulu a · (b + c) + b · c. s Inaˇe. dok prethodna formula. ovisno o izboru izluˇivanja. c Jednakost formula moˇete provjeriti na sluˇbenoj stranici kolegija: z z http://degiorgi. x1 i x2 . c) Ovdje kre´emo s viˇestrukom primjenom De Morganovih pravila kako bismo se ric s jeˇili sloˇenih izraza ispod negacija (jer s njima najˇeˇ´e ne moˇemo niˇta napraviti): s z c sc z s h=c·a+c·b·c·a+c+b =c·a+c·b+c·a+c·b =c·a+c·b+c·a+c·b = a · (c + c) + (c + c) · b = a + b. jednako dobra rjeˇenja.3. te vra´a 1 ako se broj c c (x2 x1 x0 )2 moˇe prikazati kao umnoˇak dva prosta broja.3 (Pismeni ispit iz “Uvoda u raˇunarstvo”. Inaˇe vra´a 0. ima samo 4.hr/prog1/apps/logika_sudova. mogli smo dobiti i druga. Prilikom pojednostavljivanja. Pojednostavljivanje logickih izraza 29 Primijetite da formula a · b + a · c + b · c ima 5 operatora. svaka dobivena formula mora biti ekvivalentna poˇetnoj. c c s Na primjer: a · b + (a + b) · c.math. a · (b + c) + b · c.2. s c z d) Ponovno kre´emo primjenom De Morganovih pravila. 14. Definirajte formulu c raˇuna sudova koja kao ulaz uzima binarne znamenke x0 .3.ˇ 2.pl Zadatak 2.2 (Cesta greˇka).2005).

c Upute.2002). a ∨ b iskljuˇivo ILI a ⊕ b c Tablica 2.4. Racun sudova Sada vidimo i zaˇto je ovakav raspored varijabli dobar: brojevi koje one daju (ako ih s interpretiramo kao binarne znamenke) idu po redu od 0 do 2n − 1. nego pomo´u konjunktivne norc s s c c malne forme jer imamo samo dvije jedinice i ˇak ˇest nula: c s f = x2 · x1 · x0 + x2 · x1 · x0 = x2 · x0 . te ju z povezujemo sa sklopovima koji odgovaraju operatorima koje ti sklopovi predstavljaju. Zatim izvedite konjunktivnu ili disjunktivnu s normalnu formu. na naˇin da svaki operator zamijenimo odgovaraju´im sklopom. . gdje je n broj varijabli (ovdje je n = 3). Nacrtajmo sklop koji odgovara izrazu f = a + b · c + a · c.3. c Primjer 2. logiˇki izrazi ˇesto se koriste prilikom izrade elektroniˇkih sklopova. Sklopovi koji odgovaraju osnovnim operatorima su dani su u tablici 2. te primjenom De Morganovih pravila eliminirajte sve konjukcije. ¬a a · b. Na isti naˇin nastavljamo gradnju s izlazima iz sklopova.1. 22. Napiˇite formulu c s raˇuna sudova (koja se sastoji samo od operatora ILI i negacije) koja za ulaz x = (x2 x1 x0 )2 c provjerava je li x nultoˇka funkcije f (x) = x3 − x2 − 4x + 4.1. Rjeˇenje je priloˇeno na slici 2. Simbol Naziv negacija konjukcija disjunkcija Oznake a. 2.30 ˇ 2. a ∧ b a + b. s z “Mosti´i” pokraj varijabli b i c sluˇe da se naglasi da se “ˇica” od a ne sijeˇe sa “ˇicama” c z z c z od b i c. Zadatak 2. s c c c Izraze moˇemo i nacrtati. te napiˇite tablicu istinitosti. Problem je oˇito lakˇe rijeˇiti pomo´u disjunktivne.4.4: Osnovni sklopovi Sklop gradimo tako da svakoj varijabli dodijelimo jednu ulaznu “ˇicu” (liniju). z c c koje zatim povezujemo u cjelinu.4 Osnovni sklopovi Kao ˇto smo naveli.4. Izraˇunajte nultoˇke funkcije ili uvrstite sve mogu´e vrijednosti x (cijeli brojevi c c c od 0 do 7).4 (Pismeni ispit iz “Uvoda u raˇunarstvo”.

4. Poluzbrajalo i potpuno zbrajalo 31 a b c f Slika 2.2: Sklop AND s tri ulazne “ˇice” z a · b · c. Nacrtajte sklopove koji odgovaraju originalnim i pojednostavljenim izrazima iz zadatka 2.3. on je samo pokrata i zato se broji kao dva sklopa! Ovakvim “zahvatima” u crtanju ne smanjujete broj operatora/sklopova u rjeˇenju zadatka! s 2. Konstruirajte (nacrtajte) poluzbrajalo (engl. half adder).1. Ponekad se u operatore ubacuje viˇe ulaznih “ˇica” nego je to uobiˇas z c z c jeno. kao – na primjer – kod sklopa AND na slici 2. te izlaze s (sum) i c (carry) za koje vrijedi: s = znamenka jedinica u sumi x + y c = znamenka desetica u sumi x + y Oˇito. Time se ˇeli skra´eno prikazati izraz a b c Slika 2. iako je nacrtan samo jedan sklop. c Rjeˇenje. a c “jedan dalje” prilikom zbrajanja dva binarna broja.2.5 Poluzbrajalo i potpuno zbrajalo Zadatak 2. sklop koji ima ulaze x i y (jednoznamenkasti binarni brojevi).1 (Poluzbrajalo).1: Sklop f = a + b · c + a · c Zadatak 2.2.5.1.2.5. Sastavimo tablicu istinitosti za s i c: s x y c s 0 0 0 0 0 1 0 1 1 0 0 1 1 1 1 0 . tj.4. Ipak. s predstavlja “sumu”. Napomena 2.

Izraze nalazimo pomo´u normalnih formi: c DNF: c = x · y KNF: s = (x + y) · (x + y) = (x + y) · x · y Konaˇno. a c “jedan dalje” prilikom zbrajanja tri binarna broja. te izlaze s (sum) i c (carry) za koje vrijedi: s = znamenka jedinica u sumi x + y + z c = znamenka desetica u sumi x + y + z Oˇito. Racun sudova Primijetite: x + y = (sc)2 . s predstavlja “sumu”. y i z (jednoznamenkasti binarni brojevi). Konstruirajte (nacrtajte) potpuno zbrajalo (engl. moˇemo nacrtati poluzbrajalo (v. c Slika 2. c . sliku 2.3). na svaku izlaznu “ˇicu” napisati z z je li ona s ili c).3: Poluzbrajalo Poluzbrajalo oznaˇavamo kao na slici 2.5.4: Simbol poluzbrajala crtanja poluzbrajala nuˇno je naglasiti koji je koji (tj.4. Kako izrazi c i s ne komutiraju. tj. c z x s c y Slika 2. prilikom c s H. sklop koji ima ulaze x. full adder).32 ˇ 2. Zadatak 2.A.2 (Potpuno zbrajalo).

5: Potpuno zbrajalo s kao i suma s1 + z (pri ˇemu je s1 zadnja znamenka sume x + y). prilikom c s F. Poluzbrajalo i potpuno zbrajalo 33 Rjeˇenje. Izraze moˇemo lako dobiti pomo´u normalnih formi (napravite to sami za vjeˇbu). a prenosimo “jedan dalje” c ako imamo “jedan dalje” u bilo kojem od ta dva zbrajanja (tj. s2 Slika 2.6. Kako izrazi c i s ne komutiraju. sliku 2. z c z potpuno zbrajalo moˇemo nacrtati i koriste´i poluzbrajala. c Slika 2. z .A.5.6: Simbol potpunog zbrajala crtanja potpunog zbrajala (kao i kod poluzbrajala) nuˇno je naglasiti koji je koji (tj.2. Potpuno zbrajalo oznaˇavamo kao na slici 2. Sastavimo tablicu istinitosti za s i c: s x y z c s 0 0 0 0 0 0 0 1 0 1 0 1 0 0 1 0 1 1 1 0 1 0 0 0 1 1 0 1 1 0 1 1 0 1 0 1 1 1 1 1 Primijetite: x + y + z = (sc)2 . z na svaku izlaznu “ˇicu” napisati je li ona s ili c). Suma x + y + z ima jednaku zadnju znamenku c1 x y H.5). simuliraju´i time zbrajanje z c c “znamenku po znamenku” (v.A. No.A. ako je c1 jednak 1 ili ako je c2 jednak 1). s1 c c2 z H.

rezultar ´e c c biti znamenka z1 i.7). za brojeve od 0 do 7).34 ˇ 2. neke od dioda f1 − f7 ´e biti upaljene c c f6 f3 . U ovom zadatku je sadrˇano sedam istovjetnih zadataka.3.5. Konstruirajte sklop koji zbraja dva 3-bitna binarna broja x = (x2 x1 x0 )2 i y = (y2 y1 y0 )2 . Svaki broj od 0 do 7 z f1 f2 f4 f5 f7 Slika 2. Uputa. Zbog toga ´emo s s c simulirati zbrajanje “na ruke” (slika 2. Za svaki od brojeva. Prvo zbrajamo zadnje znamenke brojeva: x0 + x0 x1 x2 y0 y1 y2 c0 H. “jedan dalje” (oznaˇimo ga s c1 ). zbrajamo c c c1 + x2 + y2 . s2 = z2 ). Racun sudova Zadatak 2. c “jedan dalje” (oznaˇimo ga s c0 ). U drugom koraku zbrajamo c0 + x1 + y1 . Rjeˇenje. c2 s2 z0 z1 z2 z3 Slika 2. Tablica istinitosti bi imala 26 = 64 retka. Rezultat tog zbroja daje posljednju znamenku konaˇnog rezultata z0 i. c1 s1 F.6 Dodatni zadaci Zadatak 2.8: 7-segmentni indikator s prikazanim brojem 3 treba nacrtati kao ˇto ga iscrtava kalkulator (pri tome se broj 1 moˇe nacrtati na dva s z naˇina.A. izaberite jedan). ˇto su prve dvije znamenke konaˇnog s c rezultata (tj.6.7: Sklop za zbrajanje troznamenkastih binarnih brojeva y0 .1. eventualno. Konstruirajte logiˇke sklopove za 7-segmentni indikator s 3-bitnim ulazom c (tj.A. ˇto je velik posao. c2 = z3 . rezultat tog zbrajanja je (c2 s2 )2 .A. 2. eventualno. s0 F. Konaˇno.

Dodatni zadaci 35 (stanje 1).6. itd). Napiˇite konjunktivnu c s i disjunktivnu normalnu formu formule f raˇuna sudova zadane pomo´u tablice: c c a b c f 0 0 0 0 0 0 1 0 0 1 0 1 0 1 1 1 a b c f 1 0 0 0 1 0 1 1 1 1 0 1 1 1 1 1 Zadatak 2. te pomo´u konjunktivnih ili disjunktivnih normalnih formi dobiti formule za c pojedine fi . no ovaj put z z sklopovi ovise o 4 ulazne varijable. f2 = x0 · x1 · x2 + x0 · x1 · x2 + x0 · x1 · x2 + x0 · x1 · x2 = x0 · x1 (x2 + x2 ) + x0 · x1 · x2 + x0 · x1 · x2 = x1 · (x0 + x0 · x2 ) + x0 · x1 · x2 = x1 · (x0 + x2 ) + x0 · x1 · x2 = x1 · x0 + x1 · x2 + x0 · x1 · x2 = x0 · x1 + (x1 + x0 · x1 ) · x2 = x0 · x1 + (x1 + x0 ) · x2 = x0 · x1 + x1 · x2 + x0 · x2 = x0 + x1 + (x0 + x1 ) · x2 = x0 + x1 + x0 · x1 · x2 . Potrebno je sastaviti tablicu istinitosti za c s sve brojeve.3 (Kolokvij iz “Uvoda u raˇunarstvo”. Neka od rjeˇenja koje trebate dobiti (uz pretpostavku da smo broj 1 dobili paljenjem s f3 i f6 . . Konstruirajte logiˇke sklopove za 7-segmentni indikator s 4-bitnim ulazom c (tj. Zadatak 2. trebate sloˇiti 7 sklopova). 30. Pazite: tablicu je najlakˇe popuniti po recima (tj. a neke ´e biti ugaˇene (stanje 0). a ne f2 i f5 ): f1 = (x0 + x1 + x2 ) · (x0 + x1 + x2 ) = x0 · x0 + x0 · x1 + x0 · x2 + x1 · x0 + x1 · x1 + x1 · x2 + x2 · x0 + x2 · x1 + x2 · x2 = x1 · (x0 + x0 + 1 + x2 + x2 ) + x0 · x2 + x0 · x2 = x1 + x0 · x2 + x0 · x2 = x1 + x0 · x2 + x0 + x2 .6. 2001). Zadatak 2. te formule treba pojednostaviti i nacrtati pripadne sklopove.6. Uputa. ali normalne forme moramo konstruirati po stupcima (tj. jednu za f1 . Na kraju.6. I ovaj zadatak sadrˇi 7 podzadataka (tj.4. 11. Pojednostavite koliko god je mogu´e formulu raˇuna sudova: c c f = a · b + a · b + a · b · c + a · c · b. za svaki x = (x2 x1 x0 )2 popuniti s nulama i jedinicama stupce f1 − f7 ovisno o tome koja dioda svjetli za prikaz broja x). ˇto znaˇi da ´e tablica istinitosti sadrˇavati 24 = 16 s c c z redaka.2. za heksadecimalne brojeve od 0 do (F )16 ). jednu za f2 .2.

y i z. Racun sudova Rjeˇenje. 2001).6. kreiranjem tablice istinitosti. x1 i x2 . z i izlazom f zadan je pomo´u sheme: c f x y z . Dodatno. Logiˇki sklop s tri c c ulaza x.6. 2002). c s z Zadatak 2. f = a · b · c. potrebno je s c paziti kako je uvjet zadan.6 (Pismeni ispit iz “Uvoda u raˇunarstvo”. ono vam ne´e donijeti dodatne bodove. a 0 inaˇe. a 0 inaˇe. z z c c Ako se ne traˇi pojednostavljivanje formule. onda treba jasno naznaˇiti o kakvoj je supstituciji rijeˇ (npr. c c Nije greˇka. te izlazom f koji treba biti 1 ako je broj (xyz)2 prost. Formula raˇuna c c sudova f sadrˇi varijable x. u prethodnom zadatku treba paziti da je prost broj (xyz)2 . x1 = b i sl). Ako se s s s z ne traˇi crtanje sklopa.7 (Pismeni ispit iz “Uvoda u raˇunarstvo”. Ako postoji potreba za izmjenom naziva varijabli. 11. Napiˇite formulu c s raˇuna sudova koja se sastoji od varijabli x0 . Na primjer. pa ´ete izgubiti poneˇto bodova.6. Konaˇno rjeˇenje je s c c s f = x · y + x · z. nego ´ete samo izgubiti vrijeme. s recimo. 7. Obavezno minimizirajte sklop! c Uputa. Zadatak rjeˇavamo klasiˇno. 2001). x1 i x2 .1 (Ceste greˇke). Napiˇite f tako da sadrˇi samo operatore I i NE.8 (Pismeni ispit iz “Uvoda u raˇunarstvo”. onda za crteˇ ne´ete dobiti bodove. y. Obavezno pojednostavite formulu! c Zadatak 2. Daz c paˇe. a c 0 inaˇe. x0 = a. 2002). 4. a ne (zyx)2 . 6. ˇ Napomena 2. konaˇni rezultat ´e biti pogreˇan. c s c c s c s Zadatak 2. a. Na primjer. 10.5 (Pismeni ispit iz “Uvoda u raˇunarstvo”. Kod opisnih zadataka u raˇunu sudova. Formula poprima vrijednost 1 ako c je broj x = (x2 x1 x0 )2 nultoˇka funkcije c f (x) = x3 − x2 − 4x + 4. y i z. ali je nepotrebno: nemojte rjeˇavati ono ˇto se u zadatku ne traˇi. 7.6. te poprima vrijednost 1 ako su barem dvije od varijabli z isitinite. Konstruirajte c logiˇki sklop s tri ulaza x.6. b i c). 22. onda i postupak i rjeˇenje trebaju biti s tim varijablama (a ne. poˇtujte nazive varijabli iz zadatka. ako pogrijeˇite. s Zadatak 2. ako je zadatrak zadan s s varijablama x0 . 18.36 ˇ 2.

te izlazom f koji treba c biti 1 ako je broj x = (x2 x1 x0 )2 nultoˇka polinoma c p(x) = x3 − 3x2 − 6x + 8.9. a 0 inaˇe. potrebno je prvo iz sklopa rekonstruirati izraz f . a 0 inaˇe. Dodatni zadaci 37 Sastavite ekvivalentan logiˇki sklop koriste´i samo jedna NE-vrata. disjunkcije i konjukcije): f = x · y · z + x · z = (x · y + x) · z = (x + y) · z. Obavezno minimizirajte sklop! c .2. x1 i x2 . paze´i na ispunjavanje uvjeta zadatka (tj. Treba joˇ samo nacrtati sklop koji odgovara tako pojednostavljenom izrazu f : s x y z f Zadatak 2.10. uz upotrebu z c po jednog od operatora negacije. Konstruirajte logiˇki sklop s tri ulaza x0 .6. te izlazom f c c koji treba biti 1 ako se broj x = (x3 x2 x1 x0 )2 moˇe prikazati kao suma barem dva uzastopna z prirodna broja.6. Obavezno minimizirajte sklop! c Zadatak 2. x2 i x3 . ˇto s s s radimo kao na priloˇenoj slici: z x·z x y z x y x·y f =x·y+x·y·z x·y·z Sada moˇemo pojednostaviti izraz. Da bismo rijeˇili zadatak. x1 . Konstruirajte logiˇki sklop s ˇetiri ulaza x0 . Rjeˇenje. jedna ILI-vrata i jedna c c I-vrata.6.

Racun sudova .38 ˇ 2.

jer se stvarni kompleksniji modeli ne razlikuju suˇtinski. Prikazani uredaj je jednostavan. za vinski podrum idealnih c z c z z 70%. uredaj ´e prije´i u stanje “odrˇavanje” u kojem samo prati temperaturu. U ovom poglavc c z lju osvrnut ´emo se na konaˇne automate i regularne jezike.1 Konaˇni automati c Pogledajmo kako bismo opisali ponaˇanje klima-uredaja specijaliziranog za vinske podrus me. Kao ˇto je poznato. mikrovalnih pe´nica i sl).Poglavlje 3 Konaˇni automati i regularni izrazi c Pri matematiˇkom modeliranju raˇunala moˇemo koristiti razne modele. a c proˇla oˇitana temperatura je viˇa od upravo oˇitane (dakle. c s z Pretpostavljamo da uredaj zna hladiti i grijati. dizala. Sliˇno i za c c c c visoke temperature i hladenje.2◦ C. Ako je uredaj ve´ bio u stanju “slabo grijanje”. prostor se i dalje hladi. idealna temperatura za ˇuvanje vina otprilike 12. oboje s dvije raspoloˇive snage (“slabo” i “jako”). Konaˇni automati su posebno korisni za modeliranje raˇunala s vrlo malo memorije c c (poput automatskih vrata. s z z Pri tome ne smije prenaglo mijenjati temperaturu.2◦ C. no pokazuje ˇto konaˇni automati rade: u memos c riji pamte vrlo ograniˇenu koliˇinu podataka (u opisanom primjeru je to jedno od pet c c 39 . z Sliˇno bi radio i ovlaˇivaˇ zraka koji bi drˇao vlaˇnost na. s c c z c Uredaj zapoˇinje rad u stanju “odrˇavanje”. te pomo´u senzora u pravilnim vremenskim intervalima oˇitava temperaturu zraka u prostoriji. te pokuˇava cijelo vrijeme odrˇavati temperaturu prostorije na ˇeljenih 12. s naglaskom na regularne c c izraze koji su ˇesto dostupno (i izuzetno korisno!) pomagalo u naprednijim tekst editoric ma. te ju usporeduje sa zadanom c vrijednoˇ´u. ˇto znaˇi da je “jaˇe” hladenje ili zas c c grijavanje prostora poˇeljno samo ako “slabije” nije dostatno (dakle. stroj prelazi u stanje “jakog grijanja”. c 3. ˇto s c s c s znaˇi da “slabo grijanje” nije dostatno). Razmotrit s c ´emo pojednostavljeni model. uredaj ne´e “ˇuriti” z c z i uvijek raditi ˇto jaˇe). uredaj ulazi u stanje “slabo sc c z z grijanje” u kojem zagrijava prostor. Ako je oˇitana temperatura niˇa od ˇeljene. Kad je postignuta idealna temperatura.

c Iz prikazanog primjera je jasno ˇto je skup stanja (“odrˇavanje”.1. q0 . c • δ : Q × Σ → Q funkcija prijelaza. U takvim prilikama su prikladniji tabliˇni i funkcijski prikaz.1). U ovisnosti o tim podacima (i upam´enima i primljenima). Abeceda se na prvi pogled c z ˇini velika (skup svih mogu´ih oˇitanja temperature). no to moˇes c z mo smatrati i ulaznim podatkom (npr. Uz stanja se mogu vezati neke akcije koje ´e obaviti neki komad z c c hardwarea (u naˇem primjeru sam klima uredaj kojim upravljamo). “prehladno i hladnije nego maloprije”.1 (Konaˇni automat). Sliku c z c c 3. uz stanje. pamtimo i proˇlo oˇitanje temperature. no to ˇesto ispada nepregledno (v. Konaˇni automat je uredena petorka (Q. te po dva “grijanja” s z i “hladenja”). senzor temperature moˇe pamtiti zadnju oˇitanu z c vrijednost. c • Σ konaˇan skup koji zovemo abeceda. kao i koje je stanje poˇetno (“odrˇavanje”). Σ. s . “prehladno”. c c pri ˇemu je c • Q konaˇan skup stanja. te slati nju i aktualnu vrijednost). no zapravo je dovoljno da senzori c c c ˇalju podatke “idealna temperatura”. δ. no njih ovdje ne´emo c c detaljnije obradivati. c c Definicija 3. uredaj mijenja stanje c ili zadrˇava postoje´e. idealno pretoplo prehladno pretoplo idealno prehladno idealno prehladno pretoplo pretoplo joˇ s hladnije hladenje joˇ s toplije odrˇavanje z grijanje prehladno joˇ s hladnije pretoplo joˇ s toplije idealno jako grijanje prehladno jako hladenje idealno Slika 3. • q0 ∈ Q poˇetno stanje. Konaˇne automate moˇemo prikazati grafiˇki. F ).1: Konaˇni automat za upravljanje klima-uredajem c Pogledajmo formalnu definiciju matematiˇkog modela konaˇnog automata. te prima nekakve ulazne podatke (u opisanom primjeru: oˇitanja senc zora). te c • F ⊆ Q skup konaˇnih stanja.40 ˇ 3. s U samom primjeru. Konacni automati i regularni izrazi ponudenih stanja).

• Zvjezdica: A∗ := {x1 x2 . stroj bi pomo´u stanja morao pamtiti s c je li proˇitao slovo “e”. inaˇe s nije. c z 3. Definicija 3. δ(“hladenje”. te mijenja stanja u kojima se nalazi.3. proglasili bismo za zavrˇno stanje. kad bismo ˇeljeli prepoznati sve rijeˇi koje c z c imaju barem jedno slovo “e”. osnovna ideja konaˇnog automata je da “ˇita” c c nekakve podatke. konaˇni automat moˇe prihva´ati i pojedine rijeˇi.2.2. te “pretoplo i toplije nego prije”. rijeˇ je kakvu traˇimo. Da bismo mogli precizno definirati regularne izraze. “pretoplo i toplije nego prije”) = “jako hladenje”. “pretoplo”) = “hladenje”. Na primjer. Za taj jezik kaˇemo da ga automat M prihva´a ili prepoznaje. . c z Konaˇni automat moˇe prihva´ati viˇe rijeˇi. no uvijek prepoznaje samo jedan jezik.2 Regularni izrazi Kako smo vidjeli u prethodnom poglavlju. Ako je.2 (Regularne operacije).1 (Regularni jezik). Primijetite da zvjezdica producira beskonaˇni jezik koji sadrˇi i praznu rijeˇ! Pomo´u c z c c regularnih operacija prirodno definiramo regularne izraze. jasno je kako je definirana funkcija δ. c s Stroj bi tako ˇitao zadanu rijeˇ i “preskakao” iz stanja u stanje. potrebne su nam prvo operacije na regularnim jezicima. Izrazi kojima opisujemo regularne jezike zovu se regularni izrazi. Kad “potroˇimo” sva c c s c z c slova. Kaˇemo da je jezik regularan ako postoji konaˇni z c automat koji ga prepoznaje. Regularni izrazi 41 “pretoplo”. Konaˇno stanje ovdje nije zadano jer ˇelimo da stroj radi unedogled.2. te bi zadnja dva slova bila “c” i “a”. Nakon ˇto smo popisali stanja i ˇlanove s c abecede. Npr. • Konkatenacija (spajanje): A ◦ B := {xy : x ∈ A i x ∈ B}. δ(“hladenje”. Za njih definiramo sljede´e regularne operacije: c • Unija: A ∪ B := {x : x ∈ A ili x ∈ B}. Neka su A i B dva regularna jezika. xk : k 0 i svaki xi ∈ A}. te – ako je – koja su zadnja dva slova. Primijetimo da je takav model idealan za prepoznavanje nekakvih rijeˇi. c z c s c Definicija 3. provjerili bismo je li stroj u zavrˇnom stanju. te zavrˇavaju na “ca”. Kao z c ˇto smo vidjeli. pa – da bismo izbjegli s c z c c zabune – za jezike obiˇno kaˇemo da ih “prepoznaje”. Stanje u kojem bi “e” bilo c proˇitano. Skup A svih rijeˇi koje prihva´a konaˇni automat M zovemo jezik automata M . u c c c oznaci L(M ) = A. . .

te se koristi u znanstvenoj i struˇnoj c c literaturi. • (R)+ = R(R)∗ (izraz R ponovljen jednom ili viˇe puta). • RS = R ◦ S (konkatenacija izraza R i S). “Introduction to the theory of computation”.1.} = (R){n}(R)* ≡ izraz R ponovljen barem n puta. odabrani simboli su nespretni za upotrebu na raˇunalu (npr. c • (R1 ◦ R2 ). c • (R){n. pri ˇemu su R1 i R2 regularni izrazi. • (R1 ∪ R2 ). u tekst editoric ma i programskim jezicima).2. c c Matematiˇka teorija je puno ˇira. pri ˇemu su R1 i R2 regularni izrazi. Kaˇemo da je R regularni izraz ako je R jedno od z navedenog: • a ∈ Σ (jedan znak zadanog alfabeta). c Napomena 3. c c • ∅ (prazni jezik). s • (R)? = (|R) (prazna rijeˇ ili izraz R). c c • $ ≡ kraj rijeˇi. rijeˇ duljine nula). Zainteresirani ˇitatelji s c c mogu viˇe prona´i u knjizi M. ili c ∗ • (R1 ).2.2. no u nastavku ´emo se baviti samo regularnim izrazima c s c jer su oni direktno primjenjivi u svakodnevnom koriˇtenju raˇunala. c • (R){n} ≡ izraz R ponovljen toˇno n puta. pri ˇemu je R1 regularni izraz. • ε (prazna rijeˇ.m} ≡ izraz R ponovljen barem n. Razlikujte ε (prazna rijeˇ. tj. s c Iako je prikazana definicija matematiˇki korektna.4. odnosno jezik koji ne sadrˇi niti jednu rijeˇ)! z c z c Regularni izrazi samo su dio priˇe o konaˇnim automatima i regularnim izrazima. Sipsera. a najviˇe m puta. odnosno – u terminima jezika – jezik koji c sadrˇi jednu (praznu) rijeˇ) i ∅ (prazni jezik. s • (R){n.3 (Regularni izraz). Konacni automati i regularni izrazi Definicija 3. Oznake koriˇtene za zapis regularnih izraza: s • R|S = R ∪ S (unija izraza R i S). Zbog toga koristimo prilagodene oznake (zajedniˇke ve´ini c c implementacija regularnih izraza). Definicija 3. • ^ ≡ poˇetak rijeˇi. c . • (R)* = (R)∗ .42 ˇ 3.

tj. z z c kad ˇelimo osigurati da se pronadena rijeˇ nalazi na poˇetku ili kraju retka. dok \. Regularni izrazi 43 • [znakovi] ≡ toˇno jedan od znakova pobrojanih unutar zagrada. izraz ab+ prihvatit ´e rijeˇi “ab”. l. j. c c Izraze [znakovi] i [^znakovi] ponekad moˇemo kra´e zapisati koriˇtenjem raspona. • \S. h. Zbog toga. Na primjer. c c Oznaka . g. n ∈ N ≡ n-ta grupacija (tj. z c s Tako [ag-m] oznaˇava bilo koji znak iz skupa {a. \[ prihva´a uglatu zagradu. U nekim verzijama se koriste c oznake \< i \> za poˇetak. koristimo z c c znakove ^ i $. obiˇno liniju po liniju teksta. Dakle. c c . ≡ bilo koji znak. no mi ´emo ukljuˇiti i skok u noc c c c vi redak. kao c c niti “a”). + i {·} djeluju samo na prethodni znak ili z zagradu. c c • \s ≡ jedan razmak. (ali NE i “abab”. jezik koji izraz a(bc|def)g prepoznaje ima toˇno dvije rijeˇi (“abcg” i “adefg”). tj. z z c izraz ([ab])c\1 prihva´a rijeˇi “aca” i “bcb” (ali NE i “acb”). a ne bilo koji c c c znak. \D i \W ≡ suprotno od \s. proizaˇli iz same upotrebe regularnih s izraza. \d i \w. prihva´a toˇku. k. i. c • [^znakovi] ≡ toˇno jedan znak. odnosno kraj rijeˇi. \\ prihva´a “naopaku kosu crtu” \). c Vaˇno je naglasiti da kvantifikatori *. jako ˇesto ne ukljuˇuje skok u novi redak. operator | djeluje na najˇire susjedne podizraze. jer definicija skoka u novi red takoder ovisi o dodatnim okolnostima (npr. respektivno. S druge strane. “abbbbb” i sl. sliˇno. Oznaka \n nam sluˇi kada se ˇelimo osigurati da se neki dio rijeˇi ponavlja. on traˇi neku rijeˇ (op´enito govore´i. • \d ≡ jedna znamenka. m}. ono ˇemu odgovara n-ta zagrada). tabulator ili neki drugi znak za razmak. u matematiˇkoj teoriji raˇunalstva regularni izraz provjerava cijele ric c jeˇi. U prethodnoj definiciji dodani su novi simboli. razliˇit od svih znakova pobrojanih unutar zagrada. c • \w ≡ jedan alfanumeriˇki znak (slovo ili znamenka) ili _. U praktiˇnim primjenama. c NE predstavlja poˇetak izraza [znakovi]. ˇto znaˇi da je s s c L(a(bc|def)g) = {“abcg”. • \b ≡ rub rijeˇi. c • \x ≡ x ako je x neka od specijalnih oznaka (npr.3. “adefg”}. mjesto izmedu \w i \W (nije znak!). tj.2. “rijeˇ” u kontekstu c c z c c c c regularnih izraza moˇe sadrˇavati i razmake!). Konkretno. • \n. c c • . o operativnom sustavu i programu u kojem koristimo regularni izraz).

regular-expressions. Ovdje smo opisali podskup PCRE-a (zapravo ERE s dodacima koje podrˇava ve´ina programa s podrˇkom za regularne izraze). dok je kvantifikator za “jedan ili viˇe izraza” c s specificiran oznakom \+.vim. z Besplatna komandnolinijska verzija za Windows nalazi se na http://gnuwin32. • OpenOffice.org/software/emacs/. pomo´u funkcija u biblioteci regex. no manje raˇireni su Perl2 Compatibile Regular Expression (PCRE). c • (g)vim – editor teksta. a postoje i “jaˇe” (ali komercijalne) verzije.php.net/uk/download.44 ˇ 3. a opisana znaˇenja im daju tek ako ispred dodamo \. Portable Operating System Interface for uniX Perl je. sluˇbeno.net/packages/grep. c oznaka + jednostavno oznaˇava znak “plus”. z http://www. Dostupno na http://download.org/. Samo za Windows. c Neke implementacije regularnih izraza prepoznaju neke od specijalnih znakova doslovno. a moˇete ga “skinuti” na z http://notepad-plus. akronim od Practical Extraction and Report Language. Python.com/en/. Regularni izrazi dostupni su i u GNU C-u. kaˇe da “Perl” znaˇi “Pathologically Eclectic Rubbish c z c Lister”. opisane ili sliˇne regularne izraze podrˇavaju i neki SQL sustavi. Dostupan na http://www. poput Delphija (v. autora Perla. na http://www. • emacs – editor teksta. Walla.org/download.htm. z 2 1 .sourceforge. • PSPad – editor teksta. c z te jezici Perl.php. Toˇnu sintaksu regularnih izraza provjerite u uputama za program ili jezik u kojem c koristite regularne izraze.gnu.html). Humoristiˇna verzija L.info/delphi. u gvim-u. s Postoji samo za Windows. Ruby. Uz pobrojane programe.NET jezici itd. Najnapredniji. Dostupan na http://www. . Najraˇireniji su c s s POSIX1 Basic (BRE) i POSIX Extended (ERE).org – besplatan uredski paket. z c s Neki od programa i jezika koji podrˇavaju takve ili sliˇne regularne izraze su: z c • (e)grep – program za traˇenje teksta u datotekama. PHP3 . a postoje i dodaci koji regularne izraze dodaju i jezicima koji ih a priori ne podrˇavaju.. 3 PHP podrˇava i ERE i PCRE. iako je naziv “Perl” nastao z prije.openoffice.pspad.sourceforge. JavaScript. Konacni automati i regularni izrazi Postoji nekoliko standarda za zapis regularnih izraza na raˇunalima. preko dva odvojena seta funkcija. • Notepad++ – editor teksta sa skromnom podrˇkom za regularne izraze. Na primjer.

Primijetite i da. traˇimo c z ^\s+ te zadajemo editoru da pronadeno zamijeni s praznim stringom.2. Ovdje ´emo uzeti da su to c s s c svi razmaci na poˇetu i na kraju linija. Ova razlika je bitna kad se regularni c c s c izraz koristi za zamjene dijelova teksta. c z zbog pohlepnosti kvantifikatora.2.”. ove dvije stvai moˇemo zamijeniti jednim z z traˇenjem z ^\s*(. izraz [qrts].*\S)\s*$ prilikom kojeg ´emo pronadeni tekst zamijeniti s povratnom referencom \1. potrebno je odrediti ˇto je to “viˇak razmaka”. Analogno. dok ´e c c posljednji znak “a” odgovarati podizrazu “. “lijenim” prepoznavanjem. standarde ne smijete mijeˇati.1. jer nikad ne bi brisao razmake na kraju linije. no c ako koristite pravila razliˇita od ovdje opisanih obavezno napiˇite koji standard koristic s s z te! Takoder. c opisani izraz ne´e obrisati linije koje sadrˇe samo razmake (zbog \S). izraz bi prepoznao “skoˇi”.2. c c s c c Da je rijeˇ bila “skoˇimˇ”.2. Ako ˇelimo “poˇistiti” i takve linije. Ako neka linija nema razmake na poˇetku/kraju. z Kvantifikatori *. Na ispitu smijete koristiti bilo koji od uobiˇajenih standarda.*i ´e u tekstu “skoˇimiˇ” prepoznati rijeˇ “skoˇimi”. c prikazani izrazi ju ne´e prepoznati. ako linija sadrˇi samo n znakova “a” (i niˇta viˇe nakon tih a-ova) za neki n > 0. Opisano ponaˇanje moˇe se u PCRE (ili njihovim s z dijelovima) zamijeniti tzv. Kako to napraviti u editoru s koji podrˇava regularne izraze? z Za poˇetak.2. pa se zamjena za njih ne´e izvrˇiti. te oni kojih ima dva ili viˇe za redom. onda ´e podizrazu a* odgovarati prvih n − 1 znakova “a”. c Ako editor podrˇava povratne reference. Pri tome. nego se morate drˇati jednog standarda! Napomena 3. “Pohlepnost” algoritma “ide” u smjeru slijeva na desno. Povratne reference (\1 i sl) NISU regularni izrazi u matematiˇkom c smislu (tj. c c “pokupiti” sve uzastopne znakove “a” (podziraz a*) na poˇetku linije i prvi znak razliˇit c c z s s od “a” (podizraz . baˇ kao ˇto bismo c c s s s i oˇekivali. Regularni izrazi 45 Napomena 3. ˇto znaˇi da ´e “pokupiti” najve´i mogu´i s c c c c dio teksta.*)\s*$ ne bi bio dobar. izraz ^\s*(. + i {·} rade “pohlepno”. ne opisuju regularne jezike). U tekstu je potrebno urediti “viˇak” razmaka. Primjer 3. Na primjer. c s Da bismo maknuli sve razmake na poˇecima svih linija.). za razmake na kraju redaka traˇimo z \s+$ i opet zamjenjujemo s praznim stringom. traˇimo z c z . To znaˇi da ´e izraz ^a*.3. ali su zbog praktiˇnosti ˇest dio implementiranih c c regularnih izraza u raznim traˇilicama.3. No.

Osnovno prepoznavanje je lagano: \s-\s ili . a c s z ne i druge “nevidljive” znakove. Dakle. c Naravno. kad znamo ispravno traˇiti. iznimka su formatirane datoteke kad zaista ˇelimo prepoznavati baˇ razmake. Konacni automati i regularni izrazi ^\s*(.} ili \s\s+ (ako editor ne podrˇava {·}) z c z te pronadeni tekst zamjenjujemo s obiˇnim razmakom ( ). a ne jedan toˇno odredeni znak. barem jedan znak “y”.”. no to optere´uje editor s puno nepotrebnih zamjena (zamjena jednog razmaka s tim istim c razmakom). op´enito je bolje koristiti \s (v.” (razmak. Mogli smo traˇiti i samo \s+. prvo rjeˇenje je bolje. Neke slike i filmovi nemaju opisa. traˇimo dva ili viˇe razmaka: c z s \s{2. s z s c Naravno. U zadacima c ´emo se baviti samo regularnim izrazima. a lagane su za napraviti.. koriˇtenje \s kao onoga s ˇime zamjenjujemo pronadeni tekst je besmisleno. z s ali ne i ostale znakove koji samo liˇe na razmak. Napiˇite regularni izraz koji prepoznaje sve opisane separatore iza kojih nema opisa s (kako biste ih u nekom editoru obrisali.$ Op´enito.2. Napiˇite regularni izraz koji prepoznaje sve linije teksta koje sadrˇe s z 1. U svakoj liniji datoteke nalazi se opis jedne slike ili filma i to tako da je navedeno ime datoteke (bez ekstenzije). Iako razmak moˇemo oznaˇavati kao . dakle i one koji iza sebe imaju opis. s te opis. Zadatak 3. no ne i time ˇime ih treba zamjenjivati. ovakav izraz prepoznat s ´e SVA pojavljivanja separatora “ . jer drugo prejudicira da nam traˇimo samo razmake.2. zatim niz znakova koji zavrˇava ne-razmakom ili prazan niz znaz s kova (u zagradi).46 ˇ 3. s c jer \s znaˇi “razmak ili tabulator ili.*\S|)\s*$ Dakle. z Zadatak 3. .) unutar teksta ˇelimo zamijeniti s po s c z jednim obiˇnim razmakom. ”. pa da u tim linijama ostanu samo nazivi datoteka). jer c c zamjene ovise o konkretnim primjenama. te na kraju razmake do kraja linije.2. Traˇeni c z regularni izraz ima samo jedan znak viˇe – onaj za oznaˇavanje kraja retka: s c \s-\s$ ili .1. takva zamjena moˇe biti korisna ako ˇelimo i pojedinaˇne tabulatore z z c (ili druge “nevidljive” znakove) zamijeniti razmacima. minus i joˇ jedan razmak). . prethodni z c c primjer) jer ono ˇto u tekstu izgleda kao razmak moˇe biti tabulator ili neˇto sliˇno. c c U primjeru smo pokazali jednu praktiˇnu primjenu regularnih izraza. Viˇestruke razmake (ukljuˇivo i tabulatore i sl. Ipak. Rjeˇenje. traˇimo razmake. U datoteci su pohranjeni opisi fotografija i filmova napravljenih digitalnim fotoaparatom. . No. zatim “ .

3. pozitivne binarne brojeve. Napiˇite regularni izraz koji u tekstu prepoznaje s 1. ispravno zapisane binarne brojeve s barem 3 znamenke.*y.2. Sam pronalazak linije je jednostavan: y (regularni izraz koji ´e prona´i znak “y”). ispravno zapisane binarne brojeve (bez vode´ih nula. njih ´e pokupiti prvi podizraz . Regularni izrazi 47 2. s 1. Drugim ric jeˇima. 2. pa tako i znaku “a”. Na osnovu prethodnog podzadatka slaˇemo ovo rjeˇenje. toˇno jedan znak “y”. ali POGRESNO rjeˇenje kod ovakvih zadataka je s ^. c Rjeˇenje.3. ovakav izraz ne´e prepoznati cijelu liniju nego samo pojedini znak (ˇto ´e stvoriti c s c neˇeljene posljedice kod izmjene teksta). moramo zadati izraz koji z prepoznaje sve znakove od poˇetka do kraja linije: c ^. c c No.*)* jednostavno c z moˇe biti prazna rijeˇ.*(a[bc]. ispravno zapisane binarne brojeve s toˇno 3 znamenke.* (zbog “pos c hlepnog” traˇenja). Poˇto ˇelimo provjeravati cijele linije. c 5.2. . z 2. nego i gdje ne´e: c ^[^a]*(a[bc][^a]*)*$ Zadatak 3. s ˇ ˇ Cesto.*$ Ako u liniji postoji viˇe znakova “y”.* moˇe odgovarati cijeloj liniji (bilo kojoj!).2. podizraz .4.*)*$ Problem ovdje je da toˇka odgovara bilo kojem znaku. pa (a[bc]. sa ili bez negativnog predznaka). c 3. s z Rjeˇenje. Poˇto ˇelimo toˇno jedan z s s z c znak “y” (koji ve´ imamo). moramo se osigurati da niti jedan znak koji podizrazi c . c 4. Dakle: ^[^y]*y[^y]*$ Zadatak 3. Ispravno je osigurati ne samo gdje ´e se “a” pojaviti (ispred “b” z c c ili “c”). Umjesto toga. ispravno zapisane pozitivne binarne brojeve (bez vode´ih nula). izraz moramo omediti znakovima ^ i $. Napiˇite regularni izraz koji prepoznaje sve linije teksta u kojima se s neposredno iza svakog znaka “a” nalazi znak “b” ili znak “c”.* prihvate ne bude “y”.

prepoznata rijeˇ mora zapoˇeti sa z c c c znamenkom koja nije nula. Ako ˇelimo osigurati da nema vode´ih nula. “na prvu z c z loptu”. s Rjeˇenje. izraz bi glasio z -?(1[01]*|0) 4. s 1. pa lijevo i desno od nje smiju biti i prazne rijeˇi. pri ˇemu ˇitani niz znakova mora c c sadrˇavati barem jedan znak (tj.). c s 3. Naime. Ovdje kvantifikator * zamjenjujemo kvantifikatorom {·}. traˇeni izraz sliˇan je prethodnom. ispravno zapisane binarne brojeve s barem 3 i najviˇe 5 znamenaka. Ovdje smo tu znamenku izdvojili (“1” u sredini). Pri tome treba uzeti u obzir da je jedna znamenka ona prva jedinica. [01]+ No. 1). pa treba prepoznati i broj 0 (jedini binarni broj koji ne poˇinje c znamenkom 1). imamo izraz c . Konacni automati i regularni izrazi 6. traˇeni izraz je z -?1[01]*|0 Da smo kao ispravan broj ˇeljeli prihvatiti i −0. Konaˇno. s time da z c znak “1” mora biti na poˇetku: c 1[01]* Primijetite: izraz 1[01]+ bi odgovarao pozitivnim binarnim brojevima strogo ve´im c od 1 (poˇinju sa znamenkom 1 i imaju joˇ barem jednu znamenku iza). Pozitivni binarni brojevi su nizovi nula i jedinica. pa ostatak broja treba imati dvije (a ne tri) znamenke.48 ˇ 3. jer ´e kao pozitivni broj prepoznati i text koji sadrˇi c c z samo nule (npr. “0000” i sl. pa je traˇeni izraz. ovo nije u potpunosti toˇno. Da bismo prepoznali minus koji se moˇe pojaviti najviˇe jednom (ali se i ne mora z s pojaviti). prazna rijeˇ nije broj). Dakle. viˇe ne ograniˇavamo brojec s c ve na pozitivne. jer joˇ ne inzistiramo na “ispravnom” zapisu) bude razliˇita od z c s c nule (tj. upotrijebit ´emo kvantifikator ?. Dakle. [01]*1[01]* Primijetite da smo kvantifikator + zamijenili kvantifikatorom *. “0”. Nama treba da barem jedna znamenka (za sada ne nuˇno vode´a. Dodatno. + nam je trebao osigurati da imamo barem jednu znamenku. c 2.

Napiˇite regularni izraz koji prepoznaje ispravno napisane e-mail adrese. Novi izraz je s -?1[01]{2. c s Kvantifikator {·} nije mogu´e koristiti u varijanti {.n} koristimo {0. Najˇeˇ´i naˇin s c z c sc c vidjet ´emo kasnije._%-]+@([a-z0-9-]+\.2. c Zadatak 3. tj.[^@. Parni brojevi su oni koji zavrˇavaju znamenkom 0. je c [a-z0-9. Uputa. u rjeˇenjima Zadatka 3. ovisi donekle o tome ˇto toˇno ˇelimo.·}.]+(\. Kako prepoznati c c c samo brojeve odvojene od teksta.6. Novi izraz je -?1[01]{2. ako ˇelimo re´i “najviˇe n ponavljanja. Tu znamenku s izdvojite. 2. Rijeˇite prethodni zadatak (svih ˇest varijanti) prepoznavaju´i s s c a) oktalne brojeve. no pripazite da ispravno prepoznate i jednoznamenkaste brojeve (jer je prva znamenka ve´ izdvojena). koji uzima u obzir i koji su znakovi gdje dozvoljeni. c Zadatak 3. te barem jednu toˇku: c [^@]+@[^@. Osnovno na ˇto ovdje ˇelimo paziti je da niz znakova mora sadrˇavati toˇno s s z z c jedan znak “@”. s Rjeˇenje.} 6.5.4} .7.2. 4. Tako ´e.3. npr.)+[a-z]{2.2. Ako kvantifikator {·} zamijenimo s {·. prva vrijednost uvijek mora c biti zadana. To nije problem: jednostavno. na primjer. umjesto z c s nepostoje´eg {.4} U rjeˇenjima prethodnog zadatka prepoznajemo binarne brojeve bez obzira na to ˇto se s s nalazi oko njih. neˇijeg korisniˇkog imena). Ako kvantifikatoru {·} dodamo zarez. mijenjamo mu znaˇenje iz “toˇno koliko piˇe” c c s u “barem koliko piˇe”. mijenjamo mu znaˇenje iz “toˇno koliko c c piˇe” u “barem koliko je prvi parametar i najviˇe koliko je drugi” (opet smanjujemo s s oba broja za jedan jer jednu znamenku provjeravamo prije [·]).2. u tekstu “Pero101x” podstring “101” biti prepoznat c kao binarni broj. b) heksadecimalne brojeve i c) parne dekadske brojeve.n}.]+)+ Toˇan izraz. Regularni izrazi 49 -?1[01]{2} 5.·}. iako je samo dio rijeˇi (npr. 6 ili 8.

s z c piˇemo s (^|\s)([A-Za-z]+)(\s|$) Dakle. kad ispred ili iza nje nema razmaka. dok prva i tre´a sluˇe za ispravno grupic c z ranje podizraza oko operatora |. Poˇto ˇelimo i takve rijeˇi prepoznati. a uz izraz treba naglasiti i koja grupa c c zagrada daje samu rijeˇ (jer nju zadatak traˇi). c Zadatak 3. tj. c z 1. Sliˇno kao kod prepoznavanja brojeva. c c 2. Bilo koje s c malo slovo prepoznajemo podizrazom [a-z]. ispred rijeˇi moˇe biti poˇetak retka (ovo nije znak!) ili razmak. c z Rijeˇ odgovara drugoj grupaciji (zagradi). Zato s z c ´emo samo rijeˇ dodatno grupirati u zagrade. s c z Prvo prikazujemo rjeˇenje u kojem ´emo traˇiti odgovaraju´i raspored razmaka u okos c z c lini traˇenih rijeˇi. Ipak.2. c Ovdje treba uzeti u obzir da se rijeˇ moˇe nalaziti i na poˇetku ili na kraju retka u c z c tekstu. bilo kakvu rijeˇ (u klasiˇnom smislu. ostala moraju biti mala). nenaglaˇenu rijeˇ (prvo slovo moˇe biti malo ili veliko. To se radi ovisno o programu/jeziku.7. U svim podzadacima moramo prepoznati “viˇak”. . primijetite u podizrazu [a-z0-9-] zavrˇni s minus: on oznaˇava znak “minus”. a ne raspon (jer nema znak do kojeg bi raspon trebao c i´i). c z Da bismo u potpunosti ispravno prepoznavali poˇetak reˇenice. tekst je potrebno tretirati c c kao cjelinu (a ne redak po redak). pa ovdje ne´emo c razmatrati. Rijeˇ omedena razmacima: c \s([A-Za-z]+)\s Rijeˇ odgovara prvoj grupaciji (zagradi). bliˇu okolinu rijeˇi. a nakon c z c rijeˇi moˇe biti razmak ili kraj retka (koji takoder nije znak). Konacni automati i regularni izrazi no to nije potrebno znati na ispitu. 2. dakle niz slova omedenih razmacima). dok veliko slovo prepoznajemo podizrazom [A-Z].50 ˇ 3. Napiˇite regularni izraz koji prepoznaje s 1. Bilo koje slovo prepoznajemo podizrazom [a-zA-Z]. z c Rjeˇenje pomo´u razmaka. treba izdvojiti prvo slovo od ostalih: c (^|\s)([A-Za-z][a-z]*)(\s|$) Rijeˇ koju traˇimo odgovara drugoj grupaciji (zagradi).

4. dok parametri u sebi ne sadrˇe uglate. c Napomena 3. u nekim izvedbama. Rijeˇ: c \b[A-Za-z]+\b ili \<[A-Za-z]+\> Poˇto \b nije znak. Zbog toga prikazani regularni izraz ne´e prepoznati da ispred rijeˇi “sadi” postoji c c razmak. c poput (g)vim-a. Napiˇite regularni izraz koji prepoznaje sve jednostavne LTEX naredbe s oblika \naredba{glavni parametar} ili \naredba[pomocni parametar]{glavni parametar} pri ˇemu treba odvojiti naredbu i parametre (u tri odvojene grupacije).2. “x”. s c c 1. z odnosno vitiˇaste zagrade. c 2. od slova “s” u c c c c “sadi”. A Zadatak 3. Naime ako imamo tekst s s z Kupus sadi ciklu onda ´e opisani regularni izrazi prepoznati svaku drugu rijeˇ. tj. nego i interpunkcijskim i sliˇnim znakovima. Opet ´emo izdvojiti prvo slovo od ostalih: c \b[A-Za-z][a-z]*\b ili \<[A-Za-z][a-z]*\> Prikazano rjeˇenje (pomo´u ruba rijeˇi) ispravno ´e prepoznati i rijeˇi koje nisu omedene s c c c c samo razmacima. s z Zadatak 3. ali mogu biti i prazni. c c prepoznavanje idu´e rijeˇi kre´e nakon ve´ prepoznatog niza znakova. jer kad prepoznamo “Kupus ”.8. “y”). \< i \>).2. Da bismo izbjegli takve probleme. Ako izraz prepoznaje “viˇak”. “w”. smatra se da cijeli s s izraz odgovara onome ˇto se u zadatku traˇi. ˇto s c c c s je upravo ono ˇto ˇelimo. Moˇete pretpostaviti c z da se naredba sastoji samo od slova (barem jednog).2.9. Zato nam ne treba grupiranje. onda ´e prikazani regularni izraz prihvatiti toˇno jednu rijeˇ. obavezno naglasite koja grupacija (ili s zagrada) odgovara rjeˇenju zadatka. koristimo rub rijeˇi \b (ili. Napiˇite regularni izraz koji prepoznaje rijeˇi koje sadrˇe nehrvatska s c z slova engleskog alfabeta (“q”. kao niti posebna provjera s z jesmo li na poˇetku ili kraju retka. Regularni izrazi 51 ´ Ovakvo rjeˇenje se NECE ponaˇati kako bismo ˇeljeli. Rjeˇenje pomo´u ruba rijeˇi. Ako takvog naglaˇavanja nema.2.3. c .

z c joˇ neke znakove). tj. To radimo dodatnim grupiranjem. Ovdje koristimo nekoliko specijalnih znakova (\. eventualno. n ≥ 1 te da niti jedan od njih ne sadrˇi z vitiˇaste zagrade. uz c s s z kvantifikator ?. nju postavljamo na prvo mjesto: s [^]. s s gp2. c Kad bi prvi znak ] zatvaro izraz. . dok ´e se glavni parametar na´i u \4. ˇto je besmisleno (postiˇe se toˇkom).5.{gpn} ili \naredba[pp]{gp1}{gp2}.] . c c c A Zadatak 3.{gpn} z pri ˇemu treba odvojiti naredbu i parametre sliˇno prethodnom zadatku... c ˇ c Sto ´e se nalaziti u \6 ako je tekst koji pretraˇujemo z Jedna \slozena{La}{TeX} naredba poˇto ´e ta grupacija prepoznati i “La” i “TeX”? s c Napomena 3. Konacni automati i regularni izrazi Rjeˇenje... {. .. Napiˇite regularni izraz koji prepoznaje sve sloˇenije LTEX naredbe s z oblika \naredba{gp1}{gp2}. . ]. c c s z c kad ˇelimo prihvatiti neki znak koji ne ukljuˇuje zatvorenu uglatu zagradu (i. c Rjeˇenje. zajedno s pripadnim vitiˇastim zagradama. c c c \3 ´e biti prazan).2. Moˇete pretposc c taviti da postoji barem jedan glavni parametar. gpn).52 ˇ 3. }) ispred kojih treba s dodati \ kako bismo prihva´ali upravo njih. tj. \\([a-zA-Z]+)(\[([^]]*)\])?\{([^}]*)\} Naredba ´e se nalaziti u \1.2.. U prethodnim zadacima vidimo relativno zbunjuju´i podizraz [^]]. s \\([a-zA-Z]+)(\[([^]]*)\])?(\{([^}]*)\})+ Sve glavne parametre ´emo “uloviti” dodatnim grupiranjem: c \\([a-zA-Z]+)(\[([^]]*)\])?((\{([^}]*)\})+) Glavni parametri bit ´e pospremljeni u \4. podizraz koji prihva´a [pomocni parametar] treba oznaˇiti kao neˇto ˇto se moˇe i ne mora pojaviti. Takoder. pomo´ni parametar (ako postoji) bit ´e u \3 (ako ne postoji. onda bi [^] znaˇilo “bilo koji znak osim niˇega”. [. kad bismo pod izraz gledali kao [^] i ] posebno..10. c Pokuˇajte u jednu grupaciju (napiˇite i koju!) “uhvatiti” sve glavne parametre (gp1. Zato. bez specijalnih znaˇenja koja inaˇe imaju c c c c u regularnim izrazima.

c Kˆdove i lokalni broj izdvojite u zasebne grupacije (i.. pa piˇemo c s [a^b] ili [ab^] ili [a-b^] Zadatak 3.11. kˆdu regije \2. pa ispred njega dodajemo \: s \b\+(\d{1.] Ako ˇelimo prihvatiti samo ^. c c c Rjeˇenje.}-?\d+)$ Zadatak 3. a ili b.2.2. izraz bi bio: ^\+(\d{1. koje sadrˇe takve brojeve i niˇta viˇe? z s s c Rjeˇenje. Napiˇite regularni izraz koji prepoznaje datume u formatu s 1. Napiˇite regularni izraz koji prepoznaje sve palindrome (rijeˇi koje se s c jednako ˇitaju slijeva i sdesna) od toˇno 5 slova.3})-(\d{1. eventuc z z alno. joˇ neki znak): s [ ].2. Regularni izrazi 53 Sliˇno. dok se lokalni z z broj telefona sastoji od znamenaka (barem tri) i najviˇe jedne crtice (koja ne smije biti na s poˇetku i kraju broja). npr. Kad bismo htjeli o z o prepoznavati linije (kako je opisano na kraju zadatka). dd. Napiˇite regularni izraz koji prepoznaje brojeve telefona u formatu s +kod1-kod2-broj gdje kod1 oznaˇava kˆd drˇave. o s s Kako biste prepoznali linije koje se sastoje samo od takvih brojeva (po jedan u svakoj liniji).mm. Kodovi drˇave i grada/regije sadrˇe izmedu jedne i tri znamenke.}-?\d+)\b Kˆdu drˇave odgovara \1. ako ˇelimo prihvatiti neki znak koji moˇe biti zatvorena uglata zagrada (i. mjesec yyyy.3})-(\d+-?\d{2.. a broj je lokalni broj c o z c o telefona.2.3. naravno. napiˇite ˇto je u kojoj). Ovdje imamo znak + koji ima specijalno znaˇenje.}|\d{2. te rubovi rijeˇi: s \b([A-Za-z])([A-Za-z])[A-Za-z]\2\1\b Zadatak 3.3})-(\d+-?\d{2. 2. piˇemo z s \^ Ako ˇelimo prihvatiti ^ i joˇ neke znakove. tj. Ovdje nam trebaju povratne reference. kod2 oznaˇava kˆd grada/regije. dd.13. a lokalnom broju telefona \3.}|\d{2.12. znak ^ ne smijemo staviti na z s poˇetak (da ne ispadne negacija). .3})-(\d{1.yyyy.

mm > 12.srt datotekama (SubRip Text. U prethodnom zadatku sljede´e rjeˇenje bilo bi KRIVO: c s ^(\d+:[0-5]?\d:[0-5]?\d. a ms milisekunde (nenegativni cijeli brojevi. Ne morate paziti koliko c c koji mjesec ima dana.2. s tim da su milisekudne uvijek zapisane kao troznamenkasti broj). Konacni automati i regularni izrazi 3. naravno.2.15.54 ˇ 3. za pohranu titlova). a yyyy godina (prirodni brojevi s najviˇe dvije.sub datoteka s (MicroDVD.14. treba pripaziti i na oznake za poˇetak i kraj linije teksta: c ^\d+:[0-5]?\d:[0-5]?\d.\d{3} Sada ovaj izraz treba zapisati dva puta. mjesec i godinu) izdvojite u grupacije (i. c Dobivene dijelove datuma (dan. mm mjesec. Svaka linija datoteke sadrˇava toˇno jedan titl ˇiji je z c c format {frame1}{frame2}Tekst . S sekunde. M minute. Traˇeni format je z vrijeme1 --> vrijeme2 pri ˇemu je svako od vremena zapisano kao c H:M:S. c Zadatak 3.\d{3}) --> \1$ jer bi odgovaralo iskljuˇivo linijama kod kojih su oba zadana vremena potpuno jednaka.2. napiˇite ˇto je u kojoj).ms gdje H oznaˇava sate. Prepoznajmo najprije jedno vrijeme: s \d+:[0-5]?\d:[0-5]?\d. c sa ili bez vode´ih nula. Napiˇite regularni izraz koji prepoznaje linije s ispravnim zapisom vres mena u . s s Zadatak 3. Usput. no izbjegnite oˇito nebulozne datume (dd > 31. Napomena 3. odnosno c s ˇetiri znamenke). “mjesec” oznaˇava tekstualni naziv mjeseca.6. c Rjeˇenje. c Pazite da minute i sekunde ograniˇite na dozvoljene vrijednosti. yyyy/mm/dd pri ˇemu je dd dan. Napiˇite regularni izraz koji prepoznaje ispravne linije .\d{3} --> \d+:[0-5]?\d:[0-5]?\d. te izmedu postaviti separator “ --> ”. viˇe od c s jedne rijeˇi u nazivu mjeseca).\d{3}$ Grupiranjem bismo mogli dobiti pojedine dijelove iz prvog ili drugog vremena (npr. za pohranu titlova). sate i minute).

Zadatak 3. X (deset). Napiˇite regularni izraz koji prepoznaje rimske brojeve u originalnoj nos taciji (dozvoljeno je samo “zbrajanje”. Pazite da ne dozvolite c prazne rijeˇi. c c c Zadatak 3. c Zadatak 3. Turingovim strojem.2.16. a reˇenice zavrˇavaju toˇkom. varijante s 1. Izz s dvojite te tri cjeline u zasebne grupacije. nositelj ordena Reda britanskog carstva i poˇasni c ˇlan Kraljevskog druˇtva znanosti.17. a podatke (bez poˇetnih razmaka) u drugu.18. c Time Magazine nazvao je Turinga jednim od 100 najvaˇnijih ljudi dvadesetog stolje´a za z c ulogu koju je odigrao u stvaranju modernih raˇunala – njegov Turingov test bio je znaˇajan c c i karakteristiˇno provokativan doprinos raspravi o umjetnoj inteligenciji.2.19.20. je 4).2. IIII. Napiˇite regularni izraz koji prepoznaje sve linije u tekstu koje zapoˇinju s c validnim JMBAGom (prirodni deseteroznamenkasti broj) iza kojeg se mogu (ali i ne moraju) nalaziti podaci o vlasniku JMBAGa (ako se nalaze.2.3. a Tekst moˇe biti bilo ˇto. DVI u “PREDVIDJETI”). tj. Zadan je tekst Alan Mathison Turing (1912–1954). Zaˇto? z s Zadatak 3. Napiˇite regularni izraz koji prepoznaje sve linije u tekstu koje zapoˇinju s c validnim JMBGom (prirodni broj koji zapoˇinje s datumom (format ddmmyyy: dvoznamenc kasti dan i mjesec i troznamenkasta godina). L (pedeset). c . kriptoanalitiˇar i c s c c c raˇunalni znanstvenik. s [A-Za-z]+(\s+[A-Za-z]+){2. C (sto). Koristite oznake I (jedan). U prethodnom zadatku. Zadatak 3. upitnikom c c s c ili uskliˇnikom i ne prelamaju se kroz retke. toˇno 3 rijeˇi i c c 2. najviˇe 3 rijeˇi s c ne moˇemo jednostavno prepoznati. V (pet).2. odvojeni su barem jednim razmakom). odvojeni su barem jednim razmakom). Napiˇite regularni izraz koji prepoznaje reˇenice s najmanje 3 rijeˇi. Regularni izrazi 55 Parametri frame1 i frame2 su nenegativni cijeli brojevi.}\. Izvrˇio je veliki utjecaj na razvoj raˇunalne znanosti i pridonio je c s c formalizaciji koncepta algoritma i izraˇunavanja s tzv. JMBAG izdvojite u jednu grupaciju. c Rjeˇenje. te ima ukupno 13 znamenaka) iza kojeg se mogu (ali i ne moraju) nalaziti podaci o vlasniku JMBGa (ako se nalaze. te da ne prepoznate dijelove ve´ih rijeˇi (npr. logiˇar. bio je engleski matematiˇar. JMBG izdvojite u jednu grupaciju. a podatke (bez poˇetnih c razmaka) u drugu.2. Godine 1999. D (petsto) i M (tisu´u). a ne IV. s c c Rijeˇi su nizovi slova odvojeni razmacima.

U prosincu 1940. . U srpnju 1942. “Reda”. “1954”. “1912”. “lan”. Turing je c c rijeˇio pomorski Enigma sustav. “Kraljevskog”. s Koji ´e sve dijelovi teksta odgovarati sljede´im regularnim izrazima. \w+-$ Rjeˇenje.)*)ing 11. 2. 3. “1940” i “1942” .56 ˇ 3. Osmislio je brojne tehnike za razbijanje njemaˇkih ˇifri. Konacni automati i regularni izrazi Tijekom Drugog svjetskog rata Turing je radio za britansku obavjeˇtajnu agenciju odgos vornu za razbijanje obavjeˇtajnih signala i osiguranje podataka britanskoj Vladi i oruˇanim s z snagama. “1999”.)(. \d{3} 5.\1){2. izmislio je tehniku za koriˇtenje protiv nove njemaˇke. \d{3. U\s(. [a-z]\w+ 3. \w+ \d 8. “Alan”. “Mathison”.+u) 9. te koje ´e vrijedc c c nosti vratiti njihove grupacije? 1. Takoder je izumio statistiˇke tehnike za pomo´ u razbis z c c janju Enigma koda. s 1. “athison”. ukljuˇuju´i elektromehas c s c c niˇki stroj koji bi mogao prona´i postavke Enigma stroja. . (. “Turing”. . s c Lorenzove ˇifre. koji je bio daleko sloˇeniji matematiˇki sustav od svih s z c koriˇtenih od strane ostalih sluˇbi. [A-Z]\w+ 2. .. [aeiou]{2. “nositelj”. “ordena”. Neko je vrijeme bio i ˇef Odjeljka 8 koji je bio odgovoran za analiziranje njes maˇkih mornariˇkih kriptograma i glavni sudionik u naporima za razbijanje njemaˇkih c c c ˇifri.} 6.. \d{4} 4. [^A-Za-z ]+ 7. “uring”.} 10. ^(\D+)(\d+) 12.} 13. T((.

“100”. kao i druge regularne izraze pisane po opisanom s standardu. \2 = “na”). “ataka” (\1 = “a”. c 7. “aˇaja” (\1 = “a”. “(1912–1954). “191”. “1954”. “100”.math. . “U prosincu”. Primjere rjeˇenja iz ovog poglavlja. preciznije ovdje: z z http://degiorgi. zbog pohlepnog principa rada algoritma) c c U oba sluˇaja. . “a ana” (\1 = “a”. raˇunaju´i da je svaka linija teksta zasebna upravo s z c c onako kako su prelomljene. \1 ´e biti sve osim prva dva znaka (poˇetno “U” i razmak) c 9. “199”. “od 1”. “1940” i “1942” 6.2. . . Regularni izrazi 57 4. “uˇuju” (\1 = “u”. “195”. “-” (prekid rijeˇi na kraju prve linije).. moˇete isprobati na sluˇbenoj stranici kolegija. \2 = “ju”) Preostale rijeˇite samostalno za vjeˇbu.php. “1999”. “.”. \2 = “ja”). izmislio je tehniku” (NE samo “U srpnju”. “ne 1”.”. \2 = “ma”). “194” i “194” 5. “Odjeljka 8”. 8. “U srpnju 1942.hr/prog1/apps/regex.3. “1912”. “anagama” (\1 = c c “a”.. \2 = “ka”). .

58 ˇ 3. Konacni automati i regularni izrazi .

Svaki korak mora biti precizno i jednoznaˇno opisan. tako da ga moˇe izvrˇiti c z s i raˇunalo. ali opisno moˇemo re´i da je algoritam postupak za rjeˇavanje nekog problema. To znaˇi da programi moraju ispisati rezultat. tada nije potrebno uˇitavati ulazne podatke i ispisivati rezultat (osim ako se u c zadatku to eksplicitno traˇi). algoritam za zbrajanje u bazi b treba ispravno raˇunati sumu dva broja c zapisana u bazi b. Na z s c primjer. z 2. Precizna definicija pojma “algoritam” je komplicirana. z Opisani procesi su primjeri algoritama. a potprogrami ga moraju c ili ispisati ili nekako vratiti glavnom programu (obiˇno ´e u zadatku biti precizirano c c ˇto treba). mnoˇi i dijeli. Algoritam zavrˇava nakon konaˇno mnogo koraka. ne smije se izvrˇavati u s c s nedogled! 4. Na primjer. Algoritam uzima ulazne i vra´a izlazne podatke koji predstavljaju rjeˇenje c s problema. c 59 . Jednim algoritmom moˇemo rijeˇiti samo toˇno odredenu klasu problema. z 3. s Ponekad ´e u zadatku biti navedeno da treba napisati samo dio programa koji neˇto c s radi. neki ima znamenku ve´u ili jednaku b). z c s Neke vaˇne karakteristike algoritama su: z 1. c s kako se u raznim brojevnim sustavima zbraja. tj. oduzima.Poglavlje 4 Uvod u algoritme i osnovni program U prethodnim poglavljima vidjeli smo razliˇite upute kako neˇto napraviti. Na primjer. ako zadatak kaˇe da treba uˇitati prirodan broj. ali nije odredeno ˇto mora raditi ako brojevi nisu dobro zapisani s (npr. niste z c duˇni provjeravati je li uˇitani broj zaista ve´i od nule (osim ako se takva provjera z c c eksplicitno traˇi u zadatku). kako od tablice z istinitosti sloˇiti konjunktivnu i disjunktivnu normalnu formu i sl. c To znaˇi da se moˇete osloniti na to da ´e ulazni podaci biti onakvi kakvi su navedeni c z c u zadatku.

c Najpoznatije al-Khw¯rizm¯ a ijevo djelo je “al-Kit¯b al-mukhtaar f¯ is¯b al-jabr wa-la i a muq¯bala” u kojem je opisao postupke rjeˇavanja jednadˇbi prvog i drugog reda. pa je rijeˇ “algoritam” preuzeta kao “postupak z c za raˇunanje”. Uvod u algoritme i osnovni program Odakle potjeˇe rijeˇ “algoritam”? Arapi su skupljali i prevodili klasiˇna grˇka djela. no ˇto to znaˇi? z s c U osnovi. mnoˇenja. a rijeˇ je o izuzetno dobro pla´enim struˇnjacima. kod zahtjevnijih projekata. oduzimanja. . programeri – osobe koje piˇu programski kˆd u odredenom programskom jeziku. “algoritmi” su samo postupci za raˇunanje. ali se ne s c c stavlja naglasak na apsolutno poznavanje sintakse odabranog jezika (u naˇem sluˇaju Cs c a). 4. 1. te je u njoj opisao postupke c zbrajanja.60 4. Prema a s z tom djelu. nuˇno je poznavanje nekog s z programskog jezika (zbog provjere rjeˇenja i poznavanja mogu´nosti raˇunala). . to dvoje je ˇesto isto. Bilo bi izuzetno loˇe za konaˇno rjeˇenje kad bi svatko to radio s c s na svoj naˇin. dovrˇiti) potjeˇe rijeˇ “algebra”. Danas postoji saˇuvan z latinski prijevod iz dvanaestog stolje´a pod naslovom “Algoritmi de numero Indorum”. Kod manjih projekata. c pri ˇemu je rijeˇ “Algoritmi” bila predstavljala latinizirano ime autora. c dakle osobe sposobne “algoritamski razmiˇljati”. Veliki projekti rade z se u viˇe razvojnih faza. s o prema uputama koje daju projektanti. 9). a postaje i sve vaˇniji c s c z u matematici.1 Tko “programira”? Danas je uvrijeˇena definicija da su programeri “oni koji programiraju”. Viˇe o tom dijelu posla uˇi se na kolegiju c s s c “Softversko inˇenjerstvo”. . isplati z c c c . nego na poznavanje principa rada i konstrukcija jezika u onoj mjeri koja je nuˇna za z zapisivanje algoritama koje ´emo raditi. c c c c te znanost iz Indije i Kine. Medutim. Kasnije je to mic c sinterpretirano kao mnoˇina na latinskom. za realizaciju velikih projekata ˇesto je potrebno mnogo c “onih koji programiraju”. c s c c U starom znaˇenju. a glavnu ulogu u tom procesu imaju software inˇenjeri – vrlo s sliˇno onome ˇto ovdje zovemo projektantima. Muammad ibn M¯s¯ al-Khw¯rizm¯ napisao je knjigu o “indijua a i skim brojevima” (precizni sustav sa znamenkama 0. Naime. Ovdje (na raˇunarskim kolegijima na PMF-MO) prvenstveno obrazujemo projektante. c ta razlika je jako bitna. “one koji programiraju” dijelimo u dvije grupe: 1. . Zbog toga je potreban manji tim projektanata koji ´e osmisliti rjeˇenje i c c s dati upute programerima. dijeljenja i vadenja korijena. od rijeˇi “al-jabr” (uspostaviti. projektanti – osobe koje osmiˇljavaju algoritme i strukture podataka kojima se s rjeˇava neki problem te s 2. dok je moderno znac c ˇenje bitno ˇire. Dakle. Pri tome. Pojam algoritma centralni je pojam raˇunarstva. c Gornja podjela na projektante i programere je simplificirana.

h> int main ( void ) { p r i n t f ( ” h e l l o . Osnovni program u C-u sastoji se od: 1. to znaˇi da prikazujemo c samo dio programa! Za uspjeˇno compiliranje i izvodenje takvog koda. potrebno je s dopisati elemente koji nedostaju! 3. backslash n) oznaˇava skok u novi red. } Lako se vidi koja naredba ispisuje tekst.h.2. Kako ´emo kasnije vidjeti. c . #include <stdio. Cesto se dodaju i druge vrijednosti. kao uvertiru u ono ˇto slijedi u c s nastavku studija. main() je obiˇan c c potprogram koji se od ostalih potprograma razlikuje samo po tome ˇto upravo njega s raˇunalo izvodi prilikom pokretanja programa. naˇin navodenja naredbi i sl. Svrha takvog programa s je demonstracija osnovne sintakse: zaglavlja. Ta datoteka c z sadrˇi sve ˇto je potrebno za ispravan ispis teksta na standardni izlaz (najˇeˇ´e ekran z s c sc raˇunala).edu/~acm/HelloWorld.4. world”.1 (“Hello world” program pisan u C-u). ˇto ´emo takoder vidjeti malo kasnije. 1 2 3 4 5 6 #include <s t d i o .h> Direktiva compileru da ukljuˇi u program sadrˇaj datoteke stdio. pa se i takvi programi ˇesto zovu “hello c sc c world” programi. c Najˇeˇ´e se ispisuje poruka “hello.shtml U C-u. Veliku arhivu takvih programa u raznim jezicima moˇete vidjeti ovdje: z http://www2. c 2. int main(void) Zaglavlje glavnog dijela programa. world \n” ) .2. Osnovni program 61 se uˇiti kolegije “Programiranje 1” i “Programiranje 2”.2 Osnovni program Pod pojmom “osnovni program” u svakom programskom jeziku podrazumijevamo program koji ispisuje neku jednostavnu poruku i zavrˇava s radom. printf("hello. c Kad negdje navedemo programski kod bez funkcije main(). takav program izgleda ovako: Primjer 4. Sama naredba za ispis. ali vidimo da je (ˇak i za ovako jednostavan c program!) potrebno napisati i neke “dodatke”. return 0 . Tekst koji ´e se ispisati navodimo izmedu dvostrukih nac ˇ vodnika. world\n"). s c Specijalni znak \n (engl. 4.latech.

return 0 . h> int main ( void ) { printf (” hell ” ). Ovdje te brojeve navodimo samo za lakˇe snalaˇenje u kodu. c s Zbog toga smo tre´i printf() zapoˇeli razmakom jer je to prvi znak koji ˇelimo ispisati c c z iza zareza (njega ispisuje drugi printf()). } Bilo kakvo drugaˇije cjepkanje niza znakova “hello. inaˇe se navodi neka druga (cjelobrojna) vrijednost.2. {} Vitiˇaste zagrade sluˇe za grupiranje pojedinih cjelina programa. Uvod u algoritme i osnovni program 4. compiler ne´e niˇta sam dodati). p r i n t f ( ” world ” ) . c 4. s z c Program iz primjera 4. kursor ostaje toˇno tamo gdje je s c ispis stao.3 Ispis U prethodnom poglavlju vidjeli smo osnovni program koji prilikom svakog izvrˇavanja s ispisuje isti tekst. return 0. ” ) .62 4. c c Primijetimo da je potrebno ispisati sve znakove (tj. mi ´emo pisati korektne programe.1 daje i sljede´i program: 1 2 3 4 5 6 7 8 9 #include <s t d i o . c 5. isti ispis kao u primjeru 4.2. world” bi poluˇilo isti rezultat. poput z c s c 1 2 3 main ( ) { p r i n t f ( ” h e l l o . Zbog c c c toga. Nakon izvrˇavanja naredbe printf(). jer prilikom “skra´ivanja” kompliciranijih proc c grama moˇe do´i do problema: neobiˇna ponaˇanja programa ili nemogu´nost prevodenja z c c s c na nekom raˇunalu ili compileru. Povratna vrijednost funkcije. potrebno je c vratiti nulu. Idu´i poziv naredbe printf() ´e nastaviti pisati upravo na tom mjestu. Ve´ina danaˇnjih C compilera ´e prihvatiti i jednostavnije verzije. na primjer. } Ipak. kod funkcije main() oznaˇava vrijednost koju program c vra´a operacijskom sustavu. Ispisati moˇemo i brojˇane vrijednosti. world \n” ) . p r i n t f ( ”\n” ) .1 je ispravno napisani program u jeziku C koji ´e ispisati ˇeljenu poruku. Ovdje je to upoc z trijebljeno za grupiranje dvije naredbe u funkciju main(). U C-u se ne navode brojevi linija (kao. Ako je program ispravno obavio posao. jednostavnim uvrˇtavanjem u niz znakova: z c s . p r i n t f ( ”o . u BASICu).

U tu svrhu koristimo varis jable. ” razlicite ”). printf ( ” c i j e l i b r o j %d . Tada u nizu znakova koji ispisujemo z treba navesti gdje ´e se dodatne vrijednosti pojaviti. Ova naredba ispisuje sljede´i tekst: c Ovdje cemo ispisati razlicite vrijednosti: cijeli broj 17. Njih ´emo koristiti u svim primjerima i zadacima. Potrebno je omogu´iti uˇitavanje vrijednosti.. \ n” ) .3. niz znakova. 1 9 . Znaˇenje samih formata je c c detaljno objaˇnjeno na predavanjima. s Primijetimo da naredbe smijemo “lomiti” izmedu parametara (npr. 1 7 . kursor ´e biti na poˇetku sljede´eg retka (zbog s c c c znaka \n na kraju). \ n” .). r e a l n i b r o j %g i znak %c . Nakon izvrˇavanja naredbi printf(). znak. Primjer 4.3.. To je poˇeljno raditi da bi programi bili pregledniji. z ˇ Cemu sluˇe formati? Oˇito..19 i znak Q. no ne treba pretjerivati. novi redak izmedu 17 i 17. 17 . te kojeg su one tipa (cijeli broj.4. raˇunanje. Podizrazi koji se navode u naredbi printf(). program koji ispisuje uvijek istu poruku nije naroˇito koz c c ristan. c c c . c c Tekst ´e biti ispisan u jednoj liniji (izmedu zareza i rijeˇi “realni” nalazit ´e se razmak). Ponekad ˇelimo neke vrijednosti navesti odvojeno. snimanje i mnoge druge c c c operacije da bi program mogao rjeˇavati odredene probleme.1 (Ispis dodatnih vrijednosti). ’Q ’ ). Ispis 63 1 p r i n t f ( ” Prog1 cu p o l o z i t i s ocjenom 4 i l i 5 . c Ovdje je razlomljen samo zato da bi stao na stranicu. realni broj 17. 1 2 3 4 5 6 7 p r i n t f ( ” Ovdje cemo i s p i s a t i %s v r i j e d n o s t i : ” . ˇije vrijednosti ´emo onda ispisivati upravo pomo´u formata u naredbi printf(). c realni broj.19). a poˇinju znakom % zovu se formati c za ispis.

Uvod u algoritme i osnovni program .64 4.

gdje 0 z c predstavlja laˇ. .1. c Napomena 5. realni. Umjesto logiˇkog tipa koristi se cjelobrojni. no u C-u tog tipa nema. c Svaka varijabla ima tip koji treba navesti prije upotrebe varijable. Prvo ´emo prikazati s kakvim c c sve podacima moˇemo baratati. Osnovni tipovi su: • brojevi (cijeli. z z c Naredba scanf() prihva´a formate sliˇne onima koje prima naredba printf(). Adresu varijable dobijamo c operatorom &. bez mogu´nosti da mu zadajemo podatke. Ti c c formati se moraju slagati s tipom varijable koju uˇitavamo.2. ) • znakovi • pokazivaˇi (sadrˇe adrese drugih varijabli) c z Neki jezici imaju i logiˇki tip (varijable koje mogu imati samo dvije vrijednosti: istina c i laˇ). a zatim i na koji naˇin to radimo. z c 5.1.1. a sve ostale vrijednosti predstavljaju istinu (obiˇno koristimo vrijednost z c 1). dok z c c c za sloˇene tipove treba posebno sloˇiti dio programa za uˇitavanje. Napomena 5.1 Uvod Varijable su simboliˇka imena za memorijske lokacije u koje pohranjujemo vrijednosti. .. bez ˇega bi svaki program c radio uvijek isto. Funkcije u C-u ne mogu mijenjati vrijednosti varijabli koje navedemo kao ulazne parametre (pri pozivu funkcije)! Zbog toga funkciji scanf() zadajemo adrese varijabli u koje spremamo uˇitane vrijednosti. 65 .Poglavlje 5 Varijable U ovom poglavlju bavimo se spremanjem podataka u memoriju. Naˇin uˇitavanja varijabli ovisi o tipu varijable! Varijable nekog od c c osnovnih tipova moˇemo uˇitati direktno (pomo´u naredbe scanf() ili neke sliˇne).

Bitna razlika c c c je u tome ˇto prilikom uˇitavanja viˇe brojeva. prvo navodimo formate vrijednosti koje uˇitavamo. "ni").1. %d oznaˇava cijeli broj. s c Rjeˇenje. return 0 . to radimo pomo´u formata %s. pripadne formate odvajamo razmakom (v.\n".2. Na sliˇan naˇin uˇitavamo znakove (tip char). Uˇitavanje niza znakova je sloˇenije i to ´emo kasnije obraditi. kao i u naredbi printf(). Tekst naveden izmedu /* i */ je komentar. &a ) . onda njenu adresu moˇemo dobiti izrazom &x. /∗ U c i t a v a n j e j e d n e v a r . dok kod znakova taj razmak izostavljamo. Potonji omogu´uje ve´i raspron vrijednosti. Varijable Dakle. Napiˇite program koji uˇitava tri znaka.1. Napiˇite program koji uˇitava tri cijela broja i ispisuje njihovu sumu. s c s liniju 6 u rjeˇenju prethodnog zadatka). &c ) . ∗/ s c a n f ( ”%d %d” .1. c U liniji 7 vidimo klasiˇan ispis tri varijable i jednog izraza. h> int main ( void ) { int a . b . } U naredbama scanf() (linije 5 i 6). ´e ispisati c Danas nije lijep dan. ∗ / p r i n t f ( ”%d + %d + %d = %d\n” . c . Na primjer. s Zadatak 5.3. b . te ih ispisuje obrnutim redoslis c jedom. ˇto znaˇi s c da ga compiler ignorira. a . &b .3 (Komentari). a + b + c ) . s 1 2 3 4 5 6 7 8 9 #include <s t d i o . ako imamo varijablu x. c . Za realne brojeve koristimo tipove float (format %f) i double (format %lg). Nakon formata (navedenih c c unutar dvostrukih navodnika) popisujemo adrese varijabli koje uˇitavamo.1.66 5. primjer 4. / ∗ U c i t a v a n j e d v i j e v a r .1). ali upotrebom formata %c. Sam niz znakova navodimo pomo´u dvostrukih c c navodnika (v. Ako ˇelimo ispisati niz c z c z znakova. Pri tome. c Napomena 5. dio koda printf("Danas %sje lijep dan. Razlozi s takvog navodenja formata objaˇnjeni su na predavanjima. z Zadatak 5. /∗ D e k l a r a c i j a v a r i j a b l i ∗/ s c a n f ( ”%d” . c c . Koristimo ga kao zabiljeˇke za lakˇe snalaˇenje u programskom s s z kodu.

&c ) . z a p i s s v e l i k i m s l o v i m a : %X\n” . i ) . return 0 . h> int main ( void ) { float a . &a ) . p r i n t f ( ”%g ∗ %g ∗ %g = %g \n” . c . c z Primjer 5. double b . t i p a i n t u d e k a d s k o m z a p i s u ∗/ #include <s t d i o . s c a n f ( ”%d” . te ispisuje njihov produkt.2. } Prilikom ispisa varijabli tipa double ne treba navoditi l u formatu. .3. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 /∗ −−− h e x a d e c i m a l n o m s m a l i m s l o v i m a −−−> %x ∗/ /∗ −−− o k t a l n o m −−−> %o ∗/ /∗ −−− d e k a d s k o m −−−> %d i l i % i ∗/ /∗ i s p i s u j e m o v a r i j a b l u i u r a z l i c i t i m f o r m a t i m a : ∗/ /∗ u c i t a v a n j e v a r . i ) . a ∗ b ∗ c ) . Joˇ o formatima s 67 Zadatak 5. s c a n f ( ”%f ” .1. a . h> int main ( void ) { int i . i ) . c .5. b .1. s 1 2 3 4 5 6 7 8 9 10 #include <s t d i o . p r i n t f ( ” d e k a d s k i z a p i s : %d\n” . /∗ −−− h e x a d e c i m a l n o m s v e l i k i m s l o v i m a −−−> %X ∗/ p r i n t f ( ” hexadec . &b . &i ) .2 Joˇ o formatima s Pomo´u formata moˇemo dodatno definirati izgled ispisanog teksta. z a p i s s malim s l o v i m a : %x\n” . i ) .2. p r i n t f ( ” o k t a l n i z a p i s : %o \n” . 5. p r i n t f ( ” hexadec . Napiˇite program koji uˇitava tri realna broja (jedan tipa float i dva s c tipa double). s c a n f ( ”%l g %l g ” . Rjeˇenje.

&i ) . s c a n f ( ”%x” . hex : %x” . i ) . Znak “%” ispisujemo navodenjem formata %%. i . i . & f l t ) . 3. 7 m j e s t a .14e-3.68 5.14E-3.2. &i ) .1. npr. . ako je potrebna enotacija.2. l i j e v o p o r a v n a v a n j e −> % −7 d ∗/ p r i n t f ( ” 7 m j e s t a s l i j e v o poravnavnato : %−7d\n” . 1 2 3 4 5 6 7 #include <s t d i o . npr. i ) . /∗ u c i t a v a n j e u o k t a l n o m i l i hex − f o r m a t u : ∗/ p r i n t f ( ” u n e s i t e c i j e l i b r o j u hex−formatu ” ) . d e s n o p o r a v n a v a n j e −> %10 d ∗/ p r i n t f ( ” 10 m j e s t a desno poravnavanato : %10d\n” . koristi slovo e • %E – e-notacija. -3.2. Primjer 5.14159 • %e – e-notacija. koristi slovo E • %g – automatski se prepoznaje o kojem se tipu zapisa radi. i . i ) . h> int main ( void ) { double d b l . s c a n f ( ”%f ” . /∗ /∗ /∗ u c i t a m o l i i n t s a % i f o r m a t s e a u t o m a t s k i ∗/ ∗/ z a p i s . float f l t . Varijable 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 /∗ −−− min . p r i n t f ( ” ( mala s l o v a ) : ” ) . 0 x 1 2 3 −> hex − z a p i s ∗/ p r e p o z n a j e 0 1 2 3 −> o k t a l n i s c a n f ( ”%i ” . npr. /∗ −−− min . ako je potrebna enotacija. o c t : %o . i ) . return 0 . p r i n t f ( ” dec : %d . %x i %X rade samo s nenegativnim cijelim brojevima! Formati kod ispisa realnih brojeva: • %f – obicni decimalni zapis. -3. p r i n t f ( ” dekadska v r i j e d n o s t od %x j e %d\n” . } Formati %o. koristi se slovo e • %G – automatski se prepoznaje o kojem se tipu zapisa radi. koristi se slovo E Napomena 5. 10 m j e s t a .

f l t ) . Raˇunalo sve. p r i n t f ( ”%%e −−> %e \n” . /∗ /∗ % 1 0 . &x ) . ispisi. p r i n t f ( ”x = %d . f l t ) .0 f \n” .5 f −−> z a o k r u z e n o na 5 d e c i m a l n i h m j e s t a ∗/ p r i n t f ( ” z a o k r u z e n o na 5 dec . p r i n t f ( ”%%g −−> %g \n” . ∗/ t r o s i ∗/ n a j m a n j e z n a k o v a p r i n t f ( ” z a o k r u z e n o na 3 dec .5. mjesta . x . .2 e \ ’ \ n” . mjesta . pointeri) sadrˇe. ). ” ) . m j e s t a : %. 3 f −−> z a o k r u z e n o u k u p n o na 3 d e c . /∗ Na i s t i n a c i n z a o k r u z u j e m o i s % e i %g ∗/ p r i n t f ( ”2 dec . Zbog toga pokazivaˇe moˇemo ispisati kao prirodne c z brojeve (unsigned int): 1 2 int x = 1 7 . d b l ) . /∗ /∗ da za b i u c i t a l i ne d o u b l e t r e b a ∗/ NUZNO j e k o r i s t i t i p r e f i x l i s p i s s c a n f ( ”%l g ” . viˇe ne´emo posebno oznaˇavati razmake u programima. c Takoder. U nastavku ´emo uglavnom navoditi samo tijela ili dijelove programa.5 f \n” . c z c pa tako i adrese. ukupno bar 12 znakova . return 0 .2. potrebno je dopisati one dijelove koji nedostaju (u pravilu zaglavlja. 10 m j e s t a . s e ne m j e s t a ∗/ ∗/ t o c k a i s p i s u j e p r i n t f ( ” z a o k r u z e n o na 0 dec .2.0 f −−> z a o k r u z e n o d e c i m a l n a na 0 d e c .3 f \ ’ \ n” . . &x = %u\n” . memorijske adrese. s c c . kako smo naveli. m j e s t a : %. &d b l ) . ukupno bar ” ) . } Pokazivaˇi (engl. pamti kao brojeve.. d b l ) . Napomena 5. Naravno. d b l ) . f l t ) . p r i n t f ( ” poravnato l i j e v o : \ ’% −12. p r i n t f ( ” 10 znakova : \ ’%10. c bez zaglavlja. Joˇ o formatima s 69 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 p r i n t f ( ”%%f −−> %f \n” . d b l ) . inaˇe programe treba pisati cijele. osim ako je u zadatku c naglaˇeno da se piˇe samo dio programa! Da biste na raˇunalu testirali dijelove s s c programa. /∗ %.2. /∗ /∗ %. deklaracije i uˇitavanja varijabli.

70 5. Varijable .

a+b . a /b=%d .Poglavlje 6 Osnovne raˇunske operacije c Vrijednosti nije dovoljno pohraniti. vra´a cjelobrojni rezultat dijeljenja dva cijela broja.42857 71 . 0 . c-d=10. a%b ) . s Primjer 6. oduzimati (operator -).i * se ponaˇaju identiˇno kao u matematici s c (s tim da treba paziti da rezultat nije prevelik. a/d ) . double c = 1 7 . a∗b=%d . a-d=10. dok opec rator ostatka. a/b=2.1. a%%b=%d\n” . a/d=2. a∗d . potrebno nam je i nekakvo mijenjanje tih c vrijednosti koje se obiˇno svodi na raˇunanje i pohranjivanje novih vrijednosti u nove ili c c ve´ koriˇtene varijable. 0 . c ∗d=%g . p r i n t f ( ” a+d=%g . a-b=10. a−b . Operator dijeljenja. tj. Operatori +. /. da ga spremamo u varijablu s dovoljno memorije). a/b . c Ukoliko je jedan od operanada realan broj. p r i n t f ( ” a+b=%d . vra´a ostatak pri dijeljenju dva cijela broja. %. c ∗d . c−d . c s 6. 1 2 3 4 5 6 7 8 int a = 1 7 .1. c*d=119. c/d=2. c /d=%g” . a∗d=%g . . a*b=119. c /d ) . b = 7 . c+d . d = 7 . a%b=3 a+d=24. c−d=%g .1 Uvod Cijele brojeve moˇemo zbrajati (operator +). operacije se vrˇe realno (a ne cjelobrojno). Ispis ovog dijela programa bit ´e c a+b=24. a−d=%g .42857 c+d=24. p r i n t f ( ” c+d=%g . a*d=119. a−b=%d . Oˇito. a+d . a /d=%g” . a−d . a∗b . mnoˇiti (operator z z *) i dijeliti (operatori / i %).

´e varijabli x pridruˇiti rezultat zbrajanja varijabli a i b.1. izraz s y = x = a + b. Rezultat koji taj izraz c vra´a je upravo vrijednost izraza A. z 6. Na sliˇan naˇin varijabli moˇemo pridruˇiti i rezultat c z c c z z nekog izraza. ´e varijabli x pridruˇiti vrijednost 17. Na primjer. ˇto ´e varijablama x i y pridruˇiti vrijednost 17.72 ˇ 6. ovakvo pridruˇivanje moˇemo s c z c z z navesti i bez zagrada (iz razloga objaˇnjenih na predavanjima). ovaj izraz ´e z c udvostruˇiti vrijednost varijable p. ´e varijablama x i y pridruˇiti rezultat zbrajanja vrijednosti koje se nalaze u varijablama c z a i b. Na primjer. te z c c tu vrijednost pridruˇuje varijabli s lijeve strane znaka jednakosti. Dakle. Razlikujte znakove “/”. Prilikom pridruˇivanja izraza varijabli.1 (Cesta greˇka). c z Svi izrazi u C-u vra´aju neku vrijednost. Dapaˇe. Osnovne racunske operacije Primijetite razliku u rezultatima cjelobrojnog (prva linija ispisa) i realnog dijeljenja (druga i tre´a linija ispisa). dok znak “\” sluˇi za specijalne znakove. izraz z x = 17. z skok u novi red ne smijete pisati “/n”! Znak “|” oznaˇava operator bitwise-OR i ne c moˇe biti zamjena niti za jedan od preostala dva znaka. Zbog toga smijemo napisati i c y = (x = 17). tj. c Navedeni izraz smo mogli i kra´e zapisati: c . Na primjer. “|” i “\”! Znak “/” oznaˇava s c dijeljenje koje ne smijete pisati “a \ b”. Vrijednost koju ´emo pridruˇiti nekoj varijabli smijemo raˇunati pomo´u te iste varic z c c jable. izraz x = a + b. c ˇ Napomena 6. pa tako i izraz x = A. Na primjer: p = p * 2.2 Pridruˇivanje z Varijabli pridruˇujemo vrijednost tako da iza nje stavimo znak = i desno od njega navez demo vrijednost koju pridruˇujemo. raˇunalo prvo raˇuna vrijednost desne strane.

1. sljede´i izrazi su ekvivalentni: c x = x + d x = x . onu c vrijednost koju je poprimila inkrementom). i ) . Na taj naˇin moˇemo skratiti i ostale izraze oblika c z a = a op b. Na sliˇan naˇin. p r i n t f ( ” i = %d\n” . Naime. c c c dok --x smanjuje vrijednost od x za jedan.2. gdje je “op” neki operator. p r i n t f ( ” i = %d . p r i n t f ( ”d = %d\n” . onu vrijednost koju c je varijabla imala prije inkrementa). dok ++x vra´a novu vrijednost varijable x (tj.i --x za dekrement. p r i n t f ( ” i = %d\n” . ” . a razlikuju se u povratnoj c vrijednosti izraza.). p r i n t f ( ”(++ i ) = %d . i ) . ” . i ) . d ) .2. ali vra´a novu vrijednost. Postoje joˇ i sljede´e posebne pokrate: s c x++ i ++x za inkrement.. te x-. p r i n t f ( ” i = %d .. i ) . p r i n t f ( ” ( d−−) = %d . d−−). x++ vra´a staru vrijednost varijable x (tj. izraz x-.. p r i n t f ( ”d = %d . d = 1 7 . ” . .d x = x * d x = x / d x = x % d x += d x -= d x *= d x /= d x %= d Isti naˇin skra´ivanja moˇe se primijeniti i na operatore koje ´emo tek obraditi (logiˇke.6. ” . Pridruˇivanje z 73 p *= 2.smanjuje vrijednost od x za jedan i vra´a staru vrijednost. p r i n t f ( ” ( i ++) = %d . Dakle. ” . Pri tome x++ i ++x pove´avaju vrijednost varijable x za jedan. i ++). Pogledajmo dio programa: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int i = 1 7 . d ) . c c z c c bitovne. ” . ++i ) . c Primjer 6.

pa se zato prvo pove´a vrijednost varijable.74 ˇ 6. 16. vrijednost koju je varijabla i imala prije inkrementa).2. Na sljede´i naˇin moˇete jednostavno zapamtiti “koji je koji” (na c c z primjeru operatora za inkrement): ++x ima operator prije varijable. pa se zato prvo vrati vrijednost varijable. izraz i++ je pove´ao vrijednost varijable i sa 17 na 18. c Tehniˇki. p r i n t f ( ”(−−d ) = %d . −−d ) . Osnovne racunske operacije 15 16 17 p r i n t f ( ”d = %d . ” . 17. d ) . ovo nije ispravno. S druge strane. pa tek onda pove´a. jer se vrijednost izraza vra´a uvijek nakon ˇto je sve ostalo c c s raˇunanje gotovo. ali je vrijednost s c izraza jednaka 17 (dakle. c c .1. d ) . a zatim vrati. i i d d = = = = 18 19 16 15 Kao ˇto vidimo. 19. p r i n t f ( ”d = %d\n” . no dobro je kao sugestija prilikom pam´enja operatora. Napomena 6. (i++) (++i) (d--) (--d) = = = = 17. 19). izraz ++i je takoder pove´ao vrijednost varijable i (ovaj put s 18 na 19). 18. ” . S druge strane. 17. Analogno vrijedi i za operator --. izraz x++ ima operator nakon c varijable. ali je c njegova povratna vrijednost jednaka novoj vrijednosti varijable i (dakle. 15. Ispis ovog dijela programa ´e biti: c i i d d = = = = 17.

x ) . c c 2. uvjetni operator (?:) ili viˇestruko grananje (koje ´emo c s c obraditi u poglavlju 9). Ovaj dio c c s nije nuˇno navesti ako u sluˇaju neispunjenja uvjeta ne treba niˇta izvrˇiti. 3. s c a n f ( ”%d” . Napiˇite dio programa koji uˇitava cijeli broj i ispisuje poruku je li taj s c broj negativan. Kljuˇna rijeˇ if i uvjet koji provjeravamo. onda ih grupiramo pomo´u vitiˇastih zagrada! c c 75 . Rjeˇenje. Grananje ima nekoliko komponenti: 1. Kljuˇna rijeˇ else i programski kod koji se izvrˇava ako uvjet nije istinit. x ) . else p r i n t f ( ” Broj %d n i j e n e g a t i v a n . 7.1. i f ( x < 0) p r i n t f ( ” Broj %d j e n e g a t i v a n . Programski kod koji se izvodi ako je uvjet istinit.Poglavlje 7 Grananje ˇ Cesto ˇelimo da se. Ako se u nekom sluˇaju (npr. \ n” .1 Obiˇno grananje c Zadatak 7.1. ovisno o vrijednostima varijabli. s 1 2 3 4 5 6 int x . U tu svrhu z s c koristimo obiˇno grananje (if). kad je uvjet ispunjen) treba izvrˇiti viˇe c s s naredbi. z c s s Napomena 7. izvrˇe razliˇite naredbe. &x ) .1.1. \ n” .

b . b . operator || oznaˇava “logiˇko ILI”. dok operator ! c c c c oznaˇava logiˇku negaciju. i f ( a > b && a > c ) p r i n t f ( ” Broj %d j e v e c i od %d i %d . c ˇ Napomena 7. a . U C-u ne postoje znakovi ≤ i ≥. Operator za provjeru “razliˇitosti” je != (“uskliˇnik” i “jednako”. Umjesto njih.2 (Cesta greˇka). izraz c a > b.2. &b . c ) . c c Dakle. ˇto je s uvijek pridruˇivanje! z Napomena 7. b . Pokuˇajte otkriti kako C interpretira takve izraze. koristimo <= i >= respektivno (NE =< i =>!). c ) . \ n” . &c ) . smijemo napisati i a > b && c i a > b. Napiˇite dio programa koji uˇitava cjelobrojne varijable a. te s c ispisuje je li a ve´i od b i c. c . Operator && oznaˇava “logiˇko I”. bez razmaka izmedu). ˇ Napomena 7.1. ali ´e rezultat u oba sluˇaja biti pogreˇan c c s (evaluirat ´e se drugaˇije od oˇekivanog).4 (Cesta greˇka).1. Uvjete moˇemo kombinirati kao i u logici sudova. c ne smijemo1 zapisati kao U stvari. Uputa. Dakle izraz c c (a > b) i (c > d ili e = d) C-ovski zapisujemo kao (a > b) && (!(c > d) || e == d).76 7. Grananje Zadatak 7. Napiˇite dio programa koji uˇitava cijeli broj i ispisuje poruku je li taj s c broj paran. else p r i n t f ( ” Broj %d n i j e v e c i od %d i %d . &a . a . Upotrijebite operator %. c. b i c. s 1 2 3 4 5 6 int a . c c c s 1 .1. \ n” .1. Operator za provjeru jednakosti dva broja je == (dvoss truko “jednako”).1.3. Operatori && i || povezuju logiˇke izraze. Drugim s c rijeˇima. s c a n f ( ”%d %d %d” .3. uvjet x != y znaˇi x = y. Treba paziti da ga se ne zamijeni s = (jednostruko “jednako”). z Zadatak 7. c Rjeˇenje.

4. 1 2 3 s c a n f ( ”%d” . .1. 7.2. Uvjetni operator 77 a > b && c ili a > b. p r i n t f ( ” P r v i p a r n i b r o j s t r o \−go v e c i od %d j e %d .2 Uvjetni operator U C-u postoji posebni operator ?: koji sluˇi za jednostavnije ubacivanje uvjeta u izraze. Zapisano pomo´u if.1. program treba re´i je li izraz s c abc + a¯ + ab¯ + abc bc c ¯ istinit ili laˇan.1. Podsjetimo se: ako broj promatramo kao logiˇki izraz. ako nije. a sve ostalo istinu. Napomena 7. Ispravan naˇin za zapisati zadani izraz je c a > b && a > c. Zbog toga. Potom.2. gornji dio koda smo mogli zapisati i bez “== 1”: c z 1 2 3 s c a n f ( ”%d” . Pri tome koristimo ˇinjenicu da je idu´i parni broj x+1 ako je x neparan. odnosno vrijednost izraza B ako uvjet UVJ nije zadovoljen. z Uputa.. taj izraz izgleda c ovako: if (UVJ) x = A. else x = B. Pojednostavite izraz.2. ” . c c Primjer 7. x . varijabla x poprima vrijednost izraza A ako je uvjet UVJ zadovoljen. z Osnovni poziv operatora izgleda ovako: x = (UVJ ? A : B). b i c koje s c imaju vrijednosti 0 ili 1 (potrebno je provjeriti da je dobro upisano i. Pri tome. onda 0 ozc naˇava laˇ. Zadatak 7. c. (x % 2 ? x + 1 : x + 2)). &x ) . prijaviti greˇku). &x ) . p r i n t f ( ” P r v i p a r n i b r o j s t r o \−go v e c i od %d j e %d . “pretvorite” ga u C-ovski zapis i upotrijebite if. odnosno x+2 c c ako je x paran. ” . ( x % 2 == 1 ? x + 1 : x + 2 ) ) .7. Uˇitavamo cijeli broj x i ispisujemo prvi parni broj strogo ve´i od njega. Napiˇite dio programa koji uˇitava cjelobrojne varijable a. x .

Grananje .78 7.

u pravilu svaki put s drugim s vrijednostima nekih varijabli. U tu svrhu koristimo razne petlje. for() i do.. s 1 2 3 4 5 6 7 8 unsigned long int x .while().Poglavlje 8 Petlje Gotovo svaki program neke dijelove koda izvodi viˇe puta. Napiˇite dio programa koji uˇitava prirodni broj x i ispisuje sve potencije s c broja 2 strogo manje od x. p ) . a izbor one “prave” ovisi o tome ˇto se toˇno traˇi. p r i n t f ( ” Unesite x : ” ) . Rjeˇenje. &x ) . c s 8. Same petlje su ekvivalentne i svaka moˇe manje ili viˇe jednostavno zamijeniti z ostale dvije. kao i o ukusu s c z s programera. te za njihov tip navodimo unsigned long int. p = 1 . p ∗= 2 .1 while()-petlja Zadatak 8. s c a n f ( ”%l u ” .. Nakon pregleda petlji u C-u.1. U C-u postoje while(). while ( p < x ) { p r i n t f ( ”%u\n” . 79 . objasnit ´emo ˇto je to sloˇenost algoritama i kako c s z usporedujemo razliˇite algoritme koji rjeˇavaju isti problem.1. } U prethodnom rjeˇenju imamo nekoliko novosti: s • U deklaraciji (linija 1) deklariramo varijable x i p.

1. p r i n t f ( ” Unesite x : ” ) . neovisno o tome radi li se s prirodnim c ili s cijelim brojevima. Mi ´emo uglavnom koristiti int. Zbog toga ˇto ne trebamo pamtiti negativne brojeve. Naime. tijelo petlje s se ponovno izvrˇava. Tako smo ovdje deklarirali varijablu x kojoj nismo zadali nikakvu vrijednost (pa ´e ona biti neka sluˇajna) i varijablu p kojoj dajemo c c vrijednost 1. jer udvostruˇenje raspona nije naroˇito veliko. &x ) . dok slovo l dodajemo prilikom uˇitavanja c c bilo koje varijable tipa long. imamo izraz p = 1. Petlje Kad brojevnom tipu dodamo atribut unsigned. moˇemo zadati vrijednost varijaz ble odmah prilikom deklaracije. Posljedica je c c s opet mogu´nost memoriranja viˇe vrijednosti. ako nije. Atribut long znaˇi da ´e varijabla zauzeti dvostruko viˇe memorije. i f ( x < 2) prost = 0 . • U liniji 5 vidimo zaglavlje while petlje: kljuˇna rijeˇ while i uvjet (naveden u oblim c c zagradama) do kada se petlja izvrˇava. Primijetite da smo slovo l dodali i prilikom uˇitavanja varijable dbl u primjeru c 5. Format %u najavljuje c uˇitavanje varijable tipa unsigned int. te ispisuje je li on s c prost ili nije. • Takoder u deklaraciji. Napiˇite dio programa koji uˇitava prirodni broj x.2. To je zato jer je double zapravo long float. ne nuˇno u z c z unsigned int). p r o s t = 1 . prirodne brojeve moˇemo spremati i u “obiˇan” int (dakle. while ( p r o s t && p < x ) { i f ( x % p == 0 ) p r o s t = 0 . c s umjesto njih moˇemo pamtiti duplo viˇe pozitivnih brojeva. pa je dobro imati varijable koje mogu pamtiti ˇto viˇe c s s vrijednosti.1. Ako je on istinit. c Napomena 8. s c a n f ( ”%d” . Varijable s atributom z s unsigned se u raˇunalu pamte kao obiˇni binarni brojevi. jer nema potrebe za dvojc c nim komplementima.1. .80 8. s s U praksi. s 1 2 3 4 5 6 7 int x .2. p = 2 .2. compileru dajemo do znanja da ´emo u tu varijablu pohranjivati iskljuˇivo nenegativne vrijednosti (engl. a moˇe prouzroˇiti c c z c probleme (kako ´emo vidjeti u jednom od zadataka). Kako ovdje radimo s potencijama. unsigc c ned znaˇi “bez predznaka”). • U liniji 4 uˇitavamo cjelobrojnu vrijednost u varijablu x. Rjeˇenje. s Nakon svakog izvrˇavanja tijela petlje. izvrˇavanje programa se nastavlja nakon petlje. Uvjet petlje se ne provjerava u toku izvodenja tijela petlje! Zadatak 8. provjerava se uvjet. c s vrijednosti ´e brzo rasti.

&n ) . k = 1. INKREMENT).2. f a k t ) .2. p r i n t f ( ” U n e s i t e n : ” ) . s c a n f ( ”%d” . Na primjer. premjeˇtanjem) inicijalizacije i inkrementa: s s 1 2 int k . } Navedeni programski isjeˇak je ekvivalentan sljede´em kodu: c c 1 2 3 4 5 6 7 8 9 int k . prethodni zadatak smo mogli rijeˇiti i isz s puˇtanjem (tj. 8.2 for()-petlja Zadatak 8. z Kod for() petlje imamo tri polja: for(INICIJALIZACIJA. } i f ( p r o s t ) p r i n t f ( ” Broj j e p r o s t . k . Rjeˇenje. n . f a k t = 1 . k <= n . f a k t = 1 . e l s e p r i n t f ( ” Broj n i j e p r o s t .8. . for()-petlja 81 8 9 10 11 p++. } Prikazana konverzija for() u while() se uvijek moˇe provesti. n . k++) { f a k t ∗= k . s 1 2 3 4 5 6 7 int k . while ( k <= n ) { f a k t ∗= k . for ( k = 1 . k . f a k t ) . \ n” ) . Nije nuˇno navesti sva polja. n . s c a n f ( ”%d” . te ispisuje koliko je s c k! za sve prirodne k manje ili jednake n. k++. &n ) . p r i n t f ( ”%d ! = %d\n” . UVJET.1. f a k t = 1 . p r i n t f ( ”%d ! = %d\n” . p r i n t f ( ” U n e s i t e n : ” ) . \ n” ) . Napiˇite dio programa koji uˇitava prirodni broj n.

3 do. s c a n f ( ”%d” . p r i n t f ( ”Suma u c i t a n i h b r o j e v a j e %d . k++. z s Kod while() i for(). Primijetite da smo varijabli x pridruˇili vrijednost 1 (mogla je biti bilo koja vrijednost razz liˇita od nule!). \ n” . \ n” . k <= n .while()-petlja Ponekad ˇelimo da se dio programa izvrˇi nekoliko puta. koristimo do. for ( . sum += x . Ovaj kod trivijalno moˇemo pretvoriti u while() ili for() na sljede´i naˇin z c c 1 2 3 4 5 6 7 8 9 int sum = 0 . c s Rjeˇenje.. p r i n t f ( ”Suma u c i t a n i h b r o j e v a j e %d .3.. ali bezuvjetno barem jednom. }. &x ) . do { p r i n t f ( ” Unesite broj : ” ) . &n ) . x = 1 . sum += x .. p r i n t f ( ”%d ! = %d\n” . Zadatak 8. } while ( x != 0 ) . f a k t ) . ) { f a k t ∗= k . Napiˇite dio programa koji uˇitava prirodne brojeve i ispisuje njihovu s c sumu. } Primijetite da separatori izmedu polja (. s c a n f ( ”%d” .) moraju ostati! 8.82 8. uvjet se provjerava prije prvog izvrˇavanja tijela petlje. sum ) . Petlje 3 4 5 6 7 8 9 p r i n t f ( ” U n e s i t e n : ” ) . Uˇitavanje treba prekinuti kad korisnik upiˇe vrijednost 0. &x ) . k .1.while petlju. k = 1. while ( x != 0 ) { p r i n t f ( ” Unesite broj : ” ) . sum ) . s 1 2 3 4 5 6 7 8 9 int sum = 0 . Da bismo s tu (prvu) provjeru izbjegli. Bez toga.. x . program bi bio neispravan jer ne smijemo ˇitati vrijednost c c . s c a n f ( ”%d” .

slaˇemo for() petlju: z 1 2 3 4 for ( p r v i k o r a k = 1 .while petlju: c c 1 2 3 for ( INICIJALIZACIJA . Program treba ispisati produkt svih brojeva koje je korisnik uˇitao. nula bi poniˇtila rezultat..8. u while() i for(). pomo´u pridruˇivanja ili z c z scanf()). c Primjer 8. c Rjeˇenje. while ( p r v i k o r a k | | UVJET) { prvi korak = 0.3. no postoji i “recept” koji uvijek vrijedi.1. ali ima inicijalizaciju. for() petlja nema inkrement. ) { prvi korak = 0. Zadaci 83 varijable prije nego joj pridruˇimo neku vrijednost (npr.2. Pretvorite sljede´e programske isjeˇke u do.1.4. Pretvorite programski kod 1 2 3 do { TIJELO . INKREMENT) { TIJELO . Ovdje smo iskoristili pomo´nu varijablu x.4 Zadaci Zadatak 8. To smijemo raditi u sluˇaju s c c sume jer ona ostaje nepromijenjena. } while (UVJET ) . } Analogno.4. TIJELO . } Ovdje. No. Zadatak 8. } 8..1. u sluˇaju produkta.3. } i 1 2 3 while (UVJET) { TIJELO . c s pa na to treba paziti. U zadatku 8. uˇitanu nulu smo pribrojili sumi. . p r v i k o r a k | | UVJET. To radimo koriˇtenjem pomo´ne varijable koja ´e biti istinita samo prilikom prve pros c c vjere uvjeta (te ´e tako osigurati da se tijelo petlje barem jednom izvrˇi): c s 1 2 3 4 5 prvi korak = 1. UVJET. TIJELO . Napiˇite dio programa koji uˇitava cijele brojeve dok korisnik ne upiˇe s c s nulu.3.

4. c Rjeˇenje. } while ( x != 0 ) . po redu . i ++. −1). sada ne moˇemo krenuti od najmanjeg broja jer takav ne postoji u s z z skupu cijelih brojeva. Na ˇalost. x . z c . max ) . Takoder. i f ( x > max) { max = x . Dakle. do { p r i n t f ( ” Unesite broj : ” ) . p r i n t f ( ” Produkt u c i t a n i h b r o j e v a j e %d . Napiˇite dio programa koji uˇitava prirodne brojeve dok korisnik ne upiˇe s c s nulu. p r i n t f ( ” N a j v e c i u c i t a n i b r o j j e %d . znamo da ´e svi biti nenegativni. i f ( x != 0 ) prod ∗= x . Program treba ispisati vrijednost najve´eg uˇitanog broja. te koji je redni broj samog c maksimuma. Zadatak 8. im ) . prod ) . Zadatak 8. Napiˇite dio programa koji uˇitava cijele brojeve dok korisnik ne upiˇe s c s nulu. treba zadati i poˇetnu vrijednost varijabli i i im. p r i n t f ( ” %d . Poˇto uˇitavamo prirodne brojeve. te koji je on (po redu) c c uˇitan. } } while ( x != 0 ) . s s c c moˇemo pretpostaviti da je maksimum neki negativni broj (npr.84 8.4. te koji je on (po redu) c c uˇitan. i = 0 .3. &x ) . moramo pamtiti i koji broj (po redu) uˇitavamo. Petlje 1 2 3 4 5 6 7 8 9 int prod = 1 . u c i t a n ” . c Rjeˇenje. im = i .2. s c a n f ( ”%d” . do { p r i n t f ( ” Unesite broj : ” ) . im . \ n” . s c a n f ( ”%d” . &x ) . x . \ n” . Zbog toga je bolje prvi broj uˇitati posebno i odmah tu vrijednost c pridruˇiti varijabli max. c z 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int max = −1. c c Nadalje. Program treba ispisati vrijednost najve´eg uˇitanog broja. pa ´e prvi uˇitani z c c broj sigurno biti ve´i i onda ´e postaviti ispravnu vrijednost maksimuma. Za to ´e sluˇiti varijable i (kao index) i im (kao index maksimuma).

p r i n t f ( ” %d . To nije morala biti vrijednost 1. &x ) . i ++. i f ( i == 1 | | ( x && x > max ) ) { max = x . p r i n t f ( ” Unesite broj : ” ) . im . } } p r i n t f ( ” N a j v e c i u c i t a n i b r o j j e %d . nego bilo koja koja zadovoljava uvijet while() petlje (x != 0). Prikazani naˇin djeluje op´enito (dakle. Primijetite da smo sada varijabli x morali zadati inicijalnu vrijednost koja osigurava ulazak u petlju u prvom koraku. po redu . im = i . Zadatak 8. s c a n f ( ”%d” . te uˇitava n realnih s c c brojeva.4. u c i t a n ” . Zadaci 85 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int max . } } p r i n t f ( ” N a j v e c i u c i t a n i b r o j j e %d . s c a n f ( ”%d” . &x ) . while ( x != 0 ) { p r i n t f ( ” Unesite broj : ” ) . c c Uputa. im ) . i f ( x && x > max) { max = x . Kad petlja treba imati unaprijed odredeni broj koraka. Preporuˇa se uzeti inicijalizaciju i = 0 i uvjet i < n. u c i t a n ” . x = 1 . Program treba ispisati sumu najve´eg i najmanjeg uˇitanog broja. max ) . i ++. mogao je biti ispravno rjeˇenje prethodnog zac c s datka). Drugi mogu´i naˇin je izoliranje prvog koraka (u ovisnosti o parametru i): c c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int max . \ n” . im = i . x . p r i n t f ( ” %d . max = x .4. im = 1 . s c a n f ( ”%d” . i = 1 . i = 0 .4. Napiˇite dio programa koji uˇitava prirodni broj n.8. po redu . \ n” . praktiˇno je upotrijebiti c for(). jer je tako lakˇe raditi s c s poljima (koja ´emo kasnije obraditi). im ) . &x ) . max ) . c . while ( x != 0 ) { p r i n t f ( ” Unesite broj : ” ) .

i ++) povrh /= i . To smijemo napraviti zato jer znamo da je k uvijek cijeli broj! Inaˇe. i −−) povrh ∗= i . Program treba ispisati sumu svih parnih i produkt svih neparnih brojeva. te ispisuje s c n koliko je k . k!(n − k)! No.4. (n − k)! k! ovisno o tome kakvi su n i k. } p r i n t f ( ” R e z u l t a t : %d\n” . i f (n < 2 ∗ k) { for ( i = n . s c a n f ( ”%d” . Napiˇite dio programa koji uˇitava prirodne brojeve n i k. c Zadatak 8.1. ˇto moˇe izazvati overflow. tj. i <= n − k . inicijalizacije i uvjeta).86 8. Rjeˇenje. n .6. i neparan . for() petlja moˇe i´i i “prema gore” i “prema dolje”. pripadna suma je 0. i ++) povrh /= i . k . p r i n t f ( ” U n e s i t e n : ” ) .7.4. i > n − k . i −−) povrh ∗= i . Primijetimo da promjenom inkrementa (i. Petlje Zadatak 8. Napiˇite dio programa koji uˇitava prirodni broj n. p r i n t f ( ” U n e s i t e k : ” ) . morali bismo paziti da dijeljenje bude realno.4. Zadatak 8. for ( i = 1 . .5. Prva formula je “bolja” ako je n − k < k. for ( i = 1 . i <= k . s c a n f ( ”%d” . Primijetimo da su dijeljenja u linijama 6 i 9 u rjeˇenju prethodnog s n zadatka cjelobrojna. Zbog toga je puno bolje c s z raˇunati c n · (n − 1) · · · · · (n − k + 1) n · (n − 1) · · · · · (k + 1) ili . opet je praktiˇno upotrijebiti for(): c c 1 2 3 4 5 6 7 8 9 10 11 int i . povrh = 1 . } else { for ( i = n . shodno tome. Prema definiciji vrijedi: s n k = n! . z c Napomena 8. n < 2k. pripadni produkt je 1. Sliˇno prethodnom programu. ako nije uˇitan niti jedan c c neparan broj. gdje je ai = 1. Ako nije uˇitan niti jedan paran broj. i > k . povrh ) . &n ) . te uˇitava n cijelih s c c brojeva. Napiˇite dio program koji za zadani prirodni broj n ispisuje vrijednost s izraza n i=1 ai · i.4. &k ) . faktorijele su ˇesto veliki brojevi. i paran 3.

1. while ( p r o s t && p < x ) { i f ( x % p == 0 ) p r o s t = 0 .2. z Petlje se mogu smjeˇtati jedna u drugu. x .2 smo vidjeli kako se provjerava je li broj prost. } p r i n t f ( ”%d\n” . p r o s t . tj.5: s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <s t d i o . Podsjetimo se: izraz i % 2 vra´a ostatak pri dijeljenju i s 2. prod ) . return 0 . Zadaci 87 Rjeˇenje. s c a n f ( ”%d” . rezultat je nula. p = 2. s da jedna petlja ne bi naruˇila vrijednosti o kojima ovisi uvjet druge petlje.4. i <= n .8. i . s c a n f ( ”%d” . Sad ´emo taj s c programski kod kombinirati s rjeˇenjem zadatka 8. Rjeˇenje. } i f ( p r o s t ) prod ∗= x . r e s = 0 . ako je broj c c neparan). i < n . h> int main ( void ) { int n . &n ) . Uz for() petlju. &x ) . Pri tome treba paziti kako koristimo varijable.4. p . uvjet je laˇan. Poˇto c s ga koristimo kao uvjet. p r i n t f ( ”%d\n” . Napomena 8. for ( i = 0 . i ++) r e s += i ∗ ( i % 2 ? 3 : 1 ) . te ispisuje produkt s c prostih.4. for ( i = 1 . prost = (x > 1). napiˇimo i jedan cijeli program: s Zadatak 8. Ako je broj paran. U zadatku 8. } . prod = 1 . taj uvjet ´e biti istinit ako je ostatak razliˇit od 0 (tj. p++. r e s ) .4. s Za razliku od dijelova programa.8. p r i n t f ( ” Unesite n : ” ) . i ++) { p r i n t f ( ” Unesite broj : ” ) . ovdje ´e nam pomo´i uvjetni operator: s c c 1 2 3 4 int i . Napiˇite program koji uˇitava n prirodnih brojeva.

} p r i n t f ( ” R e z u l t a t : %d\n” . sum . s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int x . Napiˇite dio programa koji za zadane prirodne brojeve n i b (b ≥ 2) s ispisuje koliko znamenaka ima dekadski broj n ako ga zapiˇemo u bazi b.9. } p r i n t f ( ”Suma znamenaka : %d\n” .4. U ˇemu je greˇka i kako ju ispraviti (a da poruka ostane kako smo ju upravo s c s naveli)? Uputa. sum = 0 . t . . if (x) { t = x. i ++. Vrijednost koju n ima prije petlje treba saˇuvati u pomo´noj varic c jabli jer uzastopnim dijeljenjima tu vrijednost gubimo! Zadatak 8.”..88 8. &x ) .11.\n". while ( t > 0 ) { sum += ( t % 7 ) . s 1 2 3 4 5 6 int i = 0 . Napiˇite dio programa koji uˇitava prirodne brojeve dok ne uˇita nulu..4. bio pogreˇan. s Rjeˇenje. s c c Za svaki broj (osim nule) treba ispisati sumu njegovih znamenaka u bazi 7. } } while ( x ) . Petlje Zadatak 8. sum ) . Isprobajte program na raˇunalu i primijetite da ´e ispis uvijek zapoˇinjati s c c c “Broj 0 u bazi. b.4. t /= 7 . while ( n > 0 ) { n /= b . i). n. i ) . Primijetite da bi u rjeˇenju prethodnog zadaka ispis s printf("Broj %d u bazi %d ima %d znamenaka. do { p r i n t f ( ” U n e s i t e b r o j : ” ) . Rjeˇenje. Zadatak 8.10. s c a n f ( ”%d” .

Kao ˇto vidimo. a zatim uˇitava pris c c rodne brojeve dok ne uˇita nulu. t = x. s Zadatak 8. max = 0 .4. Program treba ispisati sumu najve´ih znamenaka svih c c uˇitanih brojeva zapisanih u bazi b. max = 0 . Ovakvim zadacima treba pristupiti oprezno. onda ´e se ona za svaki uˇitani c c broj “vra´ati” na nulu. &x ) .while petlje. } while ( t ) . p r i n t f ( ”Suma n a j v e c i h znamenaka : %d\n” . . do { p r i n t f ( ” U n e s i t e b r o j : ” ) . Traˇimo i s c z neki maksimum – ali po jedan za svaki uˇitani broj – pa njega moramo inicijalizirati c unutar petlje u kojoj uˇitavamo brojeve! Pogledajmo dvije ˇeste greˇke: c c s 1. max . s c a n f ( ”%d” .. Nema recepta gdje ide ispis rezultata. zajedno s ˇestim greˇkama koje nac z c s vodimo odmah nakon ispravnog rjeˇenja.12. Primijetimo da traˇimo sumu – jednu z za cijeli program – ˇto znaˇi da nju treba inicijalizirati izvan svih petlji. c Rjeˇenje. } sum += max .3. s c a n f ( ”%d” . sum ) .. sum .4.8. Zadaci 89 Napomena 8. pa ´e na kraju imati vrijednost jednaku najve´oj znamenci c c c posljednjeg uˇitanog broja (a to je 0): c 1 2 3 4 5 6 7 8 do { sum = 0 . while ( x > 0 ) { i f (max < ( x % b ) ) max = x % b . Ako sumu inicijaliziramo unutar do.4. t . Napiˇite dio programa koji uˇita prirodni broj b. rezultat se moˇe ispisati i u s z tijelu petlje. x /= b . to treba shvatiti iz z teksta zadatka! Sljede´i zadatak je izuzetno vaˇan za razumjeti. while ( x > 0 ) { i f (max < ( x % b ) ) max = x % b . s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int x . t = x. ne nuˇno izvan nje. &x ) . p r i n t f ( ” U n e s i t e b r o j : ” ) . sum = 0 . ako zadatak zahtijeva. x /= b .

od prije) biti 9. No.while petlje!) usporedivati s 1 i 9 (od broja 19) i dobit ´e c (ispravno) najve´u znamenku drugog broja: 9. pa nam ta varijabla viˇe nema nikakvu korisnu vrijednost (nakon izvrˇavanja s s petlje. jer se max postavlja na nulu c samo prije tijela do. 19. uvjet u vanjskoj while() petlji ovisi o t. 19.. Ta razlika proizlazi iz naˇina na koji te varijable koristic mo. pa uvjet ovisi o njenoj poˇetnoj vrijednosti s s c pospremljenoj u varijabli t. t = x. Kako je su i 3 i 1 c manji od 9. Isprobajte za b = 10 i uˇitane brojeve 17. u rjeˇenju ovog zadatka. Naime. } while ( t ) . max = 0 . To ´e biti vrijednost varijable max nakon prvog c c izvodenja tijela petlje. unutarnja petlja dijeli jednu od tih varijabli dok njena vrijednost ne padne na nulu. Naravno. ovi naˇini su ekvivalentni. while ( x > 0 ) { i f (max < ( x % b ) ) max = x % b . &x ) . dakle oba ispravna. do { p r i n t f ( ” U n e s i t e b r o j : ” ) . Zatim ´e taj 7 (nepromijenjen. dok je u s prethodnom zadatku ovisio o x. pa ´e ispasti suma c c c 7 + 9 + 9 = 25 ˇto je pogreˇno! s s Dodatno. s c a n f ( ”%d” . a to ´e (opet. za tre´i broj. pa uvjet ovisi o nepromijenjenoj varijabli x. onda se najve´a znamenka brojeva uˇitanih c c nakon prvog ne´e dobro raˇunati: c c 1 2 3 4 5 6 7 8 9 10 11 sum = 0 . uvjet u vanjskoj petlji mora ovisiti o z originalnom uˇitanom broju. 31 i 0 (suma bi trebala biti 7 + 9 + 3 = c 19. no umjesto toga program ´e izraˇunati najve´u znamenku broja c c c 17 i ona ´e (ispravno) ispasti 7. c 2.. dok u ovom zadatku c u unutraˇnjoj petlji “troˇimo” varijablu x...while. } sum += max . 31 i 0. c . usporedivat ´e c c c znamenke 3 i 1 s maksimumom. Petlje 9 10 11 } sum += max . Zato u prethodnom zadatku u unutraˇnjoj petlji “troˇimo” c s s pomo´nu varijablu t. vrijednost je nuˇno nula!). a ispast ´e 0). Suma bi opet trebala biti c 7 + 9 + 3 = 19. S druge strane. x /= b . vrijednost varijable max ´e i za tre´i broj ostati 9. Ako max inicijaliziramo izvan do. } while ( t ) . Isprobajte za b = 10 i uˇitane brojeve 17.90 8.

gdje je c ∈ R neka konstanta. Dakle. i <= lmt . n . Malo o sloˇenosti z 91 8.5 Malo o sloˇenosti z Ve´inu zadataka mogu´e je rijeˇiti na viˇe naˇina. p r i n t f ( ”%d\n” . pa niti kod njih ograniˇenje i ≤ n ne uvodi c 2 probleme. To znaˇi da program z c koji radi 2 puta brˇe od drugog programa nije interesantan (u terminima sloˇenosti). dana situacija je mogu´a samo za brojeve 1. n / i ) . n .5. &n ) . pri tome zanemaruju´i dobitke u z brzini koji se mogu dobiti jednostavnom kupnjom brˇeg hardwarea. q > n . djeljivi su samo s 1 i sa samim sobom. poboljˇanje je i svaki onaj program koji radi s c s + c u vremenu c · n sekundi. n ) . te ispisuje sve djelitelje s c broja n (proizvoljnim redoslijedom. i . primijetit ´emo da ne moˇe biti p. lmt = n / 2 . i ) . c c s s c z c Sloˇenost algoritama bavi se usporedivanjem algoritama. i ++) i f ( ! ( n % i ) ) p r i n t f ( ”%d\n” . lmt . c Rjeˇenje (jednostavno). i ++) i f ( ! ( n % i ) ) p r i n t f ( ”%d\n%d\n” . No. bez obzira na veliˇinu same konstante c. ali svakog toˇno jednom). dok z z onaj koji za ulaz n ∈ N (ˇto god n bio) radi u vremenu n sekundi umjesto n2 sekundi s smatramo velikim poboljˇanjem. No.1. Drugim rijeˇima. jer bismo onda imali c z 2 n=p·q > n2 ⇒ n < 4. a neki “sporiji”. Napiˇite dio programa koji uˇitava prirodni broj n. ako pogles damo rastav n = p · q. c z tj. Zadatak 8. for ( i = 1 . to nisu sloˇeni brojevi. od kojih su neki “brˇi”. Dapaˇe.5. . 4 U ovom rjeˇenju provjeravamo djeljivost sa svim brojevima od 1 do n. &n ) . s c a n f ( ”%d” . brˇi algoritam je: c z Rjeˇenje (dvostruko brˇe). s z 1 2 3 4 5 6 7 8 int i .8. i f (n > 1) for ( i = 1 . s c a n f ( ”%d” . i <= n . s 1 2 3 4 5 int i . 2 i 3.

pa moˇe zbuniti kod ˇitanja programa (prilikom uˇenja ili traˇenja greˇaka). U terminima sloˇenosti z c z algoritama. &n ) . Za limit nismo uzeli jednoslovnu pokratu jer je slovo “l” presliˇno broju 1. pa ostaje upitno je li (i koliko) ovakav proc c gram uop´e brˇi od prvog rjeˇenja (raˇunalo obavlja razliˇite zada´e razliˇitom brzinom). To se moˇe s c z rijeˇiti dodatnim uvjetom: s Rjeˇenje (ispravak prethodnog). t . lmt . algoritmi su jednako sloˇeni (oba su linearni!). else p r i n t f ( ”%d\n%d\n” . dok slovo “t” oznaˇava privremenu varijablu. i <= lmt . i ) . for ( i = 1 . i . . nego samo jednom. for ( i = 1 . prilikom raˇunanja sloˇenosti algoritama. lmt = n / 2 . n ) . i <= lmt . i ++) if ( ! ( n % i )) p r i n t f ( ”%d\n” . lmt = n / 2 . i ++) if ( ! ( n % i )) i f ( ( t = n / i ) <= lmt ) p r i n t f ( ”%d\n” . U ovim rjeˇenjima smo uveli pomo´nu varijablu lmt koja sluˇi tome da se izraz n / 2 s c z ne raˇuna u svakom koraku petlje. &n ) . int i . s c a n f ( ”%d” . n . c c c engl. s c a n f ( ”%d” . 2 i 4 za n = 16). s 1 2 3 4 5 6 7 8 9 10 int i . temporary. neki djelitelji ´e se ispisati dva puta (npr. Petlje Ovaj program ´e se izvoditi dvostruko brˇe od prethodnog. lmt . i zbog brzine izvrˇavanja i zbog preglednosti programa: rijeˇ “lmt” je z s c izabrano kao pokrata engleske rijeˇi limit. i inzistira da se algoritmi razlikuju c z za viˇe od konstantnog faktora. s s 1 2 3 4 5 6 7 8 n 2 < x < n. i ) . c z s c c c c Zbog toga se. z Joˇ gore. z c c z s Dodatni uvjeti znaˇe i dodatno raˇunanje. n . no to znaˇi da smo jedc z c nako ubrzanje mogli dobiti i kupnjom dvostruko brˇeg raˇunala. t ) . s Ako iskoristimo ˇinjenicu da ne postoji x ∈ N takav da je n djeljiv s x i c onda zadatak moˇemo rijeˇiti i ovako: z s Rjeˇenje (poboljˇanje prethodnog).92 8. p r i n t f ( ”%d\n” . Takva uvodenja pomo´nih varijabli c c su uvijek poˇeljna.

h> #include <math . Modificirajte uvjet petlje. i <= lmt . odnosno 4 puta. ali √ da i dalje radi provjere samo za i ≤ n. tj. Malo o sloˇenosti z 93 Postignuto ubrzanje je i dalje dvostruko (dakle. Uputa.5. ˇto je ˇetverostruko.3.5. u ovom je sluˇaju nuˇno dodati i opciju -lm. pa je c ovo rjeˇenje zaista manje sloˇeno! s z √ Granicu n ne moˇemo dodatno smanjiti. ˇto je s ubrzanje od 8. ˇto nas navodi na zakljuˇak da je granica (varijabla l u programima) mogla biti jednaka s c √ n. n . } Na poˇetku je bilo potrebno dodati #include<math. i ++) if ( ! ( n % i )) p r i n t f ( ”%d\n%d\n” . No. s z 1 2 3 4 5 6 7 8 9 10 11 12 #include <s t d i o . za n = 64. Primijetimo da iz moˇemo zakljuˇiti da je z c p≤ n=p·q √ n ili q ≤ √ n. &n ) . neovisno o n). Zadatak 8. Prilikom compiliranja u komandnoj liniji.5. return 0 . n / i ) . Na primjer.h> zbog koriˇtenja matematiˇke c s c funkcije koja radi s realnim vrijednostima. dobiveno ubrzanje raste s veliˇinom ulaza n. Takvo rjeˇenje zahtijeva i poziv matematiˇke funkcije sqrt(): s c Rjeˇenje (manja sloˇenost). c . umjesto starih 64 odnosno 32. odnosno dvostruko s s s c ubrzanje. petlja se vrti 8 puta. za n = 16 petlja se vrti 4 umjesto 16 s z (u prvom rjeˇenju) ili 8 puta (u drugom rjeˇenju). s Zadatak 8.8. lmt = s q r t ( n ) . lmt .2. ˇto se pokazuje jednostavnim traˇenjem z s z protuprimjera (npr. i . Napiˇite dio programa koji za zadani prirodni broj n ispisuje sve njegove s proste djelitelje (svakog toˇno jednom). c z Ovo rjeˇenje je zaista manje sloˇeno. Dakle. konstantno. s c a n f ( ”%d” . za n = 9 moramo izvrˇiti provjere od 1 do 3). for ( i = 1 . Modificirajte prethodni program tako da ne koristi funkciju sqrt(). h> int main ( ) { int i .

dok god je n > 1). Takvo rjeˇenje s ostavljamo ˇitateljima za vjeˇbu. Npr. x ) . te provjera za svakoga je li prost ili nije. n /= x . while ( n > 1 ) { if ( ! ( n % x)) { p r i n t f ( ”%d\n” . onda bi nuˇno bilo a. Rjeˇenje. } x++. x ) . zapravo ima jednostavnije c rjeˇenje: s Zadatak 8. za n = 96 = 25 · 31 program treba ispisati: 2^5 3^1 . Petlje Rjeˇenje.94 8.4. ˇto je kontradiktorno z s pretpostavci da je x najmanji takav broj. te uz svakoga napiˇe koliko puta se pojavljuje u c s rastavu broja n na proste faktore. while ( n > 1 ) { while ( ! ( n % x ) ) { p r i n t f ( ”%d\n” . Takav broj nuˇno mora biti prost. Naizgled jednostavan naˇin za napisati ovaj program je traˇenje svih djelitelja s c z (kao u prethodnim zadacima). c z Umjesto opisanog pristupa. c Idu´i korak je dijeljenje n s pronadenim x dok god je to mogu´e.5.5. Napiˇite dio programa koji za zadani prirodni broj n ispisuje sve njegove s proste djelitelje (svakog toˇno onoliko puta koliko se pojavljuje u rastavu broja n na proste c faktore). Nakon toga se c vra´amo na traˇenje idu´eg najmanjeg djelitelja dobivenog broja. Napiˇite dio programa koji za zadani prirodni broj n ispisuje sve njegove s proste djelitelje (svakog toˇno jednom). while ( ! ( n % x ) ) n /= x . iako naizgled kompliciranija. To ponavljamo dok c z c god ima smisla traˇiti njegove djelitelje (tj.5. jer kad bi postojali a > 1 i b > 1 takvi da z je x = a · b. moˇemo traˇiti najmanji broj x (ve´i od 1) s kojim je n z z c djeljiv. s 1 2 3 4 5 6 7 8 int x = 2 . z 1 2 3 4 5 6 7 8 int x = 2 . b < x i n bi bio djeljiv s a i b. } Sljede´a modifikacija zadatka. } Zadatak 8. } x++.

8.5. Malo o sloˇenosti z

95

Zadatak 8.5.6. Napiˇite dio programa koji uˇitava realni broj x i prirodni broj n, te s c ispisuje koliko je xn . Rjeˇenje. s
1 2 3 4 5 6 7

int i , n ; double x , r e s = 1 ; p r i n t f ( ” Unesite p r i n t f ( ” Unesite for ( i = 0 ; i < p r i n t f ( ”(%g)ˆ%d n : ” ) ; s c a n f ( ”%d” , &n ) ; x : ” ) ; s c a n f ( ”%l g ” , &x ) ; n ; i ++) r e s ∗= x ; = %g” , x , n , r e s ) ;

Primijetimo da izraz res *= n izvrˇavamo n puta, ˇto znaˇi da je sloˇenost programa s s c z linearna. Moˇe li bolje? z Odgovor je (krajnje (ne)oˇekivnano): moˇe. Primijenimo uzastopno kvadriranje. Na c z primjer: x8 = ((x2 )2 )2 , tj. x2 = x · x, x4 = x2 · x2 , x8 = x4 · x4 ,

pa imamo samo 3 mnoˇenja (umjesto 8). Na taj naˇin moˇemo dobiti xn ako je n potencija z c z ˇ od 2. Sto ako nije? Pogledajmo sljede´e primjere: c n = 9 ⇒ n = 8 + 1 ⇒ x = x8 · x1 n = 12 ⇒ n = 8 + 4 ⇒ x = x8 · x4

Dakle, broj n treba prikazati kao zbroj nekih potencija broja 2. Moˇemo li to izvesti za z svaki prirodni n? Naravno. Upravo takav rastav ˇini prikaz broja u binarnoj bazi! Dakle, broj n treba c prikazati u binarnom sustavu. Za prethodne primjere: (9)10 = (1001)2 ⇒ x9 = x2 · x2 (12)10 = (1100)2 ⇒ x12 = x2 · x2
3210
3

3210

3

0

2

Vidjeli smo kako se prebrojavaju i ispisuju znamenke. Sada samo, umjesto ispisivanja binarnih znamenki, treba te znamenke iskoristiti kao uvjet u mnoˇenju. Preciznije, kad z k k god je binarna znamenka 1 mnoˇimo rezultat s x , gdje je x odgovaraju´a potencija od z c x (prvo x1 , pa x2 , pa x4 , pa x8 itd.).
1 2 3

int n , on ; double x , r e s = 1 , pot ;

96

8. Petlje

4 5 6 7 8 9 10 11 12 13 14

p r i n t f ( ” U n e s i t e n : ” ) ; s c a n f ( ”%d” , &n ) ; p r i n t f ( ” U n e s i t e x : ” ) ; s c a n f ( ”%l g ” , &x ) ; pot = x ; on = n ; while ( n > 0 ) { i f ( n % 2 ) r e s ∗= pot ; pot ∗= pot ; n /= 2 ; } p r i n t f ( ”(%g)ˆ%d = %g” , x , on , r e s ) ;
s U najgorem sluˇaju (za n = 2neˇto − 1) imamo 2 puta viˇe mnoˇenja nego n ima c s z znamenaka i toˇno onoliko dijeljenja koliko n ima binarnih znamenaka, a to je log2 n c (dokaˇite!). Dakle, sloˇenost ovakvog potenciranja je logaritamska, ˇto je puno bolje od z z s linearne.

8.6

Promjena toka petlje

Ponekad “usred izvrˇavanja” ˇelimo prekinuti petlju ili “skoˇiti” natrag na uvjet. Vratimo s z c se na zadatak 8.1.2 gdje je trebalo provjeriti je li zadani broj prost. Petlja kojom smo vrˇili provjeru izgledala je ovako: s
5 6 7 8

while ( p r o s t && p < x ) { i f ( x % p == 0 ) p r o s t = 0 ; p++; }

Dakle, u svakom koraku petlje, kao dio uvjeta se provjerava stanje varijable prost. s c Takoder, nakon ˇto varijabli prost zadamo vrijednost 0, program ´e i dalje izvesti liniju 7 (p++;) iako je ona nepotrebna. Prirodan naˇin za provesti provjeru bi, opisno, bio: c
5 6 7 8 9 10 11

dok ( p n i j e ako j e ( x zapamti prekini } povecaj p }

prevelik ) { d j e l j i v s p) { da x n i j e p r o s t provjeru za j e d a n

Petlju prekidamo naredbom break. Prikazani opisni kod moˇemo doslovno prevesti u C z liniju po liniju:
5 6

while ( p < x ) { i f ( x % p == 0 ) {

8.6. Promjena toka petlje

97

7 8 9 10 11

prost = 0; break ; } p++; }

U trenutku kad se izvrˇi naredba break, program bezuvjetno prekida izvrˇavanje tijela s s petlje. Izvrˇavanje programa se nastavlja nakon tijela petlje (na naredbi koja bi se nalazila s u liniji 12). Sliˇno, u zadatku 8.4.11 imali smo petlju: c
3 4 5 6 7 8 9 10 11 12 13 14

do { p r i n t f ( ” U n e s i t e b r o j : ” ) ; s c a n f ( ”%d” , &x ) ; sum = 0 ; if (x) { t = x; while ( t > 0 ) { sum += ( t % 7 ) ; t /= 7 ; } p r i n t f ( ”Suma znamenaka : %d\n” , sum ) ; } } while ( x ) ;

Bilo bi daleko prirodnije jednostavno prekinuti izvrˇavanje petlje onda kad znamo da smo s gotovi (umjesto da ve´i dio tijela petlje “zapakiramo” u if()): c
3 4 5 6 7 8 9 10 11 12 13

do { p r i n t f ( ” U n e s i t e b r o j : ” ) ; s c a n f ( ”%d” , &x ) ; sum = 0 ; i f ( ! x ) break ; t = x; while ( t > 0 ) { sum += ( t % 7 ) ; t /= 7 ; } p r i n t f ( ”Suma znamenaka : %d\n” , sum ) ; } while ( x ) ;

Dapaˇe, ako je x == 0, petlja ´e prekinuti odmah u liniji 6. Ako je x != 0, onda je uvjet c c u liniji 13 istinit, pa nema potrebe da ga provjeravamo. To znaˇi da liniju 13 moˇemo c z zamijeniti s:
13

} while ( 1 ) ;

No, sada nam viˇe ne treba varijabla x, pa ju ne moramo “spaˇavati” upotrebom pomo´ne s s c varijable t. Konaˇno, cijelu petlju moˇemo zapisati ovako: c z
3

do {

&x ) . i < n . x /= 7 .6. sum = 0 . s c a n f ( ”%d” . } } p r i n t f ( ”Suma znamenaka : %d\n” .. i f ( x % 2 ) continue . i f (x % 2 ) .98 8. while ( x > 0 ) { sum += ( x % 7 ) . s c a n f ( ”%d” . while ( x > 0 ) { sum += ( x % 1 0 ) . i < n . s 1 2 3 4 5 6 7 8 9 10 11 12 13 int n . sum ) . &x ) .while petlje). sum ) . Rjeˇenje. te zatim uˇitava joˇ n s c c s prirodnih brojeva. Program treba ispisati sumu svih znamenaka parnih uˇitanih brojeva c (neparne jednostavno ignorira) zapisanih u bazi 10. i ++) { p r i n t f ( ” U n e s i t e b r o j : ” ) . x . problem smo mogli rijeˇiti i pomo´u else: c s c 5 6 7 8 9 for ( i = 0 . naredba continue prekida izvrˇavanje petlje i nastavlja: c c s • s inkrementom.1. s c a n f ( ”%d” . i ++) { p r i n t f ( ” U n e s i t e b r o j : ” ) . x /= 1 0 . i . } p r i n t f ( ”Suma znamenaka : %d\n” . Naredbu break moˇemo ˇitati kao “skoˇi iza tijela petlje”. Pogledajmo zadatak: Zadatak 8. i f ( ! x ) break . Petlje 4 5 6 7 8 9 10 11 12 p r i n t f ( ” U n e s i t e b r o j : ” ) . z c c Na sliˇan naˇin. &n ) . &x ) . . sum . for ( i = 0 .. Napiˇite program koji uˇitava prirodni broj n. } while ( 1 ) . else while ( x > 0 ) { sum += ( x % 1 0 ) . te provjerom uvjeta (kod for() petlje) ili • s provjerom uvjeta (kod while() i do. sum = 0 . p r i n t f ( ” U n e s i t e n : ” ) . s c a n f ( ”%d” . Oˇito.

upravo naredbom break. kako naziv kaˇe. pa se preporuˇa koriˇtenje c c s c s ovih naredbi kad god je to prirodno. z Pogledajmo zadatak sliˇan zadatku 8. } while ( x != 0 ) . } } ili pomo´u negiranog uvjeta: c 5 6 7 8 9 10 11 12 for ( i = 0 . &x ) . i ++) { p r i n t f ( ” U n e s i t e b r o j : ” ) . prod ) . Kako svaki algoritam mora stati nakon konaˇno mnogo koraka (prema c definiciji algoritma!). Ponekad koristimo “beskonaˇne petlje”.6. Obiˇno se koristi vrijednost 1. s 1 2 3 4 5 6 7 8 9 int prod = 1 . i f ( x ) prod ∗= x . p r e k i n i p e t l j u p o v e c a j produkt }.else blokova jedan unutar drugog. } } Naredbe break i continue se uvijek mogu “zaobi´i”. s c a n f ( ”%d” . To su.1: c Zadatak 8. Najprije opisno: c 3 4 5 6 7 radi { ucitaj x ako j e x j e d n a k n u l i . do { p r i n t f ( ” Unesite broj : ” ) . x .2. Petlju smo mogli i drugaˇije napisati. ali kod sloˇenijih problema to moˇe c z z biti izuzetno komplicirano (mnogo if.6.3. c s Rjeˇenje. Promjena toka petlje 99 10 11 12 x /= 1 0 . \ n” . te dodavanje pomo´nih varijabli).. Uˇitavanje treba prekinuti kad korisnik upiˇe vrijednost 0.8. c c . x /= 1 0 . Prisjetimo se: istina je svaka vrijednost razliˇita od nule. Kompliciranje ˇesto dovodi do greˇaka. i f ( ! ( x % 2)) while ( x > 0 ) { sum += ( x % 1 0 ) .. &x ) . s c a n f ( ”%d” . i < n . p r i n t f ( ” Produkt u c i t a n i h b r o j e v a j e %d . petlje ˇiji je uvjet c z c uvijek zadovoljen. Napiˇite dio programa koji uˇitava prirodne brojeve i ispisuje njihov s c produkt. takve petlje je nuˇno prekinuti “na silu”.

1 . onda prekidanje izvrˇavanja c c s petlje nuˇno treba osigurati naredbom break. prod ∗= x . j = %d\n” . smatra se da je on istinit. Npr. } Ovdje to ne izgleda naroˇito korisno. Dakle. i f ( x == 0 ) break . &x ) . Petlje C-ovski. i f ( x == 0 ) break . Ako uvjet for()-petlje nije naveden.100 8. j ) . z Naredbe break i continue utjeˇu samo na izvrˇavanje najdublje petlje u kojoj se c s nalaze. i < 3 . ) { Napomena 8.6. ali kod sloˇenih uvjeta moˇe biti jako praktiˇno. s c a n f ( ”%d” . j < 9 9 9 . s c a n f ( ”%d” . c z z c ako imamo nekoliko uvjeta. prikazani opisni kod bi izgledao ovako: 3 4 5 6 7 do { p r i n t f ( ” U n e s i t e b r o j : ” ) . staviti s da je uvijek istinit). i f ( x == 0 ) break . } ili 3 4 5 6 7 for ( . Svaku petlju obavezno treba nekako prekinuti! Ako uvjet ne osigurava prekidanje petlje za sve mogu´e poˇetne vrijednosti varijabli. liniju 3 iz zadnjeg prikazanog programskog isjeˇka moˇemo jednostavnije zapisati ovako c z 3 for ( . } . ) { p r i n t f ( ” U n e s i t e b r o j : ” ) . i ++) { for ( j = i + 1 . onda ih je teˇko objediniti. prod ∗= x . } while ( 1 ) . &x ) . Primjer 8. j ++) { p r i n t f ( ” U n u t r a s n j a p e t l j a : i = %d . a onda sam uvjet petlje “izostaviti” (tj. } p r i n t f ( ” Vanjska p e t l j a : i = %d\n” . . “razbacanih” po tijelu petlje. pa s je lakˇe svakome zadati da prekine petlju.1.1. s c a n f ( ”%d” . i ) . &x ) .6. Programski kod 1 2 3 4 5 6 7 for ( i = 0 . i . break . prod ∗= x . ili 3 4 5 6 7 while ( 1 ) { p r i n t f ( ” U n e s i t e b r o j : ” ) .

i < n . te pomo´u zvjezdica (“*”) s c c iscrtava pravokutni trokut katete duljine n znakova. for ( i = 0 .6. s c s c jer ´e naredba break prekinuti unutraˇnju petlju odmah nakon ispisa vrijednosti. i . j . i ++) { for ( j = 0 . Oˇito. Zatim treba provjeriti je li broj prost. j ++) p r i n t f ( ”∗” ) . z Zadatak 8. j = 2 Vanjska petlja: i = 1 Unutrasnja petlja: i = 2. s Zadatak 8.3.5. s c a n f ( ”%d” . p r i n t f ( ” U n e s i t e n : ” ) . s 1 2 3 4 5 6 7 8 9 int n . p r i n t f ( ”\n” ) .6. S druge c s c s c s strane. j <= i .8.4. c Uputa. Na primjer. treba se vratiti (pomo´u c continue) na poˇetak petlje. j = 3 Vanjska petlja: i = 2 Dakle. Napiˇite program koji uˇitava prirodne brojeve dok ne uˇita nulu. pa uvjet petlje moˇe uvijek biti istinit. } . &n ) . Ako nije.6. za n = 4 treba ispisati: * ** *** **** Rjeˇenje. s Zadatak 8. j = 1 Vanjska petlja: i = 0 Unutrasnja petlja: i = 1. Napiˇite program koji uˇitava prirodni broj n. pa se izvrˇavanje programa (nakon break) nastavlja upravo na liniji 6. tijelo unutraˇnje for petlje (linije 3 i 4) ´e se izvrˇiti toˇno jednom za svaki i. linija 6 ´e se izvrˇiti za svaki i jer break “skaˇe iza (unutraˇnje) petlje”. Pros c c gram treba ispisati produkt znamenaka (u bazi 8) svih uˇitanih prostih brojeva. Petlju je dobro prekinuti pomo´u break odmah nakon uˇitavanja broja ako je broj c c jednak nuli. Promjena toka petlje 101 ´e ispisati: c Unutrasnja petlja: i = 0. Prethodni zadatak rijeˇite bez break i continue. sva potrebna prekidanja petlje ´e se izvrˇiti pomo´u c c c s c break.6.

1 znak. za n = 4 treba ispisati: * *** ***** ******* ˇ Zadatak 8.6. a horizontalna duljine 2 * n . te pomo´u zvjezdica (“*”) s c c iscrtava pravokutni trokut kojem je vertikalna kateta duljine n znakova. Napiˇite program koji uˇitava prirodni broj n. . te pomo´u s c c zvjezdica (“*”) iscrtava krug radijusa n znakova.6.7 (Slag na kraju). Na primjer.102 8. Petlje Zadatak 8.6. Napiˇite program koji uˇitava prirodni broj n.

1. i f (pom == 0 ) p r i n t f ( ” N e d j e l j a \n” ) . e l s e p r i n t f ( ” Subota \n” ) . . Klasiˇno rjeˇenje. Pomo´u switch(). . rjeˇenje izgleda ovako: c s 103 . Tada ulanˇavanje if()-ova ispas c da nespretno i nezgodno. c s 9. e l s e ( n % 7 == 4 ) p r i n t f ( ” C e t v r t a k \n” ) . pomo´u if() bi bilo: c s c 1 2 3 4 5 6 7 if if if if if if ( n % 7 == 0 ) p r i n t f ( ” N e d j e l j a \n” ) . e l s e ( n % 7 == 2 ) p r i n t f ( ” Utorak \n” ) . 365} s ispisuje na koji dan u tjednu pada n-ti dan u godini (pretpostavite da godina poˇinje c ponedjeljkom). e l s e ( n % 7 == 1 ) p r i n t f ( ” P o n e d j e l j a k \n” ) . e l s e i f (pom == 1 ) p r i n t f ( ” P o n e d j e l j a k \n” ) . e l s e i f (pom == 5 ) p r i n t f ( ” Petak \n” ) . Napiˇite dio programa koji za zadani prirodni broj n ∈ {1. ili. . pogotovo ako blokovi koji se izvrˇavaju moraju imati i neke s zajedniˇke dijelove. .1. e l s e i f (pom == 2 ) p r i n t f ( ” Utorak \n” ) . Zbog toga pribjegavamo upotrebi viˇestrukog grananja. da se smanji koliˇina raˇunanja: c c 1 2 3 4 5 6 7 8 int pom = n % 7 . e l s e ( n % 7 == 5 ) p r i n t f ( ” Petak \n” ) . e l s e i f (pom == 3 ) p r i n t f ( ” S r i j e d a \n” ) . 2. e l s e ( n % 7 == 3 ) p r i n t f ( ” S r i j e d a \n” ) .1 Naredba switch() Primjer 9.Poglavlje 9 Viˇestruko grananje s Ponekad imamo viˇe uvjeta koji ovise o istom izrazu. e l s e i f (pom == 4 ) p r i n t f ( ” C e t v r t a k \n” ) . e l s e p r i n t f ( ” Subota \n” ) .

Ukoliko ˇelimo prekinuti izvrˇavanje naredbi unutra z switch() (tj. . break . case 4 : p r i n t f ( ” C e t v r t a k \n” ) . case 3 : p r i n t f ( ” S r i j e d a \n” ) . case 1 : p r i n t f ( ” P o n e d j e l j a k \n” ) . case 4 : p r i n t f ( ” C e t v r t a k \n” ) . break . case 2 : p r i n t f ( ” Utorak \n” ) . case 5 : p r i n t f ( ” Petak \n” ) . izvrˇavanje prelazi u idu´u granu! s c Primjer 9. case 2 : p r i n t f ( ” Utorak \n” ) . Grana default (nije obavezna!) se izvrˇava ako niti jedan case nema vrijednost kao s zadani izraz (neˇto kao else kod if() petlji). . break . ˇelimo “iza´i” iz switch()). 2.1. Viˇestruko grananje s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 switch ( n % 7 ) { case 0 : p r i n t f ( ” N e d j e l j a \n” ) . Napiˇite dio programa koji za zadane prirodne brojeve p ∈ {1. ali bez upotrebe break: 1 2 3 4 5 6 7 8 9 switch ( n % 7 ) { case 0 : p r i n t f ( ” N e d j e l j a \n” ) . raˇunalo ulazi u prvu granu koja ima vrijednost jednaku vris c s jednosti izraza. . 7} i s n ∈ {1. default : p r i n t f ( ” Subota \n” ) . utorkom ako je p = 2. break . } ´e za n = 4 ispisati: c Cetvrtak Petak Subota Zadatak 9. . case 5 : p r i n t f ( ” Petak \n” ) .1. zadajemo narebu break (jednako kao kod petz c lji).1. c . . Prethodni primjer.). program treba ispisati i idu´i dan. } Prilikom izvrˇavanja. case 3 : p r i n t f ( ” S r i j e d a \n” ) . default : p r i n t f ( ” Subota \n” ) . Ukoliko je dan c koji ispisujete utorak ili petak.104 9.2.1. case 1 : p r i n t f ( ” P o n e d j e l j a k \n” ) . te nastavlja dalje. s Napomena 9.1. 365 − p} ispisuje na koji dan u tjednu pada n-ti dan u godini (pretpostavite da godina poˇinje ponedjeljkom ako je p = 1. . 2. . Ako ne zadamo break. break . itd. . break .

break . Naredba switch() 105 Rjeˇenje. . Napiˇite dio programa koji za zadani prirodni broj n ispisuje je li zadnja s dekadska znamenka broja 3n prost broj ili ne. } Zadatak 9. s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 /∗ R a c u n a n j e n − t e p o t e n c i j e b r o \− j a 3 ∗/ pot = 1 . /∗ Da l i j e z a d n j a z n a m e n k a p r o s t b r o j ∗/ p r i n t f ( ” Zadnja znamenka ” ) . break . ili. default : p r i n t f ( ” n i j e ” ) . case 1 : p r i n t f ( ” P o n e d j e l j a k \n” ) . /∗ Da l i j e z a d n j a z n a m e n k a p r o s t b r o j ∗/ p r i n t f ( ” Zadnja znamenka ” ) . kra´e: c 1 2 3 4 5 /∗ R a c u n a n j e n − t e p o t e n c i j e b r o \− j a 3 ∗/ pot = 1 . break .1.2. case 5 : p r i n t f ( ” Petak \n” ) . \ n” ) . } p r i n t f ( ” p r o s t b r o j . default : p r i n t f ( ” Subota \n” ) . case 3 : p r i n t f ( ” S r i j e d a \n” ) . case 4 : p r i n t f ( ” C e t v r t a k \n” ) . Rijeˇite prethodni program bez upotrebe switch().9. Rjeˇenje. s 1 2 3 4 5 6 7 8 9 10 11 12 13 switch ( ( n + p − 1 ) % 7 ) { case 0 : p r i n t f ( ” N e d j e l j a \n” ) .1.3. case 2 : p r i n t f ( ” Utorak \n” ) . break .1. nabrajamo ih jednu iza druge. break . switch ( pot % 1 0 ) { case 2 : case 3 : case 5 : case 7 : p r i n t f ( ” j e ” ) . while ( n−−) pot ∗= 3 . s Ukoliko dvije grane rade toˇno jednak posao. c Zadatak 9. while ( n−−) pot ∗= 3 .

1.106 9. “prazne grane” moˇemo pobrojati u jedan red.1. default : p r i n t f ( ”D” ) . Zaˇto je ovo “toˇnije”. 1 2 3 4 5 6 7 8 9 10 11 12 switch ( a ) { case 1 : p r i n t f ( ”A” ) . } p r i n t f ( ” j e p r o s t b r o j . while ( n−−) pot = ( 3 ∗ pot ) % 1 0 . } . \ n” ) . Viˇestruko grananje s 6 7 8 9 10 switch ( pot % 1 0 ) { case 1 : case 4 : case 6 : case 8 : case 9 : p r i n t f ( ” n i ” ) . s z Napomena 9. case 3 : i f ( x % 2 ) p r i n t f ( ”1 ” ) . case 4 : break . objaˇnjeno je na predavanjima (overflow).2. Napiˇite sljede´i dio koda bez upotrebe switch() (tj. else p r i n t f ( ”?” ) . samo upotrebom s c if()). case 5 : p r i n t f ( ”C” ) .4. case 2 : p r i n t f ( ”B” ) . raˇunanje zadnje znamenke n-te c c potencije broja 3 mogli smo napisati i toˇnije: c 1 2 pot = 1 . break . Kao ˇto vidimo. U prethodnom programskom isjeˇku. s c s Zadatak 9.

y ∈ Z. %d ) = ” .1 Jednostavne funkcije Zadatak 10. &x ) .1. y ) . &y ) . Program treba ispisati GCD(x. a jedina razlika u tim izvrˇavanjima su o s s s vrijednosti na kojima se taj kˆd izvrˇava. i f ( y < 0 ) y = −y . p r i n t f ( ” U c i t a j t e x : ” ) . On se svodi na dijeljenje ve´eg bros s c ja s manjim dok ostatak pri dijeljenju ne postane jednak nuli. y . Kako ne bismo dva puta pisali isto. i f ( x < y ) { int t = x . Zadatak rjeˇavamo Euklidovim algoritmom. h> int main ( void ) { int x . } 107 . s c a n f ( ”%d” . Funkcije mogu pozivati jedne druge.Poglavlje 10 Funkcije ˇ Cesto neki dio kˆda treba izvrˇiti viˇe puta. pa ˇak i same sebe. x = y . c 10. Napiˇite program koji uˇitava dva cijela broja s c x. s c a n f ( ”%d” . y = t . p r i n t f ( ” U c i t a j t e y : ” ) . c c Rjeˇenje. c c c z 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <s t d i o .1 (Euklidov algoritam). i f ( x < 0 ) x = −x . p r i n t f ( ”GCD(%d . eventualno o s uz mijenjanje naziva varijabli (ˇto lako moˇe dovesti do greˇaka). y) (najve´i zajedniˇki djelitelj brojeva x i y). Ove druge zovu se rekurzivne c funkcije i njih ´emo obraditi u drugom semestru. Tada je rezultat dijeljenja upravo najve´a zajedniˇka mjera poˇetnih brojeva (dokaˇite!). koristimo funkcije – s z s dijelove koda izdvojene u zasebne cjeline. x .

1. } Zadatak 10. Bez upotrebe nizova napiˇite program koji uˇitava razliˇite cijele brojeve s c c a. No. } while ( y ) { int t = x % y . = −y . Program treba ispisati brojeve x. p = gcd ( a . i f (p < x) x = p . q) i y= p. Rjeˇenje. y). return 0 . c ∈ Z. rjeˇenje zadatka bi izgledalo ovako (skica): s s 1 2 3 4 5 6 7 8 9 x = y = gcd ( a . gcd(%d . p r i n t f ( ”x = %d . y = %d . y .c} max GCD(p. u C-u ne postoji funkcija gcd(). x = y. y. naravno. x ) . i f (p > y) y = p .b. x . i f (p > y) y = p . y .108 10. x . y i GCD(x.c} min GCD(p. b. Idealno.b. sloˇiti svoju funkciju: c z 1 2 3 4 5 6 7 8 9 10 #include <s t d i o . pri ˇemu je c x= p. ˇto znaˇi da ili moramo viˇestruko prepisati rjes c s ˇenje prethodnog zadatka (uz prikladnu promjenu vrijednosti varijabli) ili moramo sami s definirati funkciju gcd(). %d ) = %d\n” . Funkcije 15 16 17 18 19 20 21 22 23 24 while int x = y = } (y) { t = x % y. . Mi ´emo. p r i n t f ( ”%d\n” . h> int gcd ( int x .2. i f (p < x) x = p . p = gcd ( b . y = t . int t = x .q∈{a. y ) ) . c ) . c ) . t. i f ( x < 0) x i f ( y < 0) y if (x < y) { int y ) { = −x . x = y . b ) . q). gcd ( x . repliciraju´i rjeˇenje s s c s prethodnog zadatka. Pokuˇajte zadatak rijeˇiti bez upotrebe funkcija (potprograma).q∈{a.

p r i n t f ( ” U c i t a j t e c : ” ) . x . p r i n t f ( ”x = %d . x .c). p = gcd ( a . %d ) = %d\n” . i f (p < x) x = p . y . c s • povrat vrijednosti (linija 14). a varijabla y poprima vrijednost c). b . Varijable x i y u funkciji gcd() su lokalne i nemaju veze s istoimenim varijablama u glavnom programu! U njih se spremaju kopije vrijednosti varijabli s kojima je funkcija pozvana (npr. } return x . y ) ) . p = gcd ( b . naziv funkcije. te s c c c popis formalnih argumenata (i njihovih tipova) koje funkcija prima. kojim prekidamo izvrˇavanje funkcije i zadajemo s koju vrijednost ona vra´a. . y = %d . varijabla x poprima vrijednost a. } Funkcija se sastoji od sljede´ih dijelova: c • zaglavlje (linija 3). Ovaj dio nije obavezan ako funkcija ne vra´a vrijednost. c ) . i f (p > y) y = p . c ) . s c a n f ( ”%d” . p . pozivamo s c samo return. p r i n t f ( ” U c i t a j t e b : ” ) . p r i n t f ( ” U c i t a j t e a : ” ) .1. c c ˇ Zelimo li negdje prekinuti izvrˇavanje funkcije koja ne vra´a vrijednost. gcd ( x . b ) . y . s c a n f ( ”%d” . &a ) . • tijelo (linije 4–14). Jednostavne funkcije 109 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 y = t. i f (p < x) x = p . s c a n f ( ”%d” . } int main ( void ) { int a . Promjene tih lokalnih varijabli ne utjeˇu na vrijednosti varijabli s c kojima je funkcija pozvana (tj. c .. u kojem su redom navedeni tip vrijednosti koju funkcija vra´a c (piˇemo kljuˇnu rijeˇ “void” ako funkcija ne vra´a vrijednost). navode se prazne zagrade (dakle “ime_funkcije()”). return 0 . y . &c ) . u kojima (kao i inaˇe u programu) opisujemo ˇto funkcija radi. kod poziva gcd(a. promjena vrijednosti varijabli x i y ne´e dovesti do izmjene c vrijednosti varijabli a i c). Ako funkcija ne prima nikakve vrijednosti. gcd(%d . x = y = gcd ( a .10. &b ) . i f (p > y) y = p . x .

= −y . y = %d . } (y) { t = x % y. } int max( x . h> int gcd ( int x . te s s sc 1 c (uz dodatni zahvat na ispisu ) skratit na sljede´i oblik: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <s t d i o . y . ali kao vrijednost uzima m-ti parametar. y ) { return ( x < y ? x : y ) . p ) . %2$d ) = %d\n” . } int main ( void ) { int a . c ) . e. p ) . x = min ( x . return x . 1 int y ) { = −x . gcd(%1$d . &c ) . gcd ( x . y . Zbog toga prikazani poziv funkcije printf() ispisuje vrijednosti varijabli x i y na dva mjesta (na mjesta prva dva %d i na mjesta gdje je zadano %1$d i %2$d). y = max( y . y = max( y . . pri ˇemu je m broj. p = gcd ( a . y = t . x = y = gcd ( a . c . x . p r i n t f ( ” U c i t a j t e a : ” ) . x . 3x z s c c i sl. ˇto direktno utjeˇe i na smanjivanje c c s c broja greˇaka. x = min ( x . x = y . b . potprogramima smanjujemo kos s liˇinu pisanja i pove´avamo preglednost programa. s c a n f ( ”%d” . p = gcd ( b . c ) . Rjeˇenje prethodnog zadatka moglo se dodatno raˇˇlaniti na funkcije. Funkcije Kao ˇto smo vidjeli u rjeˇenju prethodnog zadatka. &b ) . p r i n t f ( ” U c i t a j t e b : ” ) . p . b ) . a f neki od uobiˇajenih formata (d. y.). t. s c a n f ( ”%d” .110 10. p ) . p r i n t f ( ” U c i t a j t e c : ” ) . y ) { return ( x > y ? x : y ) . p ) . odgovara formatu %f. i f ( x < 0) x i f ( y < 0) y if (x < y) { while int x = y = } } int min ( x . &a ) . y ) ) . int t = x . Za one koji ˇele znati viˇe: format %m$f. p r i n t f ( ”x = %d . s c a n f ( ”%d” .

for ( i = 2 . i <= n . . Napiˇite funkciju koja kao argument uzima jedan prirodni broj n ∈ N. on je samo jedna od funkcija koja se od ostalih razlikuje iskljuˇivo po specijalnom nazivu (main())! c s Zadatak 10. ovo je KRIVO: c 1 2 3 4 5 6 long int f a k t ( int n ) { long int r e s = 1 . } ˇ Napomena 10.3. tj. i ++) r e s ∗= i . &n ) . s c a n f ( ”%d” . a kao povratnu vrijednost vra´a n! := 1 · 2 · · · · · n. moˇete se uvjeriti tako da pokuˇate rijeˇiti modifikac c s z s s ciju zadatka koja radi s 5 varijabli (umjesto njih 3).1. } Funkciju smo mogli i kra´e napisati. while ( n > 1 ) r e s ∗= ( n−−). return r e s . Ako funkcija prima neku vrijednost. Zbog toga ona ne mora niˇta niti s c s uˇitavati niti ispisivati. s 1. onda tu vrijednost ne smijete u funkciji uˇitavati. Jednostavne funkcije 111 38 39 return 0 . Dakle. long int r e s = 1 . return r e s . da njec c c nom promjenom ne´emo izazvati promjenu varijable koja je pri pozivu funkcije navedena c kao argument: 1 2 3 4 5 6 7 long int f a k t ( int n ) { long int r e s = 1 . while ( n > 1 ) r e s ∗= ( n−−). c Rjeˇenje.1.10. Funkcija prima argumente i vra´a vrijednost. ali ju ipak moˇemo smatrati algoritmom! c z 1 2 3 4 5 6 7 8 long int f a k t ( int n ) { int i .1. Pogledajte strukturu glavnog programa. } Da je rijeˇ o zaista kra´em rjeˇenju. c jer uˇitavanjem gubite zadanu vrijednost argumenta. U C-u. koriste´i ˇinjenicu da je varijabla n lokalna.1 (Ceste greˇke).

Napiˇite funkciju koja kao argument uzima jedan prirodni broj n ∈ N. p r i n t f ( ”%d\n” . Zadatak 10. } 2. s a kao povratnu vrijednost vra´a c n!! := n · (n − 2) · (n − 4) · · · · = 0≤i< n 2 (n − 2i). return x + 1 . Napiˇite funkciju koja kao argument uzima jedan prirodni broj n ∈ N. Napiˇite funkciju koja kao argument uzima jedan prirodni broj n ∈ N.1. return x . x++. Iza return nema smisla niˇta pisati jer se to ne´e izvrˇiti (return prekida izs c s vrˇavanje funkcije). u sljede´em kodu nikad ne´e do´i do ispisa: s c c c 1 2 3 4 int f ( int x ) { return 2 ∗ x .1. Zadatak 10. . x ) .4. Funkcije 7 8 9 return r e s .1. } int h ( int x ) { return ( x % 2 ? x + 1 : x ) . Na primjer. naredbe iza return ima smisla zadavati samo ako je do njih mogu´e do´i bez c c izvrˇavanja samog return-a (npr.6. Zbog toga. s a kao povratnu vrijednost vra´a c (2n + 1)!! := 1 · 3 · 5 · · · · · (2n + 1). s c Zadatak 10. s a kao povratnu vrijednost vra´a c (2n)!! := 2 · 4 · 6 · · · · · (2n) = 2n n!.112 10. } Dakle. u razliˇitim granama if()-a). idu´a funkcija vra´a najmanji parni broj ve´i ili jednak x: c c c c 1 2 3 4 5 int f ( int x ) { i f ( x % 2 == 0 ) return x . } Istu stvar rade i sljede´e dvije funkcije: c 1 2 3 4 5 6 7 int g ( int x ) { i f ( x % 2 == 0 ) return x . moˇete pomo´u return prekinuti izvrˇavanje funkcije samo u nekim sluz c s ˇajevima. } Naravno.5.

Rjeˇenje. i f ( x <= 1 ) return 0 . s 1 2 3 4 5 6 7 8 int a b s i s p r i m e ( int x ) { int i = 2 . te s vra´a 1 ako je |x| prost. pa je njen tip void. s c while() petlja nastavlja s izvrˇavanjem. na vrijednost 2). ali se djeljivost x-a s 3 itd. odnosno 0 ako |x| nije prost.1. Ako n (viˇe) nije djeljiv s p. c c Tvrdnja: Neka je pi najmanji broj (strogo ve´i od 1) takav da je n djeljiv s pi .1.3. ni ∈ N treba svaki pi ispisati ni puta. za n= i pni . x . prekidamo izvrˇavanje funkcije i ona vra´a 0. u drugom koraku i postaje 4. tj. funkciju moˇemo pozvati na sljede´i naˇin: c z c c 1 2 p r i n t f ( ” Broj |%d | %s j e p r o s t .5. Za uˇitani broj x. Petlju vrtimo dok god n ima prostih c c faktora. Funkcija ne vra´a nikakvu vrijednost.1. dok god je strogo ve´i od 1. Dok god je n djeljiv s p.1. Jednostavne funkcije 113 Zadatak 10. while ( i < x ) i f ( ! ( x % i ++)) return 0 . ali se provjerava djeljivost x-a s 2. kako s c bismo u idu´em koraku petlje probali za idu´i broj. c Zadatak 10. Osnovni algoritam s c je ve´ prikazan u zadatku 8. ispisujemo p. Dakle. Napiˇite funkciju koja prima jedan cjelobrojni parametar x ∈ Z. pove´avamo p za jedan. Zadatak 10. z Koriˇtenjem te tvrdnje moˇemo sloˇiti izuzetno brz algoritam za rastav broja na proste s z z faktore. c . \ n” . } U liniji 6. ako je x djeljiv s i. i pi prost.8. Najprije inicijaliziramo pomo´nu varijablu p na najmanju vrijednost strogo ve´u c c od 1 (tj.10. U protivnom. te s vra´a njegovu apsolutnu vrijednost. te n dijelimo s p. u prvom koraku i poprimi vrijednost 3. s c ali se djeljivost provjerava sa starom vrijednoˇ´u od i (jer i pove´avamo post-inkrement sc c operatorom). Napiˇite funkciju koja prima jedan prirodni parametar n ∈ N. te ispisuje s sve njegove proste faktore i to svakog onoliko puta kolika mu je kratnost. pa ´emo ovdje samo podsjetiti kako on radi.7. i f ( x < 0 ) x = −x .9. a b s i s p r i m e ( x ) ? ”” : ” ni ” ) . tj. Napiˇite funkciju koja prima jedan cjelobrojni parametar x ∈ Z. tada c je pi prost (dokaˇite!). return 1 . Vrijednost varijable i pove´ava se za jedan. Zatim provjeravamo djeljivost n s p. Redoslijed ispisa nije bitan. c Rjeˇenje.

te s ispisuje sve njegove proste faktore. To znaˇi da funkcija ima c lokalnu varijablu u kojoj se nalazi kopija vrijednosti s kojom se funkcija poziva. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <s t d i o . prog . h> void f ( int a ) { p r i n t f ( ” F u n k c i j a 1 : a = %d\n” . te s ispisuje sve njegove proste faktore i uz svakog njegovu kratnost. Napiˇite funkciju koja prima jedan prirodni parametar n ∈ N. n /= p .114 10. a ) .10. } int main ( void ) { int x = 1 . while ( n > 1 ) { while ( ! ( n % p ) ) { p r i n t f ( ”%d\n” . parametri se prenose “po vrijednosti”. p r i n t f ( ”Gl . } . 1 : x = %d\n” . p ) .1. p r i n t f ( ”Gl . 2 : x = %d\n” . Funkcija treba vratiti broj razliˇitih prostih faktora koje sadrˇi broj n. Napiˇite funkciju koja prima jedan prirodni parametar n ∈ N.1.11. c z 10. svakog toˇno jednom. x ) . } p++. c Zadatak 10.1. a++. a ) . Zbog toga se promjene argumenata u funkciji ne odraˇavaju na vrijednosti varijabli s kojima je z funkcija pozvana. x ) . return 0 . Primjer 10. p r i n t f ( ” F u n k c i j a 2 : a = %d\n” . Funkcije 1 2 3 4 5 6 7 8 9 10 void p r i n t p r i m e s ( int n ) { int p = 2 . } } Zadatak 10. prog .2.2 Varijabilni argumenti funkcija Kod funkcija u C-u. f (x ).

p r i n t f ( ” F u n k c i j a 2 : ∗a = %d\n” .1 i 10. x ) . 1: x = = = = 1 1 2 2 Iako radimo naizgled istu stvar. ∗a ) . } int main ( void ) { int x = 1 . bez utjecaja korisnika na stvarne vrijednosti). p r i n t f ( ”Gl . Varijabilni argumenti funkcija 115 No. Zaˇto? Pogledajmo ˇto se dogada u memoriji (slike 10. 1: x = 1 Funkcija 1: a = 1 Funkcija 2: a = 2 Gl. prog .2). return 0 . To znaˇi da je vrijabla a kopija varijable x. f (&x ) . s s Obje slike prikazuju dijelove memorije u kojima se nalaze varijable x i a. 2 : x = %d\n” .2. ˇto se dogada ako u funkciju proslijedimo adresu varijable i onda pristupamo s direktno toj adresi? Primjer 10.2. varijabla a je tipa int i prilikom poziva funkcije poprima vrijednost parametra x. promijenili smo varijablu koja je bila pozivni argument funkcije. u stvarnosti ih s dodjeljuje raˇunalo. p r i n t f ( ”Gl . Lijevo od memorije su popisane memorijske lokacije (ovdje ad hoc izmiˇljene. prog. prog. 1 : x = %d\n” .2.1. } Primjer 10. h> void f ( int ∗a ) { p r i n t f ( ” F u n k c i j a 1 : ∗a = %d\n” . prog. 1: x = 1 dok ´e primjer 10. ∗a ) .2. prog . Evaluiranjem izraza a++ mi c .2.10. U primjeru 10. ( ∗ a)++.1 ispisat ´e c Gl. prog. 1: x Funkcija 1: *a Funkcija 2: *a Gl. jedna za drugom. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <s t d i o .2 ispisati c Gl. Bitno je da te lokacije c idu po redu.2. x ) .

Zbog toga. Sto ispisuje sljede´i program? c 1 2 3 4 5 6 7 #include <s t d i o . h> void f ( int ∗a . c = &b . . .2. } . . . u primjeru 10. .2. ( ∗ c )++. .116 10. Analogno tome. Prouˇite dobro.1 mijenjamo vrijednost te kopije.1. . odnosno adresa memorijske lokacije na kojoj se nalazi neka vrijednost tipa int). s S druge strane. izraz *a oznaˇava memorijsku lokaciju na adresi s c a. . .1: Memorija u primjeru 10.2. c ˇto je adresa varijable x. 1 1234570 1234569 1234568 1234567 1234570 1234569 x 1234568 1234567 x Slika 10. pa promjenom vrijednosti *a (izraz (*a)++) efektivno mijenjamo vrijednost varijable x.2. prilikom poziva funkcije varijabla a poprima vrijednost parametra. . Naravno. Sliˇno prethodnom c primjeru.2. . varijabla a je tipa int* (pointer na int. 1 1 . dok c z c niste apsolutno sigurni da Vam je potpuno jasno. varijabla a se briˇe i promjena “nestaje”. te na raˇunalu rijeˇite sve zadatke iz c s ovog poglavlja! ˇ Zadatak 10. Funkcije Odmah nakon poziva funkcije Nakon promjene varijable a u funkciji 2473849 2473848 2473847 1 2473849 a 2473848 2473847 2 a . no varijabla x ostaje nepromijenjena. Rijeˇ je o jednoj od najvaˇnijih stvari u C-u. .2 varijabla a ima vrijednost 1234568. . prilikom izlaska iz funkcije. na slici 10. . . Napomena 10. b++. no ovaj put to je &x.1. pa c &x vra´a adresu varijable x. int b ) { int ∗ c . . . . ( ∗ a)++. Podsjetimo se: operator “&” vra´a adresu varijable koja se nalazi iza njega.

b = 1 0 . jer je c pointer na varijablu b iz funkcije. on ne´e izmijeniti niti varijablu c c c iz glavnog programa (jer s njom nema veze). b . c = 100 Iako imamo izraz (*c)++ koji je sliˇan izrazu (*a)++. } Rjeˇenje.2. c = %d\n” . niti varijablu b iz glavnog programa. p r i n t f ( ”a = %d . 1 1234568 . . return 0 . . a . a . f (&a . c = %d\n” .2 8 9 10 11 12 13 14 15 16 17 int main ( void ) { int a = 1 . Napiˇite funkciju koja omogu´uje zamjenu vrijednosti dva realna broja.2 (Cesta greˇka). c = 1 0 0 .2. . Program ispisuje s a = 1. 2 1234570 1234569 1234568 1234567 1234570 1234569 x 1234568 1234567 x (=*a) Slika 10. . b . a ona sama je kopija varijable b iz glavnog programa! Zbog toga izraz (*c)++ radi isto ˇto i b++ – mijenja lokalnu kopiju varijable b iz glavnog s programa.2: Memorija u primjeru 10. . . Varijabilni argumenti funkcija 117 Odmah nakon poziva funkcije Nakon promjene varijable *a u funkciji 2473849 2473848 2473847 1234568 2473849 a 2473848 2473847 1234568 a .2.10. c ) . b = %d . . . Zadatak 10. s ali se ˇesto – greˇkom – pojavljuje u kolokvijima i zada´ama: c s c . . . c = 100 a = 2. .2. c ) . b ) .2. . Dio programa koji ne zamjenjuje dvije varijable. . p r i n t f ( ”a = %d . . . b = %d . . . s c ˇ Napomena 10. . b = 10. b = 10.

double ∗y ) { double ∗temp . Viˇe o ovome c s s s s bit ´e reˇeno u poglavlju o dinamiˇkim varijablama. c c Naredba y = x pridruˇuje varijabli y novu vrijednost varijable x.118 10. double ∗y ) { double temp . ˇto je vrijednost koju y z s ionako ve´ ima od prije. To ˇto je varijabilni parametar pointer i dalje ne s s znaˇi da moˇemo njega mijenjati tako da promjena afektira parametar s kojim je funkcija c z pozvana. ASM – ne Assembler!) u kojima prikazana konstrukcija zaista mijenja vrijednosti dvije varijable. Moˇemo mijenjati iskljuˇivo ono na ˇto varijabilni parametar pokazuje! Na z c s primjer. znaˇilo bi da – kao i x i y – pokazuje na neku memorijsku c lokaciju u kojoj se nalazi neˇto tipa double. pa bi kod izvrˇavanja doˇlo do greˇke. ∗x = ∗y . pa ´e originalna vrijednost varijable x biti izgubljena. njen povratni tip je void): c c 1 2 3 4 5 6 void swap ( double ∗x . Funkciju za zamjenu dva realna broja moˇemo sloˇiti pomo´u varijabilnih parametara. z z c pri ˇemu funkcija ne treba vra´ati nikakvu vrijednost (tj. temp = ∗x . y = pomocna . ∗y = temp . Funkcije 1 2 x = y. c Rjeˇenje (ispravno). nije pointer na double. tj. Kad bi c ona bila pointer na double. U trenutku kad je raˇunalo izvrˇilo naredbu x = y. nemamo ni jednu s ´eliju na koju bi temp pokazivala.2. } . y = temp . za razliku od x i y. obje varijable ´e poprimiti vrijednost c s c koju je na poˇetku imala varijabla y. No. x = y. temp = x . x = y. y = x. sljede´a funkcija ne´e napraviti niˇta: c c s 1 2 3 4 5 6 void f ( double ∗x . c c c ˇ Napomena 10. No. Potrebna nam je pomo´na varijabla istog tipa kao x i y (potrebno s c ju je deklarirati na poˇetku bloka u kojem se nalazi zamjena!): c 1 2 3 double pomocna = x .3 (Cesta greˇka). } Primijetimo da je varijabla temp “obiˇni” double. u “klasiˇnim” jezicima to ne vrijedi. c Postoje jezici (npr.

To znaˇi da varijablini z c parametar mora biti tipa int** (pointer na pointer na int). postavlja ga na vrijednost NULL. Napiˇite funkciju koja prima tri argumenta: prirodni broj n ∈ N. te ih preko parametara x i y vratiti u glavni program. Varijabilni argumenti funkcija 119 Preciznije. te ih cirkularno s “pomiˇe” u desno na naˇin da tre´em pridijeli vrijednost drugog.6. tj. Napiˇite funkciju koja preko varijabilnog parametra poniˇtava pokazivaˇ s s c na cijeli broj. ali sintaksa moˇe djelovati zbunjuju´e. Funkcija treba na´i najmanji i najve´i prosti faktor c c broja n. Napiˇite funkciju koja za zadani prirodni broj n ∈ N vra´a sumu i s c produkt svih prirodnih brojeva strogo manjih od n. pointeri x i y se gube.4. Ovo je. pa je zadatak potrebno rijeˇiti z s s pomo´u varijablinih parametara. Zadatak 10.2.2. Napiˇite funkciju shift() koja prima tri cijela broja. 1 2 3 void n u l l i f y ( int ∗∗ x ) { ∗x = NULL. ali ne i vrijednosti ´elija na koje c c oni pokazuju. ona ´e zamijeniti privremene pointere x i y. Funkcija ne moˇe vratiti viˇe od jedne vrijednosti. c c Zadatak 10. c . Ovdje s z c ˇelimo mijenjati varijablu koja je tipa int* (pointer na int). te s pointere x i y na prirodne brojeve.2. ona je tipa void). pa njihova zamjena ne s utjeˇe na odgovaraju´e varijable iz glavnog programa.5. Zadatak 10.2. Princip je isti kao i do sada. drugom vrijednost prvog c c c i prvom vrijednost tre´eg.3.2. u osnovi. } Zadatak 10. Sama funkcija ne vra´a c nikakvu vrijednost (tj. c Uputa. malo modificirani swap(). Uputa. Rjeˇenje. Nakon izvrˇavanja funkcije.10.

Funkcije .120 10.

Indeksi “kre´u” od nule i moraju biti strogo manji od broja elemenata c niza! Na primjer. int x[n]. &x [ 6 ] ) . Sljede´i dio programa postavlja tre´i element varijable x na vrijednost c c 13. broja vrijednosti koliko najviˇe moˇemo pospremiti u niz. c Primjer 11. Takoder. 3 i 4. tj.1.1. Napomena 11.2. a nikako ne varijabla ili izraz ˇija vrijednost nije jednoznaˇno c c odredena u trenutku compiliranja! Pojedinim vrijednostima pristupamo navodenjem imena varijable i indeksa.Poglavlje 11 Nizovi (polja) Nizovi (polja ili indeksirane varijable) su varijable koje u sebi sadrˇe viˇe vrijednosti istog z s tipa. y [ 0 ] ) .2. Deklariramo ih navodenjem tipa vrijednosti i “duljine niza”. duljina (u ovom primjeru n) mora biti zadana konstanta. s z 11.1. ispisuje prvi element varijable y. 1. ali ne i 5 (ili bilo koji broj ve´i od 5).1. p r i n t f ( ”%g” . Napomena 11. Nizove x od (najviˇe) 17 cijelih brojeva i y od (najviˇe) 19 realnih brojeva s s deklariramo na sljede´i naˇin: c c 1 2 int x [ 1 7 ] . U deklaraciji niza.1 Uvod Primjer 11.1. 121 . za niz int x[5] indeksi kojima smijemo pristupati su 0. te uˇitava sedmi element varijable x: c 1 2 3 x [ 2 ] = 13. 2. npr. ne smijemo pristupati niti negativnim indeksima. double y [ 1 9 ] .1. s c a n f ( ”%d” .

Napomena 11. .1.1. nego moramo raditi sa svakim pojedinim ˇlanom niza (npr. varijabla x ´e biti niz od 17 cijelih brojeva nepozs c nate vrijednosti. h> int main ( void ) { unsigned int n . printf (” . c Rjeˇenje.4. pomo´u for()-petlje). 3 i 7 (respektivno). b [ 3 ] . 3 . Napiˇite program koji uˇitava prirodni broj n ≤ 20. Napomena 11.1. brojeve treba ispisati u obrnutom redoslijedu.4. 7 } .122 11. . for ( i = 3 .1. ” . . Iznimka c c su nizovi znakova (tzv. Ovdje ´emo upotrijebiti unsigned int.3. nizove ne moˇemo odjednom ispisati ili uˇitati: c z c 1 2 3 int x [ 1 7 ] . Ako nizu nije zadana poˇetna vrijednost. int y [ 1 7 ] = { 0 } . a [ 2 ] = 7. i . Ovaj primjer identiˇan je (do na dodanu c varijablu i) sljede´em kodu: c 1 2 3 4 int a [ 1 7 ] . &x ) . ” . b je niz od tri elementa (ponovno s vrijednostima 1.1. . int b [ ] = { 1 . Nizovi (polja) Nizove moˇemo deklarirati i tako da ih odmah inicijaliziramo (navedemo poˇetne vriz c jednosti njihovih elemenata). kako bismo pokazali da kod unsigned s c tipova treba dodatno pripaziti. 3 . a [ 0 ] = 1. c Zadatak 11. nego ´e ta vrijednost biti sluˇajna (kao i kod “obiˇnih” varijabli kad c c c ih neinicijaliziramo)! Primjer 11. Nakon izvrˇavanja ovog dijela programa. b [ 1 ] = 3. dok ´e varijabla y biti niz od 17 cijelih brojeva koji svi imaju vrijednost c nula. a [ 1 ] = 3.1. x ). 1 2 3 4 #include <s t d i o . Primjer 11.3. Varijable a i b razlikuju se u duljini: a je niz sa 17 elemnata od koji prva tri imaju vrijednosti 1. x [ 2 0 ] . njegovi elementi ne´e c c imati vrijednost nula. . te n prirodnih s c brojeva. dok su ostale vrijednosti nula. s c a n f ( ” . i ++) a [ i ] = 0 . b [ 0 ] = 1. b [ 2 ] = 7. stringovi) koje ´emo naknadno obraditi. Op´enito. Nakon uˇitavanja. 1 2 int x [ 1 7 ] . 7 } . i < 1 7 . 3 i 7 respektivno). 1 2 int a [ 1 7 ] = { 1 .

&x [ i ] ) . i ++) p r i n t f ( ”%u\n” . x[−−n ] ) . Mogu´e je i definirati varijablu i tako da bude c tipa unsigned int. p r i n t f ( ”\n” ) . for ( i = n − 2 . for ( i = n − 1 . i −−) p r i n t f ( ”%u\n” . s c a n f ( ”%u” . %u” . } Napomena 11. p r i n t f ( ” Unesite n : ” ) . p r i n t f ( ”pa j a nemam s t o r a d i t i . i ++) { p r i n t f ( ” U n e s i t e x[%d ] : ” . Da je tip varijable i u prethodnom programu bio unsigned int. s c a n f ( ”%u” . . i >= 0 . x [ n − i ] ) . izveden u jednoj liniji uz zareze izmedu brojeva. na naˇin da daje c jednaki ispis). i <= n . i < n .1. .5. no onda moramo izmijeniti for()-petlju (naravno. ili. x [ i − 1 ] ) . \ n” ) . ili 14 15 for ( i = n . while ( n ) p r i n t f ( ” . } p r i n t f ( ” I s p i s b r o j e v a u obrnutom r e d o s l i j e d u : \ n” ) . i −−) p r i n t f ( ” . &n ) . pomo´u while()-petlje (i bez pomo´ne varijable i): c c 1 2 3 4 p r i n t f ( ” I s p i s b r o j e v a u obrnutom r e d o s l i j e d u : %u” . i > 0 . Na primjer: 14 15 for ( i = 1 . %u” . . x [ n−1]). x [ i ] ) . moˇemo napraviti ovako: 1 2 3 4 p r i n t f ( ” I s p i s b r o j e v a u obrnutom r e d o s l i j e d u : %u” . ” ) . p r i n t f ( ”\n” ) . z Ispis iz prethodnog zadatka. Uvod 123 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int i . uvjet for()-petlje bio bi uvijek istinit.1. } else { p r i n t f ( ” O d a b r a l i s t e unos n u l a b r o j e v a . i f (n > 0) { for ( i = 0 . x[−−n ] ) . } return 0 . x [ i ] ) . i −−) p r i n t f ( ”%u\n” . i ) .11. i >= 0 .

} for ( i = 0 . Da bismo dobili s “ispravni” redoslijed. s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 int x [ 1 7 ] . n /= 1 0 . i . te ga ispisujemo unatrag. Zadatak 11. Napiˇite dio programa koji za zadani prirodni broj n ispisuje njegove s znamenke “ispravnim” redoslijedom (od lijeve prema desnoj). n++) { s c a n f ( ”%d” . V r i j e d n o s t : %d\n” .2. tj.h. for ( n = 0 . Potrebno je ispisati indeks i vrijednost broja koji ima najve´u apsolutnu c vrijednost (bez koriˇtenja funkcija iz stdlib. i ++) { int abs = ( x [ i ] < 0 ? −x [ i ] : x [ i ] ) . } } p r i n t f ( ” Index : %d . n /= 1 0 . No.124 11. s 1 2 3 4 5 6 int znam [ 1 0 0 ] . } while ( i ) p r i n t f ( ”%d\n” . Napiˇite dio programa koji uˇitava cijele brojeve dok ne uˇita nulu s c c ili 17 brojeva. no to zahtijeva dodatna znanja. i f ( abs > max) { max = abs . n . n < 1 7 . s prilikom deklaracije niza potrebno je utvrditi koliko niz mora biti dugaˇak? c Mogu´e je precizno izraˇunati najve´i mogu´i broj znamenaka (neovisno o raˇunalu na c c c c c kojem se program compilira). i f ( ! x [ n ] ) break . Rjeˇenje. } ispisuje znamenke u “pogreˇnom” redoslijedu (od desne prema lijevoj). max = 0 . while ( n > 0 ) { znam [ i ++] = n % 1 0 . maxi = 0 . i = 0 . bez koriˇtenja funkcije abs() i sliˇnih). n % 1 0 ) . x [ maxi ] ) . maxi = i . i < n . maxi . s s c Rjeˇenje. pa ´emo samo pretpostaviti c da broj n ima manje od 100 znamenaka.1. znamenke broja smjeˇtamo u niz. Rjeˇenje koje smo prije vidjeli: s 1 2 3 4 while ( n > 0 ) { p r i n t f ( ”%d\n” . Nizovi (polja) Zadatak 11.3. &x [ n ] ) . znam[−− i ] ) .1. .

ne raˇunaju´i nulu kojom se prekida uˇitavanje).11. i f ( ! x ) break .5. Rijeˇite prethodni zadatak bez upotrebe nizova! s Zadatak 11. while ( x ) { zn [ x % 10]++. Uvod 125 Zadatak 11. i ++) s c a n f ( ”%l g ” . i < n .1. &x ) .1. s c a n f ( ”%d” . } } for ( i = 0 .4. ++i ) . i ++) p r i n t f ( ”%d : %d\n” . h> int main ( void ) { int zn [ 1 0 ] = { 0 } . return 0 . s 1 2 3 4 5 6 7 8 double x [ 1 8 ] . Napiˇite program koji uˇitava prirodne brojeve dok ne uˇita nulu. int x . s s Rjeˇenje. s c Potrebno je ispisati indeks i vrijednost broja koji je najudaljeniji (ima najve´u apsolutnu c razliku) od svog sljedbenika. max = 0 . maxi = 0 . zn [ i ] ) . while ( 1 ) { p r i n t f ( ” U c i t a j t e b r o j #%d : ” . for ( i = 0 . x /= 1 0 . int i . . for ( i = 0 . } Zadatak 11. ispiˇite samo prvog. i ++) { double r a z l i k a = x [ i ] − x [ i + 1 ] . i = 0 . s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <s t d i o . i < 1 0 .1. i f ( r a z l i k a < 0) r a z l i k a = −r a z l i k a . &x [ i ] ) . c c c Rjeˇenje. i < n − 1 . Ako takvih ima viˇe. i . Za s c c svaku znamenku od 0 do 9 program treba ispisati koliko se puta pojavila (u svim uˇitanim c brojevima zajedno.6.1. Napiˇite dio programa koji uˇitava n realnih brojeva (n < 19 je zadan).

Zato su svi elementi takvog niza varijabilni argumenti funkcije! .2. vrijedi: p ⇔ &p[0] ˇ Stoviˇe. maxi = i . vrijedi i op´enitije: s c p + i ⇔ &p[i] tj. Zbog toga. c Dapaˇe. s z s program ispiˇe zadnjeg. Nizovi (polja) 9 10 11 12 13 14 } p r i n t f ( ” Index : %d . tj. Prethodnom rjeˇenju je dovoljno dodati toˇno jedan znak. } Zadatak 11. V r i j e d n o s t : %g\n” . s Uputa. Ono ˇto nama za sada s c c c s treba je ˇinjenica da se niz proslijeden kao argument funkcije ponaˇa jednako kao pointer. Promijenite prethodno rjeˇenje tako da ako traˇenih brojeva ima viˇe. x [ maxi ] ) . promjena s c s ´e se odraziti i na “originalni” niz u glavnom programu.126 11. i f ( r a z l i k a > max) { max = r a z l i k a . to je jednako kao da smo napisali *p = 17. c s To znaˇi da ako smo funkciji proslijedili niz niz i izvrˇimo pridruˇivanje c s z p[0] = 17.1 (Ekvivalencija polja i pointera). smijete to s c rijeˇiti i “kompliciranije”. *(p + i) ⇔ p[i] Viˇe rijeˇi o ovome bit ´e u poglavlju o dinamiˇkim nizovima. dok sam niz ostaje nepromijenjen u memoriji. kad “poˇaljemo” niz u funkciju. U C-u je niz (polje) ekvivalentan pointeru na nulti element tog polja. maxi . ˇto znaˇi da ne mijenjamo varijablu p nego ono na ˇto ona pokazuje. s 11.1.2 Nizovi kao funkcijski argumenti Napomena 11. Naravno.7. zapravo se u memoriji kopira samo adresa nulc s tog elementa niza.

int i . pa ju smijemo mijenjati bez c posljedica po odgovaraju´u varijablu s kojom je funkcija pozvana. Zadatak 11. nego samo jedan pointer). int n ) { double s = 0 . kao argument funkcije. Zbog toga nam ovdje ne treba duljina niza kao argument funkcije.2.1. for ( i = 0 . int i . return s . i < n . while ( n−− > 0 ) s+= n i z [ n ] . ˇto ne ovisi o duljini s s s niza (ne piˇe da treba provjeriti ispravnost parametra i. Ovdje je potrebno neˇto napraviti na nekom elementu niza. Oˇito. int x ) { . ne moramo uˇitavati brojeve. Napiˇite i program za s testiranje funkcije. Niz je odreden elementima i duljinom. potrebno je dva puta ispisati niz (prije i nakon poziva funkcije). Funkcija treba postaviti vrijednost i-tog elementa niza na x. h> void s e t ( int n i z [ ] . Nizovi kao funkcijski argumenti 127 Niz.2. tj. Takoder. Zato ´emo ispis niza smjestiti u zasebnu funkciju (print_niz()). funkcija ne mora vratiti nikakvu vrijednost.2. Napiˇite funkciju koja prima niz realnih brojeva.2. c kad samo testiramo funkciju. return s . Zbog toga (i zbog c komutativnosti zbrajanja) funkciju moˇemo i ovako napisati: z 1 2 3 4 5 double sum ( double n i z [ ] . Rjeˇenje.11. c Da bismo testirali funkciju. Kad se u zadatku kaˇe da funkcija s prima niz nekakvih podataka. te vra´a sumu njegovih s c elemenata. } Zadatak 11. z Rjeˇenje. int n ) { double s = 0 . i ++) s += n i z [ i ] . navodimo jednako kao i u deklaraciji varijable u koju pohranjujemo niz. da je on nenegativan i strogo s manji od duljine niza). 1 2 3 #include <s t d i o . c 1 2 3 4 5 6 double sum ( double n i z [ ] . moˇemo ih zadati kao dio c z programa. Napiˇite funkciju koja prima niz cijelih brojeva i cjelobrojne argumente s i i x. osim ˇto moˇemo izostaviti duljinu niza (upravo zato jer ta deklaracija s z ne alocira cijeli niz. onda se obiˇno podrazumijeva da zadajemo dva argumenta: c sam niz i prirodni broj koji predstavlja njegovu duljinu! Duljinu ne prosljedujemo kao argument ako ona nije potrebna (sljede´i zadatak). } Varijabla n je obiˇni argument (nije niti niz niti pointer).

int n ) { int i . int n ) { int i .1 moˇete vidjeti skicu memorije prilikom poziva funkcije set(). 2 3 . } void p r i n t n i z ( int n i z [ ] . 17). Rjeˇenje. 1 9 .128 11. c Zadatak 11. } Na slici 11. set (x . %d” . i < n . c c c c zbog jednostavnosti. 2 9 . print niz (x . x [ ] = { 1 7 .3. return r e s . i ++) i f ( niz [ i ] > res ) res = niz [ i ] . n i z [ i ] ) . ´elije su razliˇitih veliˇina.2. Nizovi (polja) 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 niz [ i ] = x . for ( i = 1 . print niz (x . n i z [ 0 ] ) . 3 1 } . } Rjeˇenje se moˇe napisati i malo kompaktnije: s z . int n ) { int i . 3 . for ( i = 1 . uz zanemaz rivanje veliˇina memorijskih lokacija (u stvarnosti. Napiˇite funkcije za traˇenje minimuma i maksimuma niza realnih bros z jeva. n ) . n ) . return 0 . i < n . p r i n t f ( ” El e me nti n i z a : %d” . i ++) p r i n t f ( ” . p r i n t f ( ”\n” ) . double r e s = n i z [ 0 ] . for ( i = 1 . } int main ( void ) { int n = 5 . } double max( double n i z [ ] . mi ovdje. double r e s = n i z [ 0 ] . i ++) i f ( niz [ i ] < res ) res = niz [ i ] . uzimamo veliˇinu 1). “Klasiˇno” rjeˇenje: s c s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 double min ( double n i z [ ] . return r e s . i < n .

} Oba rjeˇenja su podjednako dobra (uˇteda od jedne cjelobrojne varijable je zanemariva). osim za c . .11.2 s 1 2 3 4 5 6 7 8 9 10 11 double min ( double n i z [ ] . . . return r e s . Napiˇite funkcije min() i max() tako da primaju joˇ jedan parametar s s x tipa double. . da niz nije prazan. Funkcije trebaju vra´ati minimum (odnosno maksimum) niza. a zadatak niˇta ne govori o s tom sluˇaju.4. int n ) { double r e s = n i z [−−n ] . . } double max( double n i z [ ] . . Kad s bi niz bio prazan.2. minimum i maksimum ne bi bili definirani. . . . . while ( n−−) i f ( n i z [ n ] > r e s ) r e s = n i z [ n ] . . .2. while ( n−−) i f ( n i z [ n ] < r e s ) r e s = n i z [ n ] . tj. 1234564 1012345 1012344 1012343 niz Slika 11. int n ) { double r e s = n i z [−−n ] . s s Primijetite da oba rjeˇenja pretpostavljaju da je n > 0.2. c Zadatak 11. . . Nizovi kao funkcijski argumenti 129 2473849 2473848 2473847 1234564 x . 31 29 23 19 17 1234570 1234569 1234568 1234566 1234565 1234564 1234563 niz[4] niz[3] niz[2] niz[1] niz[0] . .1: Prikaz memorije prilikom poziva funkcije set() u rjeˇenju zadatka 11. return r e s . . . .

i p += a [ i ] ∗ pot ∗= x . i ++) { pot . . p += a [ i ] ∗ pot . Napiˇite funkciju koja prima niz realnih brojeva. s s z c Donekle bolje rjeˇenje je: s Rjeˇenje. int i . } p r i n t f ( ”p(%g ) = %g\n” . = %g\n” . Funkcija treba vratiti s sumu elemenata niza. Oˇito.2. x .1. Napiˇite dio programa koji za zadani niz realnih brojeva a duljine n+1 s (n je takoder zadan) i za zadani realni broj x ispisuje vrijednost polinoma n p(x) = i=0 ai x i = a0 + a1 x + a2 x 2 + · · · + a n x n . Npr. for ( i = 0 . ali loˇe rjeˇenje je: c s s Rjeˇenje. for ( i = 0 .2.3.3.130 11.3 Hornerov algoritam Zadatak 11. Zadatak 11. j . <= n . te – pomo´u varijabilnih parametara – najmanji i najve´i element c c niza. p ) . moˇete bilo koji od zadataka iz predhodnih poglavlja o programiranju z z pretoˇiti u jednu ili ˇak viˇe funkcija. } p r i n t f ( ”p(%g ) pot = 1 . Za vjeˇbu. Ovo rjeˇenje ima daleko previˇe mnoˇenja. Pri tome smijete koristiti funkcije iz zadatka 11. for ( j = 0 . x3 raˇunamo za svaki indeks i ≥ 3. p ) . s 1 2 3 4 5 6 7 8 double p = 0 . x . j . c c s 11. int i . s 1 2 3 4 5 6 7 double p = 0 . j < i . i ++) { double pot = 1 . Nizovi (polja) prazan niz za kojeg trebaju vratiti vrijednost x.5. j ++) pot ∗= x . i <= n .

)) Sada. z 1 2 s c a n f ( ”%g” . pa se javlja overflow ili underflow). . te za zadani niz a s c duljine 2*n ispisuje vrijednost p1 (x) · p2 (x) gdje je p1 (x) = a0 + a2 x + a4 x2 + · · · + a2n−2 xn−1 p2 (x) = a1 + a3 x + a5 x2 + · · · + a2n−1 xn−1 Rjeˇenje. . x . moˇemo raˇunati: z c = an = an−1 + xp0 = an−2 + xp1 = an−3 + xp2 . p ) . p1 = 0 .. c Daleko bolje rjeˇenje moˇemo dobiti izluˇivanjem zajedniˇkih potencija iz dijelova polis z c c noma: p(x) = a0 + a1 x + a2 x2 + a3 x3 + a4 x4 + · · · + an−1 xn−1 + an xn = a0 + x(a1 + a2 x + a3 x2 + a4 x3 + · · · + an−1 xn−2 + an xn−1 ) = a0 + x(a1 + x(a2 + a3 x + a4 x2 + · · · + an−1 xn−3 + an xn−2 )) = a0 + x(a1 + x(a2 + x(a3 + a4 x + · · · + an−1 xn−4 + an xn−3 ))) = a0 + x(a1 + x(a2 + x(a3 + x(a4 + · · · + x(an−1 + xan ) . i >= 0 . for ( i = n . pn−1 = a1 + xpn−2 pn = a0 + xpn−1 . p0 p1 p2 p3 pa je p(x) = pn . p r i n t f ( ”p(%g ) = %g\n” . Hornerov algoritam.3. a zatim s c c dobivene vrijednosti mnoˇimo.. ovo rjeˇenje joˇ uvijek nije dovoljno dobro zbog nuz s s meriˇke nestabilnosti (potencije mogu biti jako velike. po koracima. &x ) . . Zadatak 11.2.3.11. Opisani postupak zove se Hornerov algoritam. 1 2 3 4 p = 0. Hornerov algoritam 131 Iako ima puno manje mnoˇenja. Pomo´u dvije primjene Hornerovog algoritma raˇunamo p1 (x) i p2 (x). Napiˇite dio programa koji uˇitava realni broj x. i −−) p = p ∗ x + a[ i ].

i >= 0 . + 1]. i −= 2 ) p1 = p1 ∗ x + a [ i ] . int n ) { double p1 = 0 . for ( i = 2 ∗ n − 1 . &x ) . Nizovi (polja) 3 4 5 6 7 8 for ( i = 2 ∗ n − 2 .3. for ( i = n . for ( i = 2 ∗ n − 1 . i −−) { . p2 = 0 . i −= 2 ) p2 = p2 ∗ x + a [ i ] . pri ˇemu je niz a duljine 2*(n+1). c morali bismo svakoga raˇunati u zasebnoj petlji jer se petlja “vrti” onoliko puta koliko c polinom ima koeficijenata. p2 = 0 . p2 = 0 . x . p1 ∗ p2 ) . vrijednost polinoma s raˇunamo u istoj for()-petlji jer polinomi imaju jednak broj koeficijenata.1. x . for ( i = n − 1 . i >= 0 .132 11. x . s 1 2 3 double p ( double x . x . Zadatak 11. Napomena 11. = %g \n” . Funkcija treba Hornerovim c algoritmom izraˇunati i vratiti vrijednost p1 (x) + p2 (x) gdje je c p1 (x) = a0 + a1 x + a2 x2 + · · · + an xn p2 (x) = an+1 + an+2 x + an+3 x2 + · · · + a2n+1 xn Rjeˇenje. p1 = p1 ∗ x + a [ 2 ∗ i p2 = p2 ∗ x + a [ 2 ∗ i } p r i n t f ( ”p1(%g ) ∗ p2(%g ) i −−) { ]. p r i n t f ( ”p1(%g ) ∗ p2(%g ) = %g \n” . i >= 1 . p1 ∗ p2 ) . ili 1 2 3 4 5 6 7 8 s c a n f ( ”%l g ” . Primijetimo da oba polinoma moˇemo raˇunati u istoj petlji: z c 1 2 3 4 5 6 7 8 s c a n f ( ”%g” .3. Napiˇite funkciju koja kao parametre prima realni broj x. &x ) . niz realnih s brojeva a i cijeli broj n. i −= 2 ) { p1 = p1 ∗ x + a [ i − 1 ] . x . i >= 0 .3. x . double a [ ] . p1 = 0 . i >= 1 . p2 = 0 . p1 = 0 . U posljednja dva rjeˇenja prethodnog zadatka. p2 = p2 ∗ x + a [ i ] . } p r i n t f ( ”p1(%g ) ∗ p2(%g ) = %g \n” . Da nije tako. p1 ∗ p2 ) .

1. g(i) i h(x) treba uvrstiti stvarne formule. . g(i) = n − i. i −−) p = p ∗ x + a[ i ]. Hornerov algoritam 133 4 5 6 7 8 } return p1 + p2 . p ∗= x . f (n) = n. pri ˇemu za r(x).3. p = p * r(x). h(x) = x. ai xn−i = n an−i xi i=0 Dakle: r(x) = 1. pa Hornerov algoritam izgleda ovako: p = 0. Zadatak 11. for ( i = n .3. te za zadani niz a s c duljine m+n+2 ispisuje vrijednost p1 (x) − p2 (x) gdje je p1 (x) = a0 + a1 x + a2 x2 + · · · + an xn p2 (x) = an+1 + an+2 x + an+3 x2 + · · · + am+n+1 xn s Op´enito. 1 2 3 4 p = 0.11. pa Hornerov algoritam izgleda ovako: n i=0 n i=0 1 2 3 2. n ai xi+1 = x · i=0 ai xi Dakle: r(x) = x. for ( i = n . probleme s Hornerovim algoritmom je najlakˇe rijeˇiti svodenjem polinoma c s na oblik f (n) r(x) · ag(i) h(x)i . } p1 = p1 ∗ x + a [ i ] . for (i = f (n). Tada programski isjeˇak koji raˇuna vrijednost c c polinoma izgleda ovako: p = 0. f (n). g(i) = i. preslagivanjem polinoma na naˇin da potencije argumenta (ovdje je to h(x)) idu redom c od nule (bez “preskakanja” potencija). Napiˇite dio programa koji uˇitava realni broj x. i >= 0. c Primjer 11.4.3. f (n) = n. i −−) p = p ∗ x + a[n − i ]. i=0 tj. i >= 0 . p2 = p2 ∗ x + a [ i + n + 1 ] . h(x) = x. i--) p = p * h(x) + a[g(i)].1. i >= 0 .

i −−) p = p ∗ (x ∗ x) + a [2 ∗ i + 4 ] . p(x) = m+n i−m i=m+1 ai x Na primjer.5. i < 5 . Napiˇite program koji uˇitava prirodne brojeve m i n takve da je m+n < s c m+n 100. te n2 + 1 realnih brojeva s c n2 c (ai )i=0 . Program treba ispisati koliko je p(a0 ). Zadatak 11. te m + n + 1 realnih brojeva (ai )i=0 . Program treba ispisati koliko je p(am ). te m + n + 1 realnih brojeva (ai )i=0 . i >= 0 .3.5. i −−) = p ∗ (x ∗ x) + a [2 ∗ i + 4 ] .6.11.10811.10811.13} program treba ispisati 1.11.5. Napiˇite program koji uˇitava prirodni broj n. Program treba ispisati koliko je p(an2 ).134 11. for ( i = n − 2 .7. g(i) = 2i + 4. ili 1 2 3 4 p = for p for 0. n−2 n−2 a2·i x2·i+1 = i=0 a2·(i+2) x2·(i+2)+1 = x5 · i=0 a2i+4 (x2 )i Dakle: r(x) = x5 .3. pri ˇemu c je m i i=1 ai x p(x) = m+n . 1 + 13 · 72 11 · 7 77 + 637 714 Zadatak 11.37535. jer je p(2) = 3 · 2 + 5 · 22 + 7 · 23 6 + 20 + 56 82 41 = = = = 1.7. Napiˇite program koji uˇitava prirodne brojeve m i n takve da je m+n < s c m+n c 100.3. f (n) = n − 2.7. Nizovi (polja) 3. n=2 i niz brojeva a[] = {2. h(x) = x2 .3. za m=3. i−m i=m+1 ai x Na primjer. n=2 i niz brojeva a[] = {2. ( i = 0 . p ∗= x ∗ x ∗ x ∗ x ∗ x .3. pa Hornerov algoritam izgleda ovako: n i=2 1 2 3 4 p = 0. ( i = n − 2 . za m=3. . i >= 0 . pri ˇemu je n−1 n·(i+1)−1 p(x) = i=0 j=n·i aj xj−n·i . jer je p(7) = 2 · 70 + 3 · 71 + 5 · 72 2 + 21 + 245 268 = = = 0.37535. 11 · 2 + 13 · 22 22 + 52 74 37 Zadatak 11. pri ˇemu je m−1 i i=0 ai x .13} program treba ispisati 0. i ++) p ∗= x .

455 = 10. Sortiranje 135 Na primjer.7 + 0. jer je p(0. Nadalje. i ++) swap(&x [ i ] . Zamjenu i-tog elementa s lijeva i i-tog elementa s desna treba napraviti samo s u jednoj polovici niza: .7 + 0. U rjeˇenju smijete koristiti funkciju swap() iz zadatka 10.5. -7.7} program treba ispisati -20.72 ) (2 + 0. za n=3 i niz brojeva a[] = {2.4.5. 3.72 ) = 2 · 2.5} program treba ispisati 10. 0.72 )· (−2 + 3 · 0. . s Rjeˇenje (pogreˇno).3.4 Sortiranje Da bismo u nekom nizu mogli ˇto brˇe prona´i neki podatak (ili utvrditi da ga u nizu s z c nema).21 · 2. pri ˇemu je c i=0 n−1 i+1 p(x) = i=0 j=1 aj xj−1 . Zadatak 11. 0.8.2. for ( i = 0 .7) = 2 · (2 + 0.7.8511. korisno je poredati elemente niza po nekom kriteriju (npr.8511.2.07.7) · (2 + 0.3. ˇto znaˇi da ´e c s c c niz na kraju ostati nepromijenjen! Rjeˇenje. x0 ).07. 0. 0. te n + 1 realnih brojeva s c (ai )n .33) = −20. treba nam prerasporedivanje elemenata niza.2.2. ˇto je obradeno s u zadatku 10. .5 · 0. 0.455 · 2. Napiˇite program koji uˇitava prirodni broj n.455 · (−3.5 · 0. x1 .7) = (2 + 0. 11.7 + 0. xn−2 . -2. . Zamjenjujemo i-ti element s lijeva i i-ti element s desna: s s 1 2 int i .72 )· ≈ −20.3.1. xn−1−i ) elemenata.4. Na primjer. 0. i < n .5 · 0. 2. 0.3. Ovakva zamjena ´e dva puta zamijeniti svaki par (xi . po veliˇini). Napiˇite dio programa koji uˇitani niz realnih brojeva x duljine n invers c tira (poreda tako da mu elementi idu obrnutim redoslijedom: xn−1 . .3 · 0. jer je p(0. Osnovna c operacija koja nam pri tome treba je zamjena vrijednosti dviju varijabli.11.06999325 Zadatak 11.7 − 7 · 0.3 · 0. za n=3 i niz brojeva a[] = {0. 2.3 · 0. &x [ n−1− i ] ) . Program treba ispisati koliko je p(a0 ).3 · 0. = 2.

i < n / 2 . j < n . z z c Zadatak 11. int n . s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <s t d i o . c n−1 Primijetimo da je niz (xi )i=0 sortiran ako i samo ako vrijedi: ∀i. b r o j : ” . Nizovi (polja) 1 2 int i . h> int main ( void ) { int n i z [ 1 7 1 9 ] . j : (i < j) ⇒ xi ≤ xj . j ++) i f ( niz [ i ] > niz [ j ] ) { . Bez koriˇtenja funkcije swap(). i ++) { p r i n t f ( ” u n e s i t e %d . te ispisati sortirani niz. } for ( i = 0 . &n i z [ i ] ) . for ( i = 0 . te niz od n cijelih brojeva. i < n / 2 . p r i n t f ( ” k o l i k o e l e m e n a t a ima n i z ? ” ) . Napiˇite program koji uˇitava broj n ≤ 1719.4. rjeˇenje izgleda ovako: s s 1 2 3 4 5 6 int i . for ( i = 0 . } Sada smo oboruˇani s dovoljno znanja da moˇemo poredati elemente niza po veliˇini. ako uzmemo u obzir ekvivalentnost nizova i pointera u C-u: 1 2 int i . &n ) . i < n − 1 . i . s c Brojeve treba sortirati uzlazno po veliˇini. for ( i = 0 . i ++) swap ( x+i . i < n . &x [ n−1− i ] ) .2. x [ i ] = x [ n−1+i ] . potrebno ih je zamijeniti. Ako nisu. j . s c a n f ( ”%d” . Dakle. i ++) { double temp = x [ i ] . s c a n f ( ”%d” . potrebno je “protrˇati” po svim parovima indeksa i i j takvima da je i < j i c provjeriti jesu li xi i xj u ispravnom poretku. for ( i = 0 .136 11. i < n / 2 . i ++) for ( j = i + 1 . Rjeˇenje. ili. i ++) swap(&x [ i ] . i + 1 ) . x+n−1− i ) . x [ n−1+i ] = temp .

n i z [ i ] ) . s .4. Dovoljno je izmijeniti jedan znak u prethodnom rjeˇenju. n i z [ j ] = temp . jer se radi previˇe zamjena za svaki element niza. pa onda njega zamijeniti s i-tim elementom niza (pogledati predavanja): 1 2 3 4 5 6 7 8 9 10 for ( i = 0 . niz [ i ] = niz [ j ] . j ++) i f ( n i z [ mini ] > n i z [ j ] ) mini = j .3. i < n − 1 . Preciznije.4. } ili joˇ malo bolje (ne radi zamjenu elementa sa samim sobom): s 1 2 3 4 5 6 7 8 9 10 11 for ( i = 0 . for ( j = i + 1 . i ++) { int temp . } p r i n t f ( ” s o r t i r a n i n i z : \ n” ) . Puno je bolje prvo na´i najmanji s c element niza u dijelu niza s indeksima od i do n − 1. rijeˇ je o “loˇoj” varijanti tog c c s sorta. j ++) i f ( n i z [ mini ] > n i z [ j ] ) mini = j . Uputa. i f ( mini > i ) { int temp = n i z [ i ] . n i z [ mini ] = temp . mini = i . } } Zadatak 11. Sortiranje 137 17 18 19 20 21 22 23 24 25 26 27 int temp = n i z [ i ] . for ( j = i + 1 . int mini . mini = i . temp = n i z [ i ] . for ( i = 0 . i < n − 1 . Rijeˇite prethodni zadatak tako da niz sortirate silazno (od najve´eg s c broja prema najmanjem). n i z [ j ] = temp .11. i ++) { int mini . n i z [ i ] = n i z [ mini ] . niz [ i ] = niz [ j ] . } Prikazani algoritam se zove “klasiˇni sort”. j < n . j < n . i ++) p r i n t f ( ” %d\n” . i < n . return 0 .

Brojeve treba sortirati silazno po sumi znamenaka. &x [ i ] ) . Rjeˇenje. i ++) { p r i n t f ( ” U n e s i t e %d . while ( x1 > 0 ) { suma1 += x1 % 1 0 . while ( x2 > 0 ) { suma2 += x2 % 1 0 . x2 = ( x [ j ] < 0 ? −x [ j ] : x [ j ] ) . Napiˇite dio programa koji uˇitava prirodni broj n < 1317. int n . } for ( j = i + 1 . i < n . i < n . } } } p r i n t f ( ” S o r t i r a n i n i z : \ n” ) . i + 1 ) . s c a n f ( ”%d” . te ispisati sortirani niz. b r o j : ” . s c a n f ( ”%d” . i . for ( i = 0 . i ++) . j . x2 /= 1 0 . s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 int x [ 1 3 1 6 ] .4. } for ( i = 0 . x1 /= 1 0 . j ++) { /∗ Suma z n a m e n a k a e l e m e n t a x [ j ] ∗/ int suma2 = 0 . j < n . i < n − 1 . Nizovi (polja) Zadatak 11. /∗ S a d a x [ i ] ima sumu z n a m e n a k a s u m a 2 ∗/ suma1 = suma2 . &n ) .138 11. p r i n t f ( ” K o l i k o e l e m e n a t a ima n i z ? ” ) . x [ j ] = temp . } /∗ U s p o r e d b a suma z n a m e n a k a b r o j e v a x [ i ] i x [ j ] ∗/ i f ( suma1 < suma2 ) { /∗ Z a m j e n a x [ i ] i x [ j ] ∗/ int temp = x [ i ] . x1 = ( x [ i ] < 0 ? −x [ i ] : x [ i ] ) . i ++) { /∗ Suma z n a m e n a k a e l e m e n t a x [ i ] ∗/ int suma1 = 0 . for ( i = 0 . x[ i ] = x[ j ]. te niz od s c n cijelih brojeva.4.

i + 1 ) . To je puno lakˇe rijeˇiti upotrebom funkcije koja ´e zbrojiti znamenke broja i vratiti s s c tu vrijednost: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <s t d i o . j . for ( j = i + 1 . x[ i ] = x[ j ].4. i . t r e b a ∗/ k o j u j e x [ j ] . . i < n − 1 . a ne same brojeve). j < n . for ( i = 0 . i ++) { int suma1 = suma znamenaka ( x [ i ] ) . p r i n t f ( ” K o l i k o e l e m e n a t a ima n i z ? ” ) . Primijetimo da se mijenja samo uvjet zamjene (usporedujemo sume. &x [ i ] ) . i f ( x < 0 ) x = −x .11. dok sama zamjena ostaje nepromijenjena (i dalje zamjenjujemo elemente niza)! Prilikom raˇunanja suma znamenaka gledali smo apsolutne vrijednosti elemenata niza c jer za negativne vrijednosti operator % vra´a negativne vrijednosti. Sortiranje 139 41 printf (” %d\n” . s c a n f ( ”%d” . i ++) { p r i n t f ( ” U n e s i t e %d . h> int suma znamenaka ( int x ) { int suma = 0 . } int main ( void ) { int x [ 1 3 1 6 ] . ˇto bi dalo pogreˇan c s s rezultat! Ovdje imamo dva puta napisan praktiˇki isti kod (onaj za raˇunanje zbroja znamenac c ka). D a kl e a z u r i r a t i v a r i j a b l e s u m a 1 . suma1 = suma znamenaka ( x [ i ] ) . x [ i ] ) . } return suma . x [ j ] = temp . i < n . int n . /∗ S a d a p r i j e s t a n j e x [ i ] i m a o ima sumu z n a m e n a k a . b r o j : ” . &n ) . s c a n f ( ”%d” . while ( x > 0 ) { suma += x % 1 0 . j ++) { i f ( suma1 < suma znamenaka ( x [ j ] ) ) { /∗ Z a m j e n a x [ i ] i x [ j ] ∗/ int temp = x [ i ] . x /= 1 0 . } for ( i = 0 .

140

11. Nizovi (polja)

36 37 38 39 40 41 42 43 44 45

}

}

}

p r i n t f ( ” S o r t i r a n i n i z : \ n” ) ; for ( i = 0 ; i < n ; i ++) p r i n t f ( ” %d\n” , x [ i ] ) ; return 0 ; }

Napomena 11.4.1. Suma znamenaka ´e se za ve´inu brojeva raˇunati mnogo puta. Na c c c c s c z ˇalost, ovo moˇemo izbje´i samo uvodenjem pomo´nog niza, ˇto je ˇesto nepoˇeljno (i z z c zabranjeno u zadacima) zbog pove´ane potroˇnje memorije. c s Zadatak 11.4.5. Rijeˇite prethodni zadatak uvodenjem pomo´nog niza u kojem ´ete s c c ˇuvati sume znamenaka elemenata poˇetnog niza tako da se te sume raˇunaju toˇno jedc c c c nom za svaki broj. Uputa. Pazite da prilikom zamjene treba zamjenjivati elemente oba niza!
n−1 Primijetimo da je niz (xi )i=0 sortiran ako i samo ako vrijedi:

i ∈ {0, 1, . . . , n − 2} ⇒ xi ≤ xi+1 . Drugim rijeˇima, sortiranje moˇemo provesti tako da usporedujemo samo susjedne elec z mente niza. Algoritam za sortiranje koji koristi ovo svojstvo zove se Bubble sort. Zadatak 11.4.6. Napiˇite dio programa koji uzlazno sortira zadani niz a s n realnih s brojeva primjenom Bubble sorta. Ono ˇto trebamo raditi je “protrˇati” nizom i zamijeniti svaka dva susjedna elementa s c koji nisu u dobrom poretku. Na taj naˇin ´emo donekle ispraviti niz, ali ga, na ˇalost, c c z ne´emo u potpunosti sortirati. “Trˇanje” je potrebno raditi dok god niz ne postane c c sortiran, tj. dok god ne “protrˇimo” kroz niz bez i jedne zamjene. c Bubble sort.
1 2 3 4 5 6 7

int n e r e d ; do { nered = 0 ; for ( i = 0 ; i < n − 1 ; i ++) i f ( a [ i ] > a [ i +1]) { double temp = a [ i ] ; a[ i ] = a[ i + 1];

11.5. Pretraˇivanje z

141

8 9 10 11

a [ i + 1 ] = temp ; nered = 1 ; } } while ( n e r e d ) ;

Primijetimo da ´e ve´ u prvom prolazu najve´i element niza do´i na zadnje mjesto (jer c c c c je ve´i od svih, pa ´e se stalno raditi zamjene). Dakle, njega viˇe ne moramo provjeravati. c c s Zbog toga moˇemo malo smanjiti obim posla koji raˇunalo mora obaviti: z c Malo brˇi Bubble sort. z
1 2 3 4 5 6 7 8 9 10 11 12 13

int n e r e d ; int z a d n j i = n ; do { nered = 0 ; z a d n j i −−; for ( i = 0 ; i < z a d n j i ; i ++) i f ( a [ i ] > a [ i +1]) { double temp = a [ i ] ; a[ i ] = a[ i + 1]; a [ i + 1 ] = temp ; nered = 1 ; } } while ( n e r e d ) ;

Iz ovog rjeˇenja je oˇito i koliko puta ´e se izvrˇavati tijelo for() petlje u najgorem s c c s sluˇaju: u prvom koraku while()-petlje n − 1 put, u drugom n − 2 puta, . . . , u zadnjem c koraku jednom. Dakle, ukupno: n(n − 1) 2 ˇto znaˇi da i ovaj algoritam, sliˇno klasiˇnom sortu, ima kvadratnu sloˇenost. Ipak, ta s c c c z sloˇenost se postiˇe u najgorem i u prosjeˇnom sluˇaju, ali u idealnom sluˇaju (kad je z z c c c niz ve´ sortiran), algoritam samo n − 1 puta izvrˇava if() (i provjeru uvjeta i inkrement c s for()-petlje), te tri puta pridruˇivanje (zadnji = n, nered = 0 i zadnji--) i jednom z provjeru uvjeta do...while petlje. Ukupno, sloˇenost (u idealnom sluˇaju!) je samo z c linearna, ˇto je ipak brˇe od klasiˇnog sortiranja. s z c (n − 1) + (n − 2) + · · · + 2 + 1 =

11.5

Pretraˇivanje z

Zadatak 11.5.1. Neka je uˇitan niz cijelih brojeva x duljine n. Napiˇite dio programa c s koji ´e provjeriti nalazi li se u nizu x zadani cijeli broj y. Ako se nalazi, potrebno je c

142

11. Nizovi (polja)

ispisati njegov indeks; u protivnom treba ispisati odgovaraju´u poruku. c Rjeˇenje. “Trˇimo” po svim elementima niza. Ako nademo y, prekidamo “trˇanje”. Nas c c kon petlje provjeravamo jesmo li iz petlje izaˇli jer je indeks “izletio” iz niza (tj. postao s prevelik). Ako je, znaˇi da nismo naˇli traˇeni broj; u protivnom, broj se nalazi na indeksu c s z na kojem smo prekinuli petlju:
1 2 3 4 5 6 7 8

int i ; for ( i = 0 ; i < n ; i ++) i f ( x [ i ] == y ) break ; i f ( i < n) p r i n t f ( ” Broj %d s e n a l a z i u n i z u i ima i n d e k s %d\n” , y, i ); else p r i n t f ( ” Broj %d s e ne n a l a z i u n i z u . \ n” , y , i ) ;

Zadatak 11.5.2. Neka je uˇitan uzlazno sortirani niz cijelih brojeva x duljine n. Nac piˇite dio programa koji ´e provjeriti nalazi li se u nizu x zadani cijeli broj y. Ako se s c nalazi, potrebno je ispisati njegov indeks; u protivnom treba ispisati odgovaraju´u poruku. c Oˇito, ovaj zadatak moˇemo rijeˇiti jednako kao i prethodni, no moˇemo i efikasnije, c z s z koriˇtenjem podatka da je niz (uzlazno) sortiran. Osnovna ideja je iskoristiti sljede´u s c ˇinjenicu (koja vrijedi za sortirane nizove): c

x < ai ⇒ (∀j ≥ i : x < aj ) x > ai ⇒ (∀j ≤ i : x > aj ) Dakle, prvi “sumnjivi” element niza, tj. onaj koji provjeravamo, nalazi se u sredini (ima indeks ⌊ n ⌋). Ako je to element niza koji traˇimo, problem je rijeˇen. Ako nije, onda z s 2 – ovisno o tome je li taj element ve´i ili manji od traˇenog broja – znamo da se traˇeni c z z n broj ne nalazi u prvih ili u zadnjih ⌊ 2 ⌋ + 1 elemenata niza. U svakom sluˇaju, odjednom c smo “rijeˇili” barem pola niza. s Korak algoritma koji pretraˇuje elemente niza od indeksa lijevi do indeksa desni z moˇemo zapisati opisno: z • srednji =
lijevi+desni 2

• Ako je x = asrednji : Broj je naden ⇒ STOP • Ako je x < asrednji ≤ asrednji+1 ≤ . . . : Broj se ne nalazi desno od srednjeg, pa u idu´em koraku ne treba gledati niˇta od c s

} i f ( l i j e v i <= d e s n i ) p r i n t f ( ” Broj %d s e n a l a z i u n i z u i ima i n d e k s %d\n” . z z zamislite kako biste u telefonskom imeniku naˇli neku osobu kad ne biste uzeli u obzir da s je imenik abecedno sortiran. u protivnom treba ispisati odgovaraju´u poruku. Neka je uˇitan silazno sortirani niz cijelih brojeva x duljine n. nula i c c n − 1. x ) . Kao ilustraciju razlike ova dva algoritma.11. if (x < a [ srednji ]) desni = srednji − 1. : Broj se ne nalazi lijevo od srednjeg. tj. s r e d n j i . Rjeˇenje. Poˇetne vrijednosti lijevog i desnog su poˇetni prvi i zadnji indeks niza.5. srednji ). z Zadatak 11. s c potrebno je ispisati njegov indeks. \ n” . else l i j e v i = srednji + 1. else p r i n t f ( ” Broj %d s e ne n a l a z i u n i z u . potrebno je primijeniti klasiˇno pretraˇivanje (ono s poˇetka ovog poglavlja). tj.5. s lijevi = srednji + 1 Ovaj postupak ponavljamo dok ne nademo broj ili dok lijevi ne postane ve´i od desnog c (jer je tada dio niza koji gledamo prazan). s z Inaˇe. d e s n i = n − 1 . Pretraˇivanje z 143 sadaˇnjeg srednjeg na desno. Ako se nalazi. nova desna granica je prethodnik s c sadaˇnjeg srednjeg. Napomena 11. nova lijeva granica je sljedbenik s c sadaˇnjeg srednjeg. c . c c z c Klasiˇno pretraˇivanje op´enito nesortiranih nizova ima linearnu sloˇenost. . Napic ˇite dio programa koji ´e provjeriti nalazi li se u nizu x zadani cijeli broj y. while ( l i j e v i <= d e s n i ) { srednji = ( l i j e v i + desni ) / 2. Drugim rijeˇima. i f ( x == a [ s r e d n j i ] ) break .5. dok binarc z c z no pretraˇivanje ima logaritamsku sloˇenost.3. x .1. nego biste prezimena pretraˇivali po redu. . s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 int l i j e v i = 0 . pa u idu´em koraku ne treba gledati niˇta prije c s sadaˇnjeg srednjeg (niti njega). tj. Prikazani algoritam zovemo binarno pretraˇivanje i moˇemo ga z z primijeniti kad god imamo niz koji je sortiran po istom kriteriju po kojem vrˇimo traˇenje. s desni = srednji − 1 • Ako je x > asrednji ≥ asrednji−1 ≥ . Drugim rijeˇima.

ispiˇite sve. c s s Uputa. b r o j : ” . for ( i = 0 . Napiˇite program koji u niz uˇitava cijele brojeve dok god ne uˇita nulu s c c (ili dok ne uˇita 616 brojeva). p r i n t f ( ” K o l i k o e l e m e n a t a ima n i z ? ” ) .5. &x [ i ] ) .5. i .7. z Zadatak 11. Napiˇite dio programa koji uˇitava prirodni broj n ≤ 1719 i niz x od n s c realnih brojeva. zbrojimo sve elemente i na kraju c c dobivenu sumu podijelimo s brojem elemenata. n a raˇunamo ju tako da “protrˇimo” kroz cijeli niz.6: Napiˇite dio programa koji uˇitava n realnih broc s c jeva (n < 19 je zadan).144 11.6.5. Ovdje je potrebno napraviti dvije petlje: jednu koja ´e traˇiti max i drugu koja ´e ispisati sve one brojeve c z c ˇija je udaljenost od sljedbenika jednaka max. s 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 double x [ 1 7 1 9 ] . Nizovi (polja) Ponekad traˇimo sve elemente koji odgovaraju nekom kriteriju. i < n . Ako takvih ima viˇe. Aritmetiˇku sredinu niza definiramo formulom: c AS(a) = n−1 i=0 ai n = a0 + a1 + · · · + an−1 . Program treba ispisati indekse onih elemenata niza kojima c je prva znamenka manja od zadnje. Sliˇno zadatku 11. s c a n f ( ”%d” .1. / ∗ o d m a h r a c u n a m o s u m u e l e m e n a t a } a s /= n .4. a s += x [ i ] . ne pomaˇe. i ++) { p r i n t f ( ” U n e s i t e %d . u pravilu. . Ova modifikacija nije jednostavna kao ona od zadatka 11. int n . Program treba izraˇunati aritmetiˇku sredinu niza i ispisati sve elemente c c niza koji su strogo manji od aritmetiˇke sredine. Rjeˇenje. c Zadatak 11. / ∗ s u m u j o s t r e b a p o d i j e l i t i s n ∗ / /∗ /∗ ” T r c i m o ” m a n j i od po n i z u i i s p i s u j e m o s r e d i n e e l e m e n t e ∗/ k o j i a r i t m e t i c k e n i z a ∗/ su ∗/ for ( i = 0 . Zadatak 11. i < n . Tada nam sortiranost z niza. a s = 0 . &n ) . Potrebno je ispisati indeks i vrijednost broja koji je najudaljeniji (ima najve´u razliku) od svog sljedbenika. s c a n f ( ”%l g ” . x [ i ] ) .5. i + 1 ) .1. i ++) i f ( x [ i ] < a s ) p r i n t f ( ”%g\n” . c Podsjetnik s predavanja.

no takva rjeˇenja su ˇesto memoz s c s c rijski zahtjevna i komplicirana za izvodenje. moˇe rjeˇavati kreiranjem pomo´nih nizova.7 (Slag na kraju). Rjeˇenje. No.5. c Napomena 11.6. j >= i .6 Dodavanje i brisanje elemenata Ponekad je potrebno u nizove dodati nove ili izbrisati neke od starih elemenata. a s c zatim – ako takav postoji – sve elemente iza njega treba pomaknuti za jedno mjesto udesno c i broj n pove´ati za 1. Duljina niza pohranjena je u varijabli n.1 Dodavanje elemenata Dodavanje elemenata smo ve´ vidjeli u onoj najjednostavnijoj formi: uˇitavanje (svaki c c uˇitani broj dodajemo na kraj do tada uˇitanog niza).6. Dodavanje i brisanje elemenata 145 ˇ Zadatak 11. Sljede´e pomicanje je pogreˇno jer ´e “pregaziti” sve elemente c s c iza i-tog (pokuˇajte za niz 2.1. 1 2 3 4 5 6 7 8 9 10 11 12 13 /∗ T r a z e n j e p r v o g n e p a r n o g ∗/ for ( i = 0 . 5): s . Prilikom pomicanja elemenata udesno vaˇno je da petlja po varijabli z j ide s desna nalijevo. Prvo je potrebno na´i prvi neparni broj. i f ( i < n) { /∗ P o m i c a n j e s v i h i z a i − t o g ∗/ for ( j = n−1. i < n .11. −−j ) x [ j +1] = x [ j ] . c 11. niz ´e ostati nepromijenjen. Dodavanje radimo u dva koraka. /∗ S m a n j i m o n ∗/ ++n . /∗ Z a p i s u j e m o n o v i e l e m e n t ∗/ x [ i ] = 17. c Zadatak 11. c 11. ponekad elemente treba c c dodati na poˇetak ili drugdje. To se. Program treba ispisati one elemente c c niza kojima je suma znamenka prost broj ve´i od 17. 4. } Primijetite: ako u nizu nema neparnih brojeva. ++i ) i f ( x [ i ] % 2 ) break .1. Napiˇite dio programa koji ´e u uˇitani niz x cijelih brojeva dodati broj s c c 17 ispred prvog neparnog broja. naravno.6. Dodavanje i brisanje elemenata moˇemo z jednostavno raditi na postoje´im nizovima.6. Napiˇite program koji u niz uˇitava prirodne brojeve dok s c god ne uˇita prost broj (ili dok ne uˇita 616 brojeva). 3.

i f ( i < n) { /∗ P o m i c a n j e s v i h i z a i − t o g ∗/ for ( j = n−1. ++j ) x [ j +1] = x [ j ] . Zadatak 11. j < n . Duljina niza pohranjena je u varijabli n. uz jedinu razliku u petlji za pomak udesno s s c (linija 7) i zadavanju vrijednosti 17 (linija 12). Napiˇite dio programa koji ´e u uˇitani niz x cijelih brojeva dodati s c c brojeve 17 i 19 a) ispred b) iza c) i ispred i iza prvog neparnog broja.6. ++i ) i f ( x [ i ] % 2 ) break .146 11. Napiˇite dio programa koji ´e u uˇitani niz x cijelih brojeva dodati broj s c c 17 iza prvog neparnog broja. /∗ S m a n j i m o n ∗/ ++n . Napiˇite dio programa koji ´e u uˇitani niz x cijelih brojeva dodati s c c brojeve 17 i 19 a) ispred b) iza c) i ispred i iza zadnjeg neparnog broja.3.6. . s Zadatak 11. Zadatak 11. } Alternativno. mogli smo samo prije ubacivanja (tj. Duljina niza pohranjena je u varijabli n. i < n . /∗ Z a p i s u j e m o n o v i e l e m e n t ∗/ x [ i +1] = 1 7 . Rjeˇenje je identiˇno prethodnom. j > i . 1 2 3 4 5 6 7 8 9 10 11 12 13 /∗ T r a z e n j e p r v o g n e p a r n o g ∗/ for ( i = 0 .4. prije linije 6 ili 7) pove´ati vrijednost c varijable i za 1 i u potpunosti primijeniti rjeˇenje prethodnog zadatka. Duljina niza pohranjena je u varijabli n.6.2. Nizovi (polja) 6 7 8 /∗ P o m i c a n j e s v i h i z a i − t o g ∗/ for ( j = i . −−j ) x [ j +1] = x [ j ] . Rjeˇenje.

i . p r i n t f ( ” Unesite duljinu niza : ” ) .1).6. Jedino ˇto se mijenja je dio programa koji traˇi referentni ˇlan. ++i ) { p r i n t f ( ” U n e s i t e %d . x [ i ] ) .1 treba i´i unatrag (od n − 1 do 0). i +1). no takvo rjeˇenje bilo bi komplicirano i sporo. c l a n n i z a : ” . for ( i = 0 . Umjesto toga.6. for ( i = 1 . potrebno je prvo izraˇunati novu duljinu niza. Petlja u liniji 2 s z c c rjeˇenja zadatka 11.6. U petlju u liniji s z c 2 rjeˇenja zadatka 11. ++i ) p r i n t f ( ” . c Zadatak 11. Jedino ˇto se mijenja je dio programa koji traˇi referentni ˇlan. n2 . j . b r d o d a n i h = 0 . c Uputa. Dodavanje i brisanje elemenata 147 Uputa. h> void i s p i s ( int x [ ] .6.6. Napiˇite dio programa koji ´e u uˇitani niz x cijelih brojeva dodati broj s c c 2xk ispred svakog neparnog broja xk . kao i kod pomicanja elemenata za jedno mjesto (iz istog razloga koji je objaˇnjen u napomeni 11.6. p r i n t f ( ”%d” . s c a n f ( ”%d” . Duljina niza pohranjena je u varijabli n.1 treba dodati brojaˇ koji se pove´ava sa svakim pronadenim s c c neparnim brojem. } int main ( void ) { int x [ 1 7 1 9 ] .1. Petlja se prekida kad taj brojaˇ dostigne vrijednost 3. c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <s t d i o .11. Napiˇite dio programa koji ´e u uˇitani niz x cijelih brojeva dodati s c c brojeve 17 i 19 a) ispred b) iza c) i ispred i iza tre´eg neparnog broja. s Zadatak 11. x [ 0 ] ) . &n ) . %d” . prepisuju´i elemente na njihova nova mjesta. i < n . Postavlja se pitanje s odakle krenuti? Da bismo to znali. n .6. i < n . p r i n t f ( ”\n” ) . Ovaj bismo zadatak mogli rijeˇiti viˇestrukim ponavljanjem rjeˇenja zadatka s s s s 11. c Kroz niz je potrebno prolaziti s desna na lijevo.6. Rjeˇenje. int n ) { int i .5. . zadatak ´emo rijeˇiti s c s jednim prolazom kroz cijeli niz. Duljina niza pohranjena je u varijabli n.

148

11. Nizovi (polja)

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 /∗ /∗

s c a n f ( ”%d” , &x [ i ] ) ; } p r i n t f ( ”\ n P r i j e dodavanja : ” ) ; i s p i s (x , n ) ;
Ra \ v { c } u n a n j e n o v e d u l j i n e n i z a ∗/

for ( i = 0 ; i < n ; ++i ) i f ( x [ i ] % 2 == 1 ) ++b r d o d a n i h ; n2 = n + b r d o d a n i h ;
D o d a v a n j e n o v i h e l e m e n a t a ∗/

j = n2 − 1 ; for ( i = n − 1 ; i >= 0 ; −−i ) { x[ j ] = x[ i ]; −−j ; i f ( x [ i ] % 2 == 1 ) { x[ j ] = 2 ∗ x[ i ]; −−j ; } } n = n2 ; p r i n t f ( ”Nakon dodavanja : ” ) ; i s p i s (x , n ) ; return 0 ; }

11.6.2

Brisanje elemenata

Zadatak 11.6.7. Napiˇite dio programa koji iz uˇitanog niza x cijelih brojeva briˇe prvi s c s parni broj. Duljina niza pohranjena je u varijabli n. ˇ Napomena 11.6.2 (Ceste greˇke). Elemente koje ˇelimo obrisati nije dovoljno zamijeniti s z s nulom, jer je to samo zamjena elemenata drugom vrijednoˇ´u, a broj elemenata u nizu sc ostaje nepromijenjen. Takoder, nije dovoljno niti samo ispisati niz bez elemenata koje ˇelimo obrisati, jer se z samim ispisom niz uop´e ne mijenja i ti elementi i dalje ostaju njegovi ˇlanovi. c c Rjeˇenje zadatka 11.6.7. Sliˇno rjeˇenju zadatka 11.6.1, brisanje radimo u dva koraka. s c s Prvo je potrebno na´i prvi parni broj, a zatim – ako takav postoji – sve elemente iza c njega treba pomaknuti za jedno mjesto ulijevo i broj n smanjiti za 1.

11.6. Dodavanje i brisanje elemenata

149

1 2 3 4 5 6 7 8 9 10 11 12 13

/∗

T r a z e n j e

p r v o g

p a r n o g

∗/

for ( i = 0 ; i < n ; ++i ) i f ( x [ i ] % 2 == 0 ) break ; i f ( i < n) {
/∗

P o m i c a n j e

s v i h

i z a

i − t o g

∗/

while ( i +1 < n ) { x [ i ] = x [ i +1]; ++i ; }
/∗ S m a n j i m o n ∗/

}

−−n ;

Zadatak 11.6.8. Napiˇite dio programa koji iz uˇitanog niza x cijelih brojeva briˇe zadnji s c s parni broj. Duljina niza pohranjena je u varijabli n. Zadatak 11.6.9. Napiˇite dio programa koji iz uˇitanog niza x cijelih brojeva briˇe prvi s c s parni broj i idu´a dva elementa iza njega. Duljina niza pohranjena je u varijabli n. c Napomena 11.6.3. Pripazite postoje li traˇena dva elementa niza. Na primjer, ako je z prvi parni broj u nizu predzadnji element, onda iza njega postoji samo jedan element niza, pa ´e ukupni broj obrisanih elemenata biti dva, a ne tri. c Zadatak 11.6.10. Napiˇite program koji uˇitava prirodni broj n ≤ 1719 i niz x od n s c realnih brojeva. Program treba iz niza obrisati sve elemente koji su strogo manji od aritmetiˇke sredine svih elemenata niza, te ispisati tako nastali niz i novu aritmetiˇku sredinu c c niza. Rjeˇenje. Ovaj zadatak moˇemo rijeˇiti viˇestrukim ponavljanjem rjeˇenja prethodnog s z s s s zadatka, no to znaˇi da ´emo mnogo elemenata pomicati viˇe puta po jedno mjesto, ˇto c c s s je sporo. Zato ovakvo brisanje (linije 35–44) radimo, kao i kod viˇestrukog dodavanja u zadatku s 11.6.6, na naˇin da po redu ˇitamo sve elemente (indeks i). One koje ne treba obrisati, c c prepisujemo na nove pozicije te pove´avamo odgovaraju´i indeks (j) kako bi bio spreman c c za zapisivanje idu´eg broja. Za elemente koje treba obrisati, pamtimo koliko je obrisanih c (varijabla br_obrisanih), ali ne mijenjamo indeks j. Na kraju je potrebno smanjiti vrijednost u varijabli n koja drˇi duljinu niza. z
1 2 3 4 5

#include <s t d i o . h> #include < s t d l i b . h> void p r o v j e r i n ( int n ) {
/∗ a r i t m e t i c k a s r e d i n a

n i j e

d e f i n i r a n a

za

p r a z n e

n i z o v e

∗/

150

11. Nizovi (polja)

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51

}

i f ( n == 0 ) { p r i n t f ( ” Niz j e prazan . ” ) ; exit (0); }

double a r s r ( double n i z [ ] , int n ) { int i ; double sum = 0 ; for ( i = 0 ; i < n ; ++i ) sum += n i z [ i ] ; return sum / n ; } int main ( void ) { double x [ 1 7 1 9 ] , a s ; int n , i , j = 0 , b r o b r i s a n i h = 0 ; p r i n t f ( ” Unesite duljinu niza : ” ) ; s c a n f ( ”%d” , &n ) ; provjeri n (n ) ; for ( i = 0 ; i < n ; ++i ) { p r i n t f ( ” U n e s i t e %d . c l a n n i z a : ” , i +1); s c a n f ( ”%l f ” , &x [ i ] ) ; } as = a r s r (x , n ) ; p r i n t f ( ” A r i t m e t i c k a s r e d i n a p r i j e b r i s a n j a : %g\n” , a s ) ;
/∗ B r i s a n j e ∗/

for ( i = 0 ; i < n ; ++i ) { i f ( x [ i ] < as ) { ++b r o b r i s a n i h ; continue ; } if ( i > j ) x[ j ] = x[ i ]; ++j ; } n −= b r o b r i s a n i h ; provjeri n (n ) ; as = a r s r (x , n ) ; p r i n t f ( ” A r i t m e t i c k a s r e d i n a nakon b r i s a n j a : %g\n” , a s ) ; p r i n t f ( ”%g” , x [ 0 ] ) ; for ( i = 1 ; i < n ; ++i )

pa njih moˇemo s z mijenjati bez posebnih “zahvata”. Podsjetimo se: niz je odreden s dva podatka.6. Program treba iz niza obrisati sve elemente kojima je index neka potencija broja 2. polja se uvijek prenose kao varijabilni argumenti. int i .6.14. Program treba iz niza obrisati sve elemente koji su strogo ve´i od svog c prvog susjeda slijeva.15. Program treba iz niza obrisati sve elemente kojima je index prost broj. Prilikom brisanja elemen(a)ta. Napiˇite program koji uˇitava prirodni broj n ≤ 1719 i niz x od n s c realnih brojeva. no nije primjenjiv kad funkcija mora vratiti joˇ neku vrijednost. te ispisati tako nastali niz. potrebno je smanjiti duljinu niza. . return 0 . te ispisati tako nastali niz. treba obrisati samo najljevijeg s od njih.6. s Kao ˇto znamo. Napiˇite program koji uˇitava prirodni broj n ≤ 1719 i niz x od n s c realnih brojeva. Ako se taj pojavljuje u nizu viˇe puta.6. Napomena 11. /∗ Ako j e n i z p r a z a n . Zadatak 11. Napiˇite program koji uˇitava prirodni broj n ≤ 1719 i niz x od n s c realnih brojeva. Prvi naˇin je obiˇno c c jednostavniji. To moˇemo napraviti ili z preko povratne vrijednosti funkcije ili preko varijabilnih argumenata.4.6). x [ i ] ) .6. te ispisati tako nastali niz.6. te ispisati tako nastali niz.6. Napiˇite funkciju koja prima niz realnih brojeva. c Zadatak 11.6. ˇto znaˇi da funkcija mora primiti s s c barem dva argumenta (polje i duljinu niza).13. int ∗n ) { double min . Program treba iz niza obrisati sve elemente kojima je index izmedu 7 i 19.11. Zadatak 11.11. Zadatak 11. te iz njega briˇe s s najmanji element. Napiˇite program koji uˇitava prirodni broj n ≤ 1719 i niz x od n s c realnih brojeva.12. Dodavanje i brisanje elemenata 151 52 53 54 55 56 p r i n t f ( ” . j . Zadatak 11. } Kod viˇestrukog dodavanja kroz niz prolazimo slijeva na desno. rjeˇenje c s zadatka 11. Rjeˇenje. nemamo s t o r a d i t i ∗/ i f ( n == 0 ) return . p r i n t f ( ”\n” ) . /∗ T r a z i m o n a j m a n j i e l e m e n t n i z a ∗/ min = x [ 0 ] . te ju nekako vratiti u glavni program. Utoliko je brisanje jednoss tavnije od dodavanja jer nije potrebno unaprijed izraˇunati novu duljinu niza (v. %g” . Pripazite odakle ˇitate niz. jer prvi element niza nema lijevih susjeda. 1 2 3 4 5 6 7 void b r i s i ( double x [ ] .

/∗ B r i s e m o p r v o p o j a v l j i v a n j e n a j m a n j e g e l e m e n t a n i z a ∗/ } for ( i = 0 .6. n ) . int i . i < n . s c . ++i ) i f ( x [ i ] < min ) min = x [ i ] .18. Ovakvo rjeˇenje ne´e biti primjenjivo u zadatku 11. } } Primjer poziva funkcije: 1 2 3 4 double x [ 1 7 1 9 ] . nemamo s t o r a d i t i ∗/ i f ( n == 0 ) return 0 . n = b r i s i (x . /∗ T r a z i m o n a j m a n j i e l e m e n t n i z a ∗/ min = x [ 0 ] . int n ) { double min . Nizovi (polja) 8 9 10 11 12 13 14 15 16 17 18 for ( i = 1 . j < n . b r i s i ( x . return . i < ∗n . int n . j . &n ) . ++i ) i f ( x [ i ] < min ) min = x [ i ] . int n .. ++j ) x [ j −1] = x [ j ] .. . for ( i = 1 . i < n . −−(∗n ) .152 11. /∗ Ako j e n i z p r a z a n . } } Primjer poziva funkcije: 1 2 3 4 double x [ 1 7 1 9 ] . −−n . ++i ) { i f ( x [ i ] == min ) { for ( j = i +1. Ista funkcija bez varijabilnih argumenata izgleda ovako: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int b r i s i ( double x [ ] . /∗ B r i s e m o p r v o p o j a v l j i v a n j e n a j m a n j e g e l e m e n t a n i z a ∗/ } for ( i = 0 . return n . ++i ) { i f ( x [ i ] == min ) { for ( j = i +1. .. j < ∗n . i < ∗n .. ++j ) x [ j −1] = x [ j ] .

Napiˇite funkciju koja prima niz realnih brojeva. . treba obrisati sve njih.17. Funkcija s kao povratnu vrijednost treba vratiti broj obrisanih elemenata.6. treba obrisati sve njih.18. Napiˇite funkciju koja prima niz realnih brojeva. treba obrisati samo najdesnijeg s od njih. Dodavanje i brisanje elemenata 153 Zadatak 11. s Uputa. Rjeˇenje je jednako prvom iz zadatka 11. te iz njega briˇe s s najmanji element.16.6. s Uputa. te iz njega briˇe s s najmanji element. Ako se taj pojavljuje u nizu viˇe puta.6. uz promjenu smjera unutraˇnje s petlje kod brisanja (linija 13). Napiˇite funkciju koja prima niz realnih brojeva. uz brisanje naredbe return u liniji s 15.6.11.15. Ako se taj pojavljuje u nizu viˇe puta. Zadatak 11. Rjeˇenje je jednako prvom iz zadatka 11. Zadatak 11. Ako se taj pojavljuje u nizu viˇe puta. te iz njega briˇe s s najmanji element.6.6.15.

140 djelitelji. 95 Bubble sort. 117. 111 on-line sadrˇaj z nizovi. 24 pretvaranje u dekadsku bazu. 24 brojevni sustavi. 125 brzo potenciranje. 148 brojevni sustavi. 29 z disjunktivna. 6 z jezik. 72 traˇenje baze. 93 Euklidov. 136 suma brojeva. 4 automat. 1 ˇeste greˇke. 107 Hornerov. 142 z brojanje znamenaka. 67 formule za pojednostavljivanje logiˇkih izrac za. 82 suma znamenaka. 113 prosti djelitelji (uz kratnost). 36 c specijalni znakovi. 27 c normalne forme broj 1 nije ni prost ni sloˇen. 41 pretvaranje iz dekadske baze. 136 c produkt brojeva. 59 binarno traˇenje. 133 c klasiˇni sort. 103 jezik. 89 provjera jednakosti formula raˇuna suc pridruˇivanje u uvjetima. 76 funkcije. 9. 111. 76 z dova. 88 raˇun sudova. 148 c s ˇeste greˇke c s inicijalizacija. 24 formati. 131 Hornerov (op´i oblik). 126 grananje ˇeste greˇke. 11 c s komentari. 66 direktno pretvaranje izmedu baza bn1 i konaˇni c bn2 . 76 c s switch(). 24 C-ovski zapis “a > b. 29 154 . 94 provjera je li broj prost. c”. 6 c nizovi ˇeste greˇke. 6 petlja u petlji. 27 funkcije ˇeste greˇke. 3 konjunktivna normalna forma. 41 brojevni sustavi. 2 raˇunske operacije. 40 on-line vjeˇbalica. 113 sort. 117 disjunktivna normalna forma. 11 z varijabilni argumenti funkcija. 118 zamjena varijabli. 122 1 + 1 = 2 u raˇunu sudova. 9 konjunktivna.Indeks algoritmi. 93. 118 c s nizovi kao argumenti. 99 prosti djelitelji.

32 verzije s viˇe ulaza. 121 ˇeste greˇke. 31 potpuno zbrajalo. 19 . 41. 27 negacija implikacije.INDEKS 155 vjeˇbalica za normalne forme. 41 sklopovi osnovni. 30 poluzbrajalo. 98 “crtanje”. 29 operatori (opisno).. 20 c operatori raˇuna sudova (pomo´u tablice isc c tinitosti). 72 c s osnovni. 27. 71 nizovi. 19 tablica istinitosti. 42 regularni jezik. 89 c s do. 74 traˇenje najve´eg cijelog broja.. 15. 96 continue. 26 z varijable. 20 palindrom. 20 tipovi podataka operatori. 31 s zbrajanje binarnih brojeva. 20 c regularni izraz. 29. 74 op=. 21 on-line provjera jednakosti formula. 101 ˇeste greˇke. 79 program osnovni dijelovi.while(). 81 while(). 34 sud. 36 c s De Morganove formule. 53 petlje break. 61 raˇun sudova c ˇeste greˇke. 73 operatori raˇuna sudova (opisno). 42 oznake. 20 operatori (pomo´u tablice istinitosti). 65 dekrement. 21 formule za pojednostavljivanje. 82 for(). 84 z c inkrement. 21 obrat po kontrapoziciji.