6. Silmukkarakenteet while / for

Kun ohjelman täytyy suorittaa samaa asiaa useampaan kertaan, voidaan käyttää toistorakennetta while tai for. Ohjelma toistaa silmukkaa aina silloin, kun toistamisen päättävä ehto ei ole tosi tai kunnes jokin ohjausrakenne (tai varattu sana) pysäyttää toiston suorittamisen. Toistojen määrä voi siten olla ääretön, yksi tai jotain siltä väliltä.

Toistoa voidaan tarvita esimerkiksi silloin, kun muuttujan arvoa täytyy kasvattaa tiettyyn rajaan asti (kuten esimerkin 5 Viive() -aliohjelmassa) tai vaikkapa 7-segmenttinäytön ohjauksessa.

while(silmukan ehto)

Pääohjelman toistosilmukka onkin jo edellä tullut tutuksi, mutta tarkastellaan while -silmukkaa vielä paremmin. Tätä silmukkaa käytetään yleensä silloin, kun toistoa pitää suorittaa kunnes jokin ehto täyttyy. Eli siis, silmukkarakenne while suorittaa lohkoaan niin kauan, kunnes sulkujen sisällä oleva ehto on epätosi. Näin ollen esimerkkien mukaista pääohjelman silmukkaa while(1) suoritetaan niin kauan kuin laite on päällä, koska 1 on tosi.

Silmukan ehtolausekkeen sisällä voisi olla myös jokin muu ehto. Kun ehto ei enää päde, ohjelman suoritus siirtyy seuraavaan suoritettavaan riviin joka lähdekoodista löytyy silmukan loppusulkeen jälkeen. Jos ehto vielä pätee, silmukka suoritetaan uudestaan. Näin ollen jokaisen silmukan alussa ehto tarkistetaan.

for(alkuarvot ; silmukan ehto ; mitä tehdään kun silmukka suoritetaan)

Otsikossa onkin kuvattu for() silmukan olennaisimmat parametrit. Tätä toistorakennetta käytetään yleensä silloin, kun toistojen määrä on etukäteen tiedetty (staattinen toistaminen). On myös mahdollista, että toistojen määrä muokkautuu for silmukan sisällä (dynaaminen toistaminen), esimerkiksi jonkun ehdon toteutuessa.

Esimerkki 1: while ja for peräkkäin

Alla olevassa esimerkkiohjelmassa on tehty kaksi toistorakennetta peräkkäin. Nämä suoritetaan ohjelman pääsilmukassa, sillä siitä ei ole edelleenkään syytä poistua. Kaksi erilaista toistoa tekevät erilaisia asioita Launchpadin punaiselle ja vihreälle ledille. Esimerkki perustuu edelliseen koodiin, joten sitä muokkaamalla saadaan ohjelma nopeasti kirjoitettua.

#include <msp430g2231.h>
// aliohjelmat täytyy esitellä koodissa 
void Viive(unsigned int aika); 
void PitkaViive(unsigned int aika); // eri aliohjelmilla voi olla samannimisiä parametrejä

void main(void)
{ 
     char vertailuLuku=0; // vertailuluku muuttuja silmukoita varten
     WDTCTL = WDTPW + WDTHOLD; // Pysäytetään vahtikoira 
     P1DIR |= BIT0 + BIT6; // asetetaan ledipinnit outputiksi 
     P1OUT &= ~(BIT6 + BIT0); // asetetaan ledipinnit nollaan ettei ledit pala           
     while(1) // pääohjelman pääsilmukka           
     { 
          // toistorakenne for missä asetetaan vertailuLuku aluksi nollaan, 
          // sitten verrataan onko luku pienempi kuin 10, 
          // jos ehto on tosi, kasvatetaan vertailuLuku muuttujaa 
          // ja suoritetaan silmukka, muutoin silmukasta poistutaan. 
          // Silmukka suoritetaan 10 kertaa, mutta LED vilkkuu viidesti 
          for(vertailuLuku = 0; vertailuLuku < 10; vertailuLuku++) 
          { 
               P1OUT ^= BIT0; 
               // ^ merkki on XOR operaatio, missä bitti 
               // asetetaan 0:aan jos se on 1 ja päinvastoin 
               // kutsutaan Viive -aliohjelmaa 
               Viive(30000); 
          } 
     // While rakenteessa verrataan onko luku suurempi kuin 4 
     // luku on tähän tullessa aina 10, joten 
     // silmukka suoritetaan 6 kertaa, mutta LED vilkkuu kolmesti 
     while(vertailuLuku > 4) 
     { 
          // kutsutaan pitkää viivettä: 2 * 50000 = 100 000 
          PitkaViive(2); 
          // käännetään bitti 
          P1OUT ^= BIT6; 
          // pienennetään arvoa 
          vertailuLuku--; 
     } 
     } // pääohjelman ikuisen silmukan loppusulku
}

// Aliohjelma Viive() joka kuluttaa CPU:n suoritusaikaa. Ns. tuhlaava rutiini. 
void Viive(unsigned int aika)
{
     unsigned int x=0;
     // luodaan uusi muuttuja
     // asetetaan x=0, vertaillaan onko x pienempi kuin aika muuttuja
     // jos ei ole niin kasvatetaan muuttujaa x yhdellä. 
     for(x=0;x<aika;x++)
     {
          // ei tehdä mitään
          // pyöritään vain silmukassa
     }
}
void PitkaViive(unsigned int aika)
{
     unsigned int x=0; // luodaan uusi muuttuja 
     for(x=0;x<aika;x++)
     {
          // kutsutaan Viive-aliohjelmaa, jolloin saadaan pitkä
          // viive aikaiseksi 
          Viive(50000);
     }
}

Kun käännät ja lataat ohjelman mikrokontrollerille, huomaat että koodi vilkuttaa ensin punaista lediä 5 kertaa, jonka jälkeen vihreä led vilkkuu kolmesti, mutta hieman hitaammin. Ohjelma on kommentoitu, mutta avataan toiminnallisuutta ja koodin pätkiä vielä tässäkin.

Kuten huomaat, ohjelmaan tuli yksi uusi funktio nimeltä PitkaViive lisää. C-kielessä muuttujien nimet ja funktioiden (aliohjelmien) nimet eivät saa sisältää ääkkösiä, joten ä on jätetty sanasta "pitkä" pois. Funktio PitkaViive eroaa Viive -funktiosta siten, että PitkaViive kutsuu sen for-silmukassa Viive -funktiota jolloin saadaan aikaiseksi entistä pidempi viive.

Ohjelman kulku

Pääohjelman alussa ei juuri ihmeitä tapahdu, ensin varataan muistista vertailuLukuniminen muuttuja, jota käsitellään silmukoissa. Sen jälkeen pysäytetään vahtikoira, alustetaan lähdöt ja sammutetaan ledit.

Pääohjelman silmukassa sammutetaan myös ledit, sillä ne ovat voineet jäädä päälle edellisellä suorituskerralla (ensimmäisellä kerralla ne ovat tietysti pois päältä).

Tultaessa ensimmäistä kertaa for -silmukkaan, suoritetaan alkuarvojen alustus eli vertailuLuku asetetaan nollaan. Tätä ei siis tehdä muilla suorituskerroilla. Silmukan sisällä tehdään punaista lediä ohjaavalle bitille XOR -operaatio, tällöin bitin arvo aina kääntyy ja saadaan "toggle" (kääntö) tehtyä. Eli bitti menee "1" -> "0" ja päinvastoin, kun koodirivi suoritetaan.

Silmukassa while suoritetaan ensin vertailuoperaatio vertailuLuku > 4, ja jos ehto ei ole totta, niin silmukan sisältö suoritetaan. Toisin sanoen, silmukkaa suoritetaan niin kauan, kunnes ehto täyttyy. Silmukan ensimmäisellä suoritettavalla rivillä kutsutaan uutta PitkaViive -funktiota, joka puolestaan kutsuu Viive-funktiota muodostaen edellisiä esimerkkejä verraten pidemmän viiveen. Seuraavaksi ohjelma tekee XOR-operaation vihreää lediä ohjaavalle bitille ja bitin kääntö "toggle" tapahtuu. Lopuksi pienennetään vertailuLuku -muuttujan arvoa, sillä muuten ohjelma jäisi while -silmukkaan eikä pääsisi takaisin pääsilmukkaan.

Nyt kun ohjelma on käyty läpi, voit kokeilla leikkiä sillä. Muuta vaikka viiveiden pituuksia ja ledivilkutuksien määrää. Aja koodia myös steppaamalla (F5/F6) jolloin saat paremman käsityksen kuinka ohjelma suorittaa koodia.