Zanka while
Spoznali smo že pogojni stavek if
-else
, ki nam
omogoča, da program izvede ene ali druge ukaze, glede na to ali
je dani pogoj izpolnjen. Včasih pa želimo v programu kake ukaze
ponavljati, dokler je izpolnjen dani pogoj. To naredimo z
zanko.
Java pozna tri vrste zank: zanka while
, zanka
for
in zanka do
. Najbolj osnovna je zanka
while
.
Zanka while
ima naslednjo obliko:
To pomeni:
"če je izpolnjen pogoj p
, izvedi ukaze
A
, nato ponovi zanko." Shematično to prikažemo takole:
Ukazi
A
se imenujejo
telo zanke,
p
pa je
pogoj.
Zanke s preprostimi števci
Kot prvi primer napišimo program, ki na zaslon izpiše vsa cela
števila od 1 do 100:
StoStevil.java |
---|
1
2
3
4
5
6
7
8
9
| public class StoStevil {
public static void main(String[] args) {
int i = 1;
while (i <= 100) {
System.out.print(i);
i = i + 1;
}
}
} |
> javac StoStevil.java
> java StoStevil
12345678910111213141516171819202122232425262728293031323334353637383940414243444
54647484950515253545556575859606162636465666768697071727374757677787980818283848
58687888990919293949596979899100 |
Ker smo uporabili ukaz
System.out.print
, so se števila
izpisala eno za drugim brez kakeršnihkoli vmesnih presledkov.
Program uporabi spremenljivko
i
z začetno vrednostjo
1
, ki ji v vsaki izvedbi prišteje
1
. Ko se
vrednost
i
poveča do
101
, se zanka ustavi, ker
pogoj
i <= 100
ni izpolnjen.
Seveda lahko izvedemo zanko tudi kako drugače. Na primer,
lahko bi začeli z drugačno začetno vrednostjo i
, ali pa
bi v vsakem koraku prišteli 2
namesto 1
. Prav
tako bi lahko spreminjali pogoj i <= 100
.
Oglejmo si še en primer: program, ki izpiše vsa liha števila med
-10 in 33 v padajočem vrstnem redu. Tokrat naj se vsako število
izpiše v svojo vrstico. Sedaj je treba šteti od začetne
vrednosti
33
in v vsakem koraku
odšteti2
. Pogoj za izvajanje zanke pa je, da mora biti števec
i
večji ali enak
-10
.
LihaStevila.java |
---|
1
2
3
4
5
6
7
8
9
| public class LihaStevila {
public static void main(String[] args) {
int i = 33;
while (i >= -10) {
System.out.println(i);
i = i - 2;
}
}
} |
> javac LihaStevila.java
> java LihaStevila
33
31
29
27
25
23
21
19
17
15
13
11
9
7
5
3
1
-1
-3
-5
-7
-9 |
Spoznali bomo še mnogo drugih vrst uporabe zanke
while
.
Na primer, ni nujno, da ima zanka
while
števec
i
, s katerim kaj štejemo. Lahko se tudi zgodi, da imamo
znotraj zanke
while
še eno zanko (takim zankam pravimo
dvojne ali
vgnezdene zanke).
Premisli, kaj počne naslednji program:
Klop.java |
---|
1
2
3
4
5
6
7
| public class Klop {
public static void main(String[] args) {
while (true) {
System.out.print("klop pod klopjo, ");
}
}
} |
Če razumete, kako deluje zanka
while
, potem ste
odgovorili, da izpisuje niz
"klop pod klopjo"
v
nedogled:
> javac Klop.java
> java Klop
klop pod klopjo, klop pod klopjo, klop pod klopjo, klop pod klopjo, klop pod klo
pjo, klop pod klopjo, klop pod klopjo, klop pod klopjo, klop pod klopjo, klop po
d klopjo, klop pod klopjo, klop pod klopjo, klop pod klopjo, klop pod klopjo, kl
op pod klopjo, klop pod klopjo, klop pod klopjo, klop pod klopjo, klop pod klopj
o, klop pod klopjo, klop pod klopjo, klop pod klopjo ... |
Naloga 1
Kaj počne naslednji program?
RibaRacaRak.java |
---|
1
2
3
4
5
6
7
8
9
| public class RibaRacaRak {
public static void main(String[] args) {
int i = 100;
while (i > 100) {
System.out.print("riba raca rak ");
i = i + 1;
}
}
} |
Namig
Pozorno preberi program.
[
rešitev]
Vidimo, da zanko while
uporabimo, kadar je treba
ponavljati kako zaporedje ukazov. Vedno moramo poskrbeti, da se
zanka ustavi (razen če namenoma pišemo program, ki se nikoli ne
ustavi).
Oglejmo si še en primer bolj podrobno. Denimo, da želimo s
programom izračunati vsoto števil
1 + 2 + 3 + ... + 99 +
100. To lahko naredimo na tri načine:
Ker smo matematiki, vemo, da je 1 + 2 + 3 + ... + n
aritmetična vrsta in da je njena vsota enaka
n(n+1)/2. Torej je vsota prvih sto števil enaka
101 * 100 / 2
in programa sploh ni treba pisati.
Napišemo program
VsotaBednaResitev.java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| public class VsotaBednaResitev {
public static void main(String[] args) {
int vsota = 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 +
41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 +
51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 +
61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 +
71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 +
81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 +
91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 + 100;
}
} |
To je precej nepraktična rešitev, ki se ne bi obnesla, če bi
želeli izračunati večjo vsoto, na primer od 1 do 1000000.
Uporabimo zanko while
.
Kako torej napišemo program, ki s pomočjo zanke
while
sešteje števila od 1 do 100? Tako kot v primeru, ko smo izpisali
števila od 1 do 100, v zanki štejemo s spremenljivko
i
od 1 do 100. Poleg tega pa uvedemo še eno spremenljivko
vsota
, ki ji v vsakem koraku zanke prištejemo vrednost
i
. Ko se zanka konča, je želena vsota shranjena v
spremenljivki
vsota
:
Vsota.java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| public class Vsota {
public static void main(String[] args) {
int i = 1;
int vsota = 0;
while (i <= 100) {
vsota = vsota + i;
i = i + 1;
}
System.out.println(vsota);
}
} |
> javac Vsota.java
> java Vsota
5050 |
Ponovimo še enkrat: spremenljivka
vsota
je na začetku
0. Po vsakem izvajanju zanke, se k njen prišteje vrednost
spremenljivke
i
. Ker spremenljivka
i
šteje od
1 do 100, se v
vsota
nabere seštevek vseh celih števil
od 1 do 100.
V naslednji nalogi se naučimo, da lahko uporabimo v programu več
zank, eno za drugo.
Naloga 2
Napiši program, ki izračuna vsoto
V = 12 + 23 + 32 +
43 + ... + 992 + 1003
Namig
Vsoto
V zapiši kot
V = A + B, pri čemer je
A = 12 + 32 + 52 + ... + 992
B = 23 + 43 + 63 + ... + 1003
Z eno zanko izračunaj
A, nato z drugo
B, na
koncu pa seštej
V = A + B.
Naloga 3
Dana je spremenljivka
int n
z neko začetno
vrednostjo (na primer
n = 20
).
Napiši program, ki s pomočjo zanke
while
izpiše na
zaslon
n
zvezdic med njimi pa presledke. V primeru
n = 20
se tako izpiše
* * * * * * * * * * * * * * * * * * * * |
Pozor — za zadnjo zvezdico se
ne
sme izpisati še en presledek.
Namig
Z zanko while
izpiši n-1
zvezdic s
spresledki. Po koncu zanke izpiši še eno zvezdico.
[
rešitev]
Naloga 4
Napiši program
SteviloDeliteljev.java
, ki iz
standardnega vhoda prebere pozitivno celo
število
n
in na zaslon izpiše, koliko deliteljev
ima
n
. Primer uporabe:
> java SteviloDeliteljev
Vpisi stevilo: 12
Stevilo 12 ima 6 deliteljev. |
Število 12 ima namreč naslednje delitelje: 1, 2, 3, 4, 6, 12.
Namig
Pomagali si bomo s spremenljivko int d = 0
in
napisali zanko, ki bo d
nastavila na število
deliteljev n
.
Zanka naj s števcem k
šteje od 1
do
n
in vsakič preveri, ali je k
delitelj
n
. Če je, potem poveča d
za ena.
Ko se zanka konča, vsebuje d
želeno vrednost.
Zanke brez števcev
Do sedaj smo videli zanke, ki se ponavljajo v nedogled, in take,
ki uporabijo števec. Seveda pa to ni edini način za uporabo
zank. Oglejmo si primer zanke, v kateri niso uporabljena števila
in števci.
V spremenljivki String s
je shranjen niz znakov.
Napraviti želimo nov niz String t
, ki je tak kot niz
s
brez presledkov na začetku. Na primer, če je niz
s
enak " Trije presledki na zacetku."
, potem
mora biti t
enak "Trije presledki na zacetku."
Pri pisanju programa uporabimo metodo
substring
,
ki vrne podniz danega niza:
s.substring(i,j) |
vrni podniz s od i -tega do
(j-1) -tega znaka
|
Primer uporabe:
PrimerSubstring.java |
---|
1
2
3
4
5
6
7
| public class PrimerSubstring {
public static void main(String[] args) {
String a = "Od nekdaj lepe so Ljubljanke slovele.";
String b = a.substring(6, 20);
System.out.println(b);
}
} |
> java PrimerSubstring
daj lepe so Lj |
Naš program sestoji iz ene zanke, ki v vsakem koraku odstrani
prvi znak iz niza
t
. Začetna vrednost
t
je
enaka
s
. Zanka se ustavi, ko postane
t
prazen
niz, ali pa prvi znak ni presledek.
OdstraniPresledke.java |
---|
1
2
3
4
5
6
7
8
9
10
11
| public class OdstraniPresledke {
public static void main(String[] args) {
String s = " Trije presledki na zacetku.";
String t = s;
while (!t.equals("") && t.charAt(0) == ' ') {
t = t.substring(1, t.length());
}
System.out.println(s);
System.out.println(t);
}
} |
> java OdstraniPresledke
Trije presledki na zacetku.
Trije presledki na zacetku. |
Naloga 5
V spremenljivki String s
je shranjen niz znakov.
Napiši program, ki v spremenljivko String t
shrani
niz, ki je tak kot s
brez presledkov na začetku
in koncu. Na primer, če je s
niz
" Juhica je
pripravljena. "
, potem mora biti
t
enak "Juhica je pripravljena."
Namig
Uporabi dve zanki, eno za drugo. Prva odstrani presledke na
začetku, druga pa na koncu.
Vgnezdene zanke
Oglejmo si sedaj, kako lahko vgnezdimo eno zanko v drugo.
Denimo, da želimo izpisati na zaslon pet vrstic sestavljenih
iz desetih zvezdic, ločenih s presledki:
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * *
* * * * * * * * * * |
Prvi način:
Zvezdice1.java |
---|
1
2
3
4
5
6
7
8
9
| public class Zvezdice1 {
public static void main(String[] args) {
System.out.println("* * * * * * * * * *");
System.out.println("* * * * * * * * * *");
System.out.println("* * * * * * * * * *");
System.out.println("* * * * * * * * * *");
System.out.println("* * * * * * * * * *");
}
} |
Seveda se tak program ne obnese, če želimo izpisati 10000 vrstic
po 10 zvezdic. Bolje je, če uporabimo zanko
while
:
Zvezdice2.java |
---|
1
2
3
4
5
6
7
8
9
| public class Zvezdice2 {
public static void main(String[] args) {
int i = 0;
while (i < 10) {
System.out.println("* * * * * * * * * *");
i = i + 1;
}
}
} |
Ta rešitev je že boljša, vendar se ne bi obnesla, če bi želeli
izpisati 10 vrstic po 10000 zvezdic. Program spremenimo tako, da
vsako vrstico izpiše s pomočjo zanke
while
. Kako se to
naredi, smo že videli v
prejšnji
vaji.
Zvezdice3.java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| public class Zvezdice3 {
public static void main(String[] args) {
int i = 0;
while (i < 10) { // 10 vrstic zvezdic
int j = 0;
while (j < 9) { // 9 zvezdic s presledkom
System.out.print("* ");
j = j + 1;
}
System.out.println("*"); // zadnja zvezdica in pomik v novo vrsto
i = i + 1;
}
}
} |
Vidimo primer
vgnezdene zanke, saj imamo znotraj
ene zanke
while
še eno zanko
while
.
Naloga 6
Kolikokrat se v programu
Zvezdice3.java
izvede 7. vrstica in kolikokrat 10. vrstica, ko ga poženemo?
[
rešitev]
V naslednjem primeru si oglejmo, kaj se zgodi, če želimo v vsaki
vrstici izpisati kaj drugega. Na primer, da želimo s pomočjo
dvojne zanke izpisati na zaslon
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9 |
Ker želimo izpisati 9 vrstic, bo program sestavljen iz zanke, ki
šteje od 1 do 9:
1
2
3
4
5
| int i = 1;
while (i <= 9) {
// tukaj napišemo še eno zanko
i = i + 1;
} |
Kaj pa naj se izvede v notranji zanki? V
i
-ti vrstici moramo
izpisati števila od
1
do
i
. To pa spet naredimo z
zanko, ki šteje od
1
do
i
. To nas privede do
naslednjega programa:
ZankaZanka.java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| public class ZankaZanka {
public static void main(String[] args) {
int i = 1;
while (i < 10) {
int j = 1;
while (j <= i) {
System.out.print(j);
System.out.print(" ");
j = j + 1;
}
System.out.println();
i = i + 1;
}
}
} |
> javac ZankaZanka.java
> java ZankaZanka
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9 |
Naloga 7
Dano je spremenljivka
int n
, z neko začetno
vrednostjo (na primer
n = 8
).
Sestavi program, ki na zaslon izpiše tole (prikazan je primer
n = 8
):
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
6 6 6 6 6 6
7 7 7 7 7 7 7
8 8 8 8 8 8 8 8 |
Uporabi vgnezdeno zanko.
Zanke z dodatnim pogojem za ustavljanje
Včasih želimo, da bi se izvajanje zanke prekinilo, čeprav števec
še ni preštel do konca. To lahko naredimo s pomožno
spremenljivko tipa boolean
, ki jo v telesu zanke
nastavimo na false
, če je treba zanko prekiniti. Pogoj
zanke nato upošteva vrednost spremenljivke.
Za primer vzemimo naslednjo nalogo. Denimo, da želimo poiskati
najmanjše pozitivno celo število med 1 in 100, ki zadošča enačbi
x2 − 21 x = 882.
Če tako število ne obstaja, potem izpišemo na zaslon
"Ni resitve med 1 in 100."
Treba je torej izračunati dva podatka: ali rešitev
obstaja (true
ali false
) in kolikšna je
rešitev (celo število). Torej imam dve spremenljivki,
vsako za en podatek, ki ga je treba izračunati. Prva
spremenljivka je boolean obstaja
, ki se mora
nastaviti na true
, če rešitev obstaja. Druga
spremenljivka je int x
, ki vsebuje rešitev enačbe, v
primeru da rešitev obstaja.
Zanka, ki išče rešitev po vrsti pregleda vse vrednosti
x
med 1 in 100 in preveri, ali katero od njih zadošča enačbi. Če
kako število zadošca enačbi, nastavi
obstaja
na
true
in neha izvajati zanko. Na koncu rešitev še
izpišemo, da vidimo, kaj se je zgodilo.
IsciResitev.java |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| public class IsciResitev {
public static void main(String[] args) {
int x = 1;
boolean obstaja = false;
while (!obstaja && (x <= 100)) {
if (x * x - 21 * x == 882) {
obstaja = true;
}
else {
x = x + 1;
}
}
if (obstaja) {
System.out.print("Resitev: x = ");
System.out.println(x);
}
else {
System.out.println("Ni resitve med 1 in 100.");
}
}
} |
Če izvajanje programa pride v 8. vrstico, se
obstaja
nastavi na
true
in zanka neha izvajati, saj njen pogoj
zahteva, da mora veljati
!obstaja
.
> javac IsciResitev.java
> java IsciResitev
Resitev: x = 42 |
Vaje za ponavljanje
Naloga 8
V spremenljivki int x je dana količina denarja v
tolarjih, ki bi ga radi izplačali s kovanci po 10, 5, 2 in 1
tolar. Na primer, če je x = 38, potem bi izplačali
tri kovance po 10, enega po 5, enega po 2 in enega za 1 tolar.
Sestavi program, ki izračuna, koliko kovancev vsake vrste
moramo izplačati. Število kovancev vsake vrste naj shrani v
spremenljivke int k10, int k5, int
k2, in int k1.
Program naj na koncu še izpiše na zaslon, koliko kovancev
vsake vrste je treba izplačati.
Namig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| public class Denar {
public static void main(String[] args) {
int k = tu vstavi zacetno vrednost;
int k10, k5, k2, k1;
tu napisi svoj program
System.out.print(k + " tolarjev = ");
System.out.print(k10 + " kovancev za 10 + ");
System.out.print(k5 + " kovancev za 5 + ");
System.out.print(k2 + " kovancev za 2 + ");
System.out.println(k1 + " kovancev za 1 tolar.");
}
} |
Naloga 9: Kvadratna enačba
Sestavi program, ki reši kvadratno enačbo in rešitvi izpiše
na zaslon. Če enačba nima realnih rešitev, naj program
izpiše "Ni resitev"
.
Naloga 10: Opis temperature
Sestavi program, ki za dano temperaturo
t
izračuna
njen opis po naslednjih pravilih:
če je t
< -10, je opis "zelo zelo hladno"
.
sicer če je t
< 0, je opis "zelo hladno"
.
sicer, če je t
< 10, je opis "hladno"
.
sicer če je t
< 20, je opis "prijetno"
.
sicer če je t
< 30, je opis "vroče"
.
sicer če je t
≥ 30, je opis "zelo vroče"
.
Naloga 11
V spremenljivki
int k je dano nenegativno število.
Sestavi program, ki na zaslon izpiše
Miha ima k
limon., pri čemer pa mora biti stavek slovnično
pravilen, se pravi:
Miha ima 0 limon.
Miha ima 1 limono.
Miha ima 2 limoni.
Miha ima 3 limone.
Miha ima 4 limone.
Miha ima 5 limon.
Miha ima 6 limon.
(in tako naprej)
Kaj naredi tvoj program, če je
k = 101?
Namig
Uporabi kombinacijo
if-
else takole:
1
2
3
4
5
| if (k == 0) { nic limon }
else if (k == 1) { ena limona }
else if (k == 2) { dve limoni }
else if (k == 3 || k == 4) { tri ali stiri limone }
else { pet ali vec limon } |
Naloge s predavanj in vaj
Naloga 12: Vsota števil
Sestavi diagram poteka in program, ki za dano nenegativno
celo število
n izračuna vrednost vsote
1 + 2 + 3 + ... + n
Naloga 13: Vsota aritmetične vrste
Sestavi diagram poteka in program, ki izračuna vsoto dane
aritmetične vrste.
Naloga 14: Vsota števil
Sestavi diagram poteka in program, ki za dani n izračuna vsoto
vseh produktov i * j, pri čemer je 1 ≤ i, j
≤ n.
Sestavi diagram poteka in program, ki za dani n izračuna vsoto
vseh produktov i * j, pri čemer je 1 ≤ i < j
≤ n.
Naloga 15: Vsota geometrijske vrste
Sestavi diagram poteka in program, ki izračuna vsoto dane
geometrijske vrste.
Naloga 16: Vsota Taylorjeve vrste
Sestavi diagram program, ki izračuna vsoto prvih n členov
Taylorjeve vrste za funkcijo ex, pri
danem x
.
Sestavi diagram program, ki izračuna vsoto prvih n
členov Taylorjeve vrste za funkcijo sin(x), pri
danem x
.
Naloga 17
Sestavi diagram poteka in program, ki poišče celo število
a, ki da pri deljenju s 5 ostanek 3 in pri deljenju s
7 ostanek 1.
Naloga 18
Dani sta pozitivni celi števili a in n.
Sestavi diagram poteka in program, ki izpiše vsa števila
1 ≤ i ≤ n, za katera velja i %a = i %
a˛.
Naloga 19
Sestavi diagram poteka in program, ki preveri, ali obstaja
celo število
x med 1 in 100 in celo število
y
med −100 in 100, ki zadošča enačbi
y10 + 2 y x2 + 951 = 0
Dodatno vprašanje: ali je 10010 več kot
največja vrednost tipa int
? Če je, kaj to pomeni za
tvojo rešitev?
Namig
Uporabi vgnezdeno zanko. Zunanja zanka šteje y
notranja pa x
(ali obratno).
Naloga 20
Sestavi diagram poteka in program, ki za dano pozitivno celo
število ugotovi, ali je praštevilo.