Kontrollirakenteet ja operaattorit

Samoin kuin Pythonissa myös C++:ssa on kontrollirakenteita valintaa ja toistoa varten. Tässä kohdassa vertaillaan ensin näiden kielten if- ja while-lauseita. Sen jälkeen esitellään yksi tapa käyttää C++:n for-silmukkaa. Lopuksi esittelemme lyhyesti C++:n operaattorit.

Python vs. C++: valinta ja silmukat (if- ja while-lauseet)

Vertaile seuraavien esimerkkiohjelmien avulla miten C++:n valinta- ja silmukkarakenteet eroavat Pythonin vastaavista rakenteista:

def main():
    salaluku = int(input("Syötä salainen luku: "))
    arvattu_luku = -1
    arvausten_määrä = 0

    while salaluku != arvattu_luku:
        arvattu_luku = int(input("Anna arvaus: "))

        arvausten_määrä += 1

        if arvattu_luku < salaluku:
            print("Arvaus on liian pieni!")
        elif arvattu_luku > salaluku:
            print("Arvaus on liian suuri!")
        else:
            print("Arvasit oikein!")

    print("Arvausten lukumäärä: ", arvausten_määrä)

main()
#include <iostream>

using namespace std;

int main() {
    int salaluku = 0;
    cout << "Syota salainen luku: ";
    cin >> salaluku;

    int arvattu_luku = -1;
    int arvausten_maara = 0;

    while ( salaluku != arvattu_luku ) {
        cout << "Anna arvaus: ";
        cin >> arvattu_luku;

        arvausten_maara += 1;

        if ( arvattu_luku < salaluku ) {
            cout << "Arvaus on liian pieni!" << endl;
        } else if (arvattu_luku > salaluku ) {
            cout << "Arvaus on liian suuri!" << endl;
        } else {
            cout << "Arvasit oikein!" << endl;
        }
    }

    cout << "Arvausten lukumaara: "
         << arvausten_maara << endl;
}

Huomaamme, että merkintätavallisia eroja (puolipisteet, sulut jne.) lukuunottamatta esimerkeissä ei ole radikaaleja eroavaisuuksia. Tästä voi hyvin huomata, mitä tarkoitetaan sillä, että ohjelmointi on kieliriippumaton taito. Esimerkiksi toisto on käsite, joka pysyy samanlaisena, riippumatta siitä, millä ohjelmointikielellä toistorakenne on toteutettu.

Sulkeiden käyttöön on kuitenkin syytä kiinnittää erityistä huomiota. C++:ssa lohkon ympärillä olevat aaltosulkeet voi jättää kirjoittamatta, jos lohkossa on vain yksi käsky. Esimerkiksi seuraavan ohjelmakoodin

int = 0;
while(i < 10)
{
    ++i;
}
cout << i << endl;

voi lyhentää muotoon

int = 0;
while(i < 10)
    ++i;
cout << i << endl;

Tämä saattaa ensin vaikuttaa näppärältä, mutta ennen kuin ottaa tällaisen lyhentämisen tavaksi, kannattaa huomata, että se voi johtaa vaikeasti jäljitettäviin ohjelmointivirheisiin. Kun Pythonia kirjoittaessaan on tottunut ajatukseen siitä, että sisennetty teksti on lohkon sisällä, voivat lohkoa ympäröivät sulkeet unohtua helposti. Sulkeiden unohtumisesta huolimatta seuraava koodipätkä menee kuitenkin läpi C++-kääntäjästä:

int = 0;
while(i < 10)
    ++i;
    cout << i << endl;
cout << "Hommat jatkuu silmukan jälkeen" << endl;

Nyt ensimmäistä tulostusta ei toisteta, koska se ei ole toistorakenteen lohkossa. Lohkosulkeiden puuttuessa lohkoon kuuluu vain yksi lause, joka tässä tapauksessa on ++i;. Ensimmäinen tulostus suoritetaan ainoastaan kerran: silloin kuin toisto päättyy ja suoritus jatkuu silmukan jälkeen seuraavasta käskystä.

C++-kääntäjä ei myöskään ole kovin tarkka siitä, kuinka ohjelma on jaettu riveille. Yleisesti on käytössä ainakin kaksi erilaista tapaa asemoida lohkosulkeet. Näistä toinen, pienempään rivimäärään johtava tapa, näyttää seuraavalta:

if( x ) {
    ...
}

Toinen tapa, jossa saman toistorakenteen alku- ja loppusulje ovat samassa sarakkeessa, näyttää tältä:

if( x )
{
    ...
}

Voit käyttää näistä kumpaa vain, mutta on hyvä olla johdonmukainen sen suhteen, että varsinkin kontrollirakenteiden kohdalla käytetään samaa tapaa ohjelman alusta loppuun.

Varoitus

Python-ohjelmissa olet saattanut käyttää poikkeusmekanismia (try-rakennetta) esimerkiksi ehtolauseen sijaan. Ellet aivan varmasti osaa, niin älä yritä käyttää C++:n poikkeusmekanismia tällä kurssilla. Sen käyttö opetetaan vasta seuraavalla ohjelmointikurssilla.

C++:n for-lause (yksi tapa)

C++:ssa on myös for-silmukka, jolle useita eri käyttötapoja. Se on erityisen kätevä tietorakenteiden alkioiden läpikäyntiin, joten nämä käyttötavat esitellään vasta sitten, kun osaamme käyttää C++:n tietorakenteita.

Jotta voisit käyttää for-silmukkaa jo tämän kierroksen tehtävissä, esittelemme tässä kuitenkin, miten sitä voidaan käyttää halutun kokonaislukuvälin arvojen läpikäyntiin:

for ( int luku = 5; luku < 10; ++luku ) {
    cout << 9 * luku << endl;
}

Tämä vastaa alla olevaa Python-rakennetta:

for luku in range(5, 10):
    print(9 * luku)

Silmukasta poistuminen

Silmukan suoritus lopetetaan, kun annettu ehto tulee epätodeksi. C++:ssa on muutama muukin tapa, jolla silmukan suoritusta voidaan säädellä. Lause

break;

lopettaa silmukan suorituksen ja siirtyy suorittamaan silmukan jälkeen tulevaa lausetta. Jos yllä oleva lause kirjoitetaan sisäkkäisistä silmukoista sisempään, lopetetaan vain sisemmän silmukan suoritus, mutta jatketaan ulomman silmukan suorittamista.

Lause

continue;

ohittaa silmukan sisällä olevat loput lauseet ja hyppää silmukan alkuun (olettaen että silmukan ehto on vielä voimassa).

Lause

return;

lopettaa koko funktion suorittamisen ja palaa kutsukohdan jälkeiseen koodiin. Jos siis yllä oleva lause kirjoitetaan silmukan sisään, myös silmukan suoritus lopetetaan. Huomaa, että lause voidaan yllä olevassa muodossa kirjoittaa myös void-funktioon. Jos taas funktiolla on paluuarvo, pitää myös palauttaa jokin arvo, eikä lausetta voi kirjoittaa pelkästään yllä olevaan muotoon. (Funktioista kerrotaan vähän jäljempänä lisää.)

C++:n operaattoreista

Edellä olevien esimerkkien ehdoissa (totuusarvoisissa lausekkeissa) nähtiin joitakin C++:n vertailuoperaatioita. Kaiken kaikkiaan C++:ssa on vertailuoperaattorit: ==, !=, <, <=, > ja >=, joiden merkitys on sama kuin Pythonin vastaavilla operaattoreilla. Pythonin tapaan C++:ssa on sijoitusoperaattorit: +=, -=, *= ja /=.

Esimerkeissä nähtiin myös C++:n inkrementointioperaattori ++. Esimerkiksi ++i kasvattaa muuttujan i arvoa yhdellä. Vastaavasti dekrementointioperaattori -- vähentää muuttujan arvoa yhdellä. Näitä operaattoreita kannattaa käyttää kuitenkin vain yksinään eikä yhdistellä niitä muiden operaattoreiden kanssa, sillä muuten tulokset saattavat yllättää.

C++:ssa on (tietenkin) myös normaalit aritmeettiset operaattorit yhteen-, vähennys-, kerto- ja jakolaskua varten. Operaattori % tarkoittaa (kokonaislukujen) jakojäännöstä. Kokonaislukujen tapauksessa operaattori / suorittaa kokonaislukujen jakolaskun, jolloin esimerkiksi 7 / 3 = 2 ja 1 / 5 = 0.

C++:ssa on seuraavat loogiset operaattorit:

  • looginen negaatio: not a, joka on sama kuin !a
  • looginen ja-operaattori: a and b, joka on sama kuin a && b
  • looginen tai-operaattori: a or b, joka on sama kuin a || b.

Kaksi viimeksi mainittua ovat niin sanottuja oikosulkuoperaattoreita, mikä tarkoittaa, että jälkimmäistä operandia ei evaluoida, mikäli koko lausekkeen arvo tiedetään ensimmäisen operandin perusteella. Esimerkiksi false and a on epätosi riippumatta a:n arvosta. Samoin true or a on tosi riippumatta a:n arvosta.

Lisäksi kahdella viimeksi mainitulla loogisella operaattorilla on biteittäiset vastineensa eli operaattorit & ja |. Nämä operaattorit vertailevat operandejaan biteittäin eli binaarilukuina bitti bitiltä. Bittioperaatio on myös ^, joka tarkoittaa loogista xor-operaatiota (exclusive or). Bittioperaatioilla ei ole käyttöä tällä kurssilla.

C++:ssa ei ole operaattoria potenssiin korotusta varten.