6. while-silmukka

while-silmukka

while-silmukka toistaa tiettyä koodia niin kauan, kuin haluttu ehto pitää paikkansa.

Silmukan rakenne on seuraava:

while ([ehto]) {
    [koodi]
}

Esimerkki

Seuraava ohjelma tulostaa luvut väliltä 1–10 while-silmukan avulla:

int luku = 1;
while (luku <= 10) {
    System.out.println(luku);
    luku = luku + 1;
}

Ohjelman tulostus on seuraava:

1
2
3
4
5
6
7
8
9
10

Tässä muuttuja luku on aluksi 1. Silmukan jokaisella kierroksella ohjelma tulostaa muuttujan luku ja kasvattaa sen arvoa yhdellä. Silmukka jatkuu niin kauan, kuin muuttujan luku arvo on korkeintaan 10.

Totuusarvot

Nyt on tullut aika esitellä uusi Javan tietotyyppi. Totuusarvo on tyyppi, jolla on vain kaksi mahdollista arvoa: true (tosi) ja false (epätosi).

Totuusarvoja on jo käytetty paljon, vaikka niitä ei ole mainittu nimeltä. Kaikki ehdot if-rakenteessa ja silmukoissa ovat nimittäin totuusarvoja.

Totuusarvotyypin tunnus on boolean. Totuusarvoja voi käsitellä samaan tapaan kuin merkkijonoja ja lukuja, kuten seuraava ohjelma havainnollistaa:

boolean salasanaOikein = salasana.equals("kissa");
if (salasanaOikein) {
    System.out.println("Salasana on oikein!");
}

Tässä muuttuja salasanaOikein saa arvon true, jos salasana on kissa, ja muuten arvon false. Tämän jälkeen if-rakenteen sisällä oleva koodi suoritetaan, jos ehdon totuusarvo on true eli muuttujan arvo on true.

Tällä hetkellä saattaa tuntua vaikealta keksiä käyttöä totuusarvomuuttujalle, koska esimerkiksi yllä olevan koodin voisi kirjoittaa lyhyemmin ilman muuttujaa. Myöhemmin kuitenkin huomaamme, että totuusarvomuuttuja voi olla varsin hyödyllinen.

Ikuinen silmukka

Ikuinen silmukka on silmukka, jonka toistamista ei ole rajoitettu. Javassa ikuinen silmukka voidaan luoda seuraavasti:

while (true) {
    [koodi]
}

Tämä silmukka jatkuu niin kauan, kuin ehto true on tosi – mutta tämä ehto on aina tosi. Ongelmaksi näyttää siis tulevan, että silmukka ei pääty milloinkaan.

Silmukan lopettamiseen on kuitenkin myös toinen tapa: komento break. Tämä komento silmukan sisällä lopettaa silmukan välittömästi riippumatta silmukan ehdosta.

Tyypillinen ikuinen silmukka näyttää seuraavalta:

while (true) {
    ...
    if ([ehto]) {
        break;
    }
    ...
}

Seuraavat esimerkit näyttävät, mitä hyötyä ikuisesta silmukasta voi olla.

Esimerkki: Salasana

Seuraava ohjelma kysyy käyttäjältä salasanaa, kunnes käyttäjä antaa oikean salasanan.

while (true) {
    System.out.print("Anna salasana: ");
    String salasana = input.nextLine();
    if (salasana.equals("kissa")) {
        break;
    }
    System.out.println("Väärin meni!");
}
System.out.println("Tervetuloa!");

Ohjelman suoritus voi olla seuraava:

Anna salasana: koira
Väärin meni!
Anna salasana: lehmä
Väärin meni!
Anna salasana: kissa
Tervetuloa!

Esimerkki: Iän kysyminen

Seuraava ohjelma kysyy käyttäjältä ikää, kunnes käyttäjä antaa kelvollisen iän:

while (true) {
    System.out.print("Kuinka vanha olet? ");
    int ika = Integer.parseInt(input.nextLine());
    if (ika >= 0 && ika <= 120) {
        break;
    }
    System.out.println("Ikä ei kelpaa!");
}
System.out.println("Kiitos!");

Ohjelman suoritus voi olla seuraava:

Kuinka vanha olet? -5
Ikä ei kelpaa!
Kuinka vanha olet? 139
Ikä ei kelpaa!
Kuinka vanha olet? 56
Kiitos!

Tässä silmukan lopettamisen ehtona on, että ikä on välillä 0–120.

Silmukan muodostaminen

Silmukan muodostamiseen on yleensäkin kaksi eri tapaa:

Seuraavat koodit havainnollistavat asiaa:

ehto rungossakäytössä break
String salasana = "";
while (!salasana.equals("kissa")) {
    System.out.print("Anna salasana: ");
    salasana = input.nextLine();
}
while (true) {
    System.out.print("Anna salasana: ");
    String salasana = input.nextLine();
    if (salasana.equals("kissa")) {
        break;
    }
}

Molemmat koodit toimivat, ja on makuasia, kumpaa haluaa käyttää. Koodien ajattelutapa on kuitenkin erilainen: vasemmassa koodissa ajatellaan "silmukka jatkuu niin kauan, kuin salasana ei ole kissa" kun taas oikeassa koodissa ajatellaan "silmukka jatkuu, kunnes salasana on kissa".

Muuttujien näkyvyys

Seuraava asia on hyvä tiedostaa: Jos muuttujan määrittelee silmukan sisällä, sen alkuarvo palautetaan silmukan jokaisella kierroksella eikä muuttujaa voi käyttää muualla kuin silmukan sisällä.

Esimerkiksi seuraava koodi ei toimi:

while (summa < 100) {
    int summa = 0;    
    summa = summa + 1;
}

Nyt muuttuja summa nollautuu silmukan joka kierroksella eikä siihen voi edes viitata silmukan ehdossa.

for vai while?

Mistä tietää, kannattaako toistaminen tehdä for-silmukan vai while-silmukan avulla?

Perussääntö on, että jos toistokertojen määrä on tiedossa ennen silmukan aloittamista (esim. koodi toistetaan 5 kertaa), for-silmukka on luonteva valinta, ja muussa tapauksessa while-silmukka sopii ehkä paremmin.

Kuitenkin kummalla tahansa silmukalla voi toteuttaa minkä tahansa toistorakenteen. Niinpä toinen silmukka on tavallaan "turha". Molemmat silmukat ovat Javassa, koska molemmille on luontevia käyttötilanteita.

Hauska lisätehtävä: Mieti, miten voit korvata for-silmukan while-silmukalla ja päinvastoin.