Valinnat ja päätökset



Samankaltaiset tiedostot
Ehto- ja toistolauseet

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Java-kielen perusteita

Java-kielen perusteet

Java-kielen perusteet

Ohjelmoinnin perusteet Y Python

Osoitin ja viittaus C++:ssa

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

Python-ohjelmointi Harjoitus 2

13. Loogiset operaatiot 13.1

Tietotyypit ja operaattorit

Osoittimet. Mikä on osoitin?

12. Javan toistorakenteet 12.1

12. Javan toistorakenteet 12.1

11. Javan toistorakenteet 11.1

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Ohjelman virheet ja poikkeusten käsittely

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Ohjausrakenteet. Valinta:

Ohjelmoinnin perusteet Y Python

Sisällys. 12. Javan toistorakenteet. Yleistä. Laskurimuuttujat

Kerta 2. Kerta 2 Kerta 3 Kerta 4 Kerta Toteuta Pythonilla seuraava ohjelma:

Kääntäjän virheilmoituksia

Ohjelmointi 1 Taulukot ja merkkijonot

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Ohjelmoinnin perusteet Y Python

Harjoitus 3 (viikko 39)

ITKP102 Ohjelmointi 1 (6 op)

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

Perusteet. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät Pasi Sarolahti

13. Loogiset operaatiot 13.1

7. Näytölle tulostaminen 7.1

ITKP102 Ohjelmointi 1 (6 op)

Ohjelmoinnin perusteet Y Python

Osa. Toimintojen toteuttaminen ohjelmissa vaatii usein haarautumisia ja silmukoita. Tässä luvussa tutustummekin seuraaviin asioihin:

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

11. Javan valintarakenteet 11.1

4. oppitunti. Ilmaukset ja ohjelmalauseet. Osa

Osa. Listaus 2.1. HELLO.CPP esittelee C++ -ohjelman osat. 14: #include <iostream.h> 15: 16: int main() 17: {

Zeon PDF Driver Trial

Johdatus Ohjelmointiin

Muuttujien roolit Kiintoarvo cin >> r;

Ohjelmoinnin peruskurssi Y1

12 Mallit (Templates)

Ohjelmoinnin perusteet Y Python

14. Hyvä ohjelmointitapa 14.1

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

ITKP102 Ohjelmointi 1 (6 op)

ITKP102 Ohjelmointi 1 (6 op)

Ohjelmoinnin peruskurssi Y1

Lauseet. Ehdollinen lause. Tämän osan sisältö. Ehdollinen lause. Esimerkkejä. Yksinkertainen ehto. Lohkosulut ja sisennys. Ehdollinen lause if

Ohjelmoinnin perusteet Y Python

Sisällys. 3. Muuttujat ja operaatiot. Muuttujat ja operaatiot. Muuttujat. Operaatiot. Imperatiivinen laskenta. Muuttujat. Esimerkkejä: Operaattorit.

Perustietotyypit ja laskutoimitukset

13. Hyvä ohjelmointitapa (osa 1) 13.1

Ohjelmoinnin perusteet Y Python

IDL - proseduurit. ATK tähtitieteessä. IDL - proseduurit

3. Muuttujat ja operaatiot 3.1

ATK tähtitieteessä. Osa 3 - IDL proseduurit ja rakenteet. 18. syyskuuta 2014

C-kielessä taulukko on joukko peräkkäisiä muistipaikkoja, jotka kaikki pystyvät tallettamaan samaa tyyppiä olevaa tietoa.

Virtuaalifunktiot ja polymorfismi

Ehto- ja toistolauseet

Ohjelmointiharjoituksia Arduino-ympäristössä

Ohjelmoinnin perusteet Y Python

C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. C-ohjelma. Operaatioiden suoritusjärjestys

Operaattoreiden uudelleenmäärittely

Harjoitus 2 (viikko 45)

Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

AS C-ohjelmoinnin peruskurssi 2013: C-kieli käytännössä ja erot Pythoniin

811120P Diskreetit rakenteet

Ohjelmoinnin perusteet Y Python

Tietojen syöttäminen ohjelmalle. Tietojen syöttäminen ohjelmalle Scanner-luokan avulla

System.out.printf("%d / %d = %.2f%n", ekaluku, tokaluku, osamaara);

Javan perusteet. Ohjelman tehtävät: tietojen syöttö, lukeminen prosessointi, halutun informaation tulostaminen tulostus tiedon varastointi

KAAVAT. Sisällysluettelo

Sisällys. 3. Pseudokoodi. Johdanto. Johdanto. Johdanto ja esimerkki. Pseudokoodi lauseina. Kommentointi ja sisentäminen.

Ohjelmassa muuttujalla on nimi ja arvo. Kääntäjä ja linkkeri varaavat muistilohkon, jonne muuttujan arvo talletetaan.

Tutoriaaliläsnäoloista

// Tulostetaan double-tyyppiseen muuttujaan "hinta" tallennettu // kertalipun hinta ja vaihdetaan riviä. System.out.printf("%.1f euros.

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Harjoitus 5. Esimerkki ohjelman toiminnasta: Lausekielinen ohjelmointi I Kesä 2018 Avoin yliopisto 1 / 5

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

1. Mikä on lukujen 10, 9, 8,..., 9, 10 summa? 2. Mikä on lukujen 10, 9, 8,..., 9, 10 tulo? =?

Harjoitus 5 (viikko 41)

Esimerkkiprojekti. Mallivastauksen löydät Wroxin www-sivuilta. Kenttä Tyyppi Max.pituus Rajoitukset/Kommentit

Merkkijono määritellään kuten muutkin taulukot, mutta tilaa on varattava yksi ylimääräinen paikka lopetusmerkille:

Luokat. Luokat ja olio-ohjelmointi

5/20: Algoritmirakenteita III

811120P Diskreetit rakenteet

Python-ohjelmointi Harjoitus 5

// Tulostetaan double-tyyppiseen muuttujaan "hinta" tallennettu // kertalipun hinta ja vaihdetaan riviä. System.out.printf("%.1f euros.

Luento 5. Timo Savola. 28. huhtikuuta 2006

Ohjelmoinnin peruskurssi Y1

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

Ohjelmoinnin perusteet Y Python

Metropolia ammattikorkeakoulu TI00AA : Ohjelmointi Kotitehtävät 3

\+jokin merkki tarkoittaa erikoismerkkiä; \n = uusi rivi.

Transkriptio:

Valinnat ja päätökset 4 Valinnat ja päätökset Päätöksenteko on erittäin tärkeässä asemassa kaikissa ohjelmointikielissä. Jos ohjelman lauseiden suoritusjärjestystä ei voitaisi muuttaa tietojen vertailun perusteella, useimpien ongelmien ratkaiseminen tietokoneohjelmilla olisi mahdotonta. Tässä luvussa käsittelemme, miten C++-ohjelmissa tehdään valintoja ja päätöksiä. Näin voit esimerkiksi tarkistaa ohjelmien syötteiden oikeellisuuden tai kirjoittaa ohjelmia, joiden suoritus riippuu syötetystä tiedosta. Ohjelmasi voivat käsitellä ongelmia, joissa loogiset valinnat ovat välttämättömiä. Luvun aiheita ovat: Miten tietoja vertaillaan Kuinka ohjelman lauseiden suoritusjärjestystä muutetaan vertailun tuloksen perusteella Mitä ovat loogiset operaattorit ja vertailulausekkeet ja kuinka niitä käytetään Miten käsitellään tilanteita, joissa on useita vaihtoehtoja Tiedon vertailu Jotta voimme tehdä päätöksiä, tarvitsemme tavan, jolla voimme vertailla asioita. Kaiken lisäksi olemassa on erityyppisiä vertailuja. Esimerkiksi päätös jos liikennevalo näyttää punaista, pysäytä auto, sisältää yhtäsuuruuden vertailun. Vertaamme liikennevalon näyttämää väriä vertailuväriin, punaiseen, ja jos ne ovat samat, pysäytämme auton. Toisaalta esimerkiksi päätös jos auton nopeus ylittää nopeusrajoituksen, hiljennä vauhtia, sisältää erityyppisen vertailun: vertailemme auton nopeutta voimassa olevaan nopeusrajoitukseen. Molemmat vertailut ovat samanlaisia siinä, että ne molemmat palauttavat toisen kahdesta arvosta: ne ovat joko tosia (true) tai epätosia (false). Vertailut tapahtuvat C++:ssa juuri tällä tavalla. Voimme vertailla arvoja vertailuoperaattoreilla. Käytössä on kuusi perusvertailuoperaattoria: < pienempi kuin <= pienempi tai yhtä suuri kuin > suurempi kuin >= suurempi tai yhtä suuri kuin == yhtäsuuruus!= erisuuruus 111

C++ Ohjelmoijan käsikirja! Tässä yhtäsuuruus -vertailuoperaattorissa on kaksi peräkkäistä yhtäsuuruusmerkkiä. Tämä ei ole sama kuin sijoitusoperaattori (=), jossa on vain yksi yhtäsuuruusmerkki. Varsin yleinen virhe on käyttää vain yhtä yhtäsuuruusmerkkiä kahden sijaan, kun vertaillaan yhtäsuuruutta. Kääntäjä ei yleensä anna tästä virheilmoitusta, joten sinun tulee olla erityisen tarkka. Kukin näistä binäärisistä operaattoreista vertailee kahta arvoa ja palauttaa arvon true, jos vertailu on tosi tai arvon false, jos vertailu on epätosi. Arvot true ja false ovat varattuja sanoja C++:ssa. Ne muodostavat myöskin uuden literaalivakion: booleanliteraalin (boolean algebran isän George Boolen mukaan). Sen tyyppi on bool. Jos muunnat arvon true integer-tyyppiseksi, tulos on 1 ja jos muunnat arvon false kokonaisluvuksi, tulos on 0. Voit myös muuntaa numeerisen arvon bool-tyyppiseksi; tällöin nolla on false ja nollasta poikkeava true. Kuten muidenkin perustietotyyppien kohdalla, voit luoda bool-tyyppisen muuttujan booleanarvon tallettamista varten. Esittelet tällaisen aivan samaan tapaan kuin muunkin muuttujan: bool paatos = true; //Esitellään, määritellään ja alustetaan //looginen muuttuja Tämä esittelee ja määrittelee muuttujan paatos boolean-tyyppiseksi ja alustaa siihen alkuarvon true. Vertailuoperaattoreiden käyttö Näemme muutaman yksinkertaisen esimerkin avulla, kuinka vertailuoperaattoreita käytetään. Oletetaan, että käytössämme on kaksi kokonaislukumuuttujaa i ja j, joiden arvot ovat 10 ja -5. Voimme käyttää niitä seuraavanlaisissa vertailulausekkeissa: i > j i!= j j > -8 i <= j + 15 Kaikkien näiden lausekkeiden arvo on true. Huomaa, että viimeisessä lausekkeessa, i <= j + 15, lisäysoperaatio j + 15 suoritetaan ensin, koska + on suoritusjärjestyksessä ennen operaattoria <=. Voit sijoittaa minkä tällaisen lausekkeen tahansa tuloksen bool-tyyppiseen muuttujaan. Esimerkiksi: char ensimmainen = A ; char viimeinen = Z ; Voimme nyt kirjoittaa joitakin esimerkkejä, jotka käyttävät näitä muuttujia. Tarkastellaan seuraavia: ensimmainen < viimeinen E <= ensimmainen ensimmainen!= viimeinen 112

Valinnat ja päätökset Ensimmäinen näistä lausekkeista tarkistaa, onko muuttujan ensimmainen arvo, joka on A, pienempi kuin muuttujan viimeinen arvo, joka on Z. Tämä on aina true. Voit tarkastaa tämän ASCII-merkkien kohdalla liitteestä A - isot kirjaimet ovat nousevassa järjestyksessä koodeissa 65-90; 65 kuvaa arvoa A ja 90 arvoa Z. Toisen lausekkeen arvo on false, koska E on suurempi kuin muuttujan ensimmainen arvo. Viimeinen lauseke on true, koska A ei todellakaan ole sama kuin Z. Voimme tulostaa bool-tyyppisiä arvoja aivan samaan tapaan kuin muitakin muuttujia, joten katsotaan esimerkin avulla, miltä ne näyttävät. Kokeile itse - Tietojen vertailu Tämä esimerkki lukee käyttäjältä kaksi char-tyyppistä arvoa, ja tulostaa niiden välisten vertailujen tulokset: // Esimerkki 4.1 - Tietojen vertailu #include <iostream> using namespace std; int main() char ensimmainen = 0; char toinen = 0; // Sisältää ensimmäisen merkin // Sisältää toisen merkin // Luetaan käyttäjältä ensimmäinen merkki cout << "Syötä merkki: "; cin >> ensimmainen; // Luetaan käyttäjältä toinen merkki cout << "Syötä toinen merkki: "; cin >> toinen; cout << "Lausekkeen ensimmainen < toinen arvo on: " << (ensimmainen < toinen) << endl << "Lausekkeen ensimmainen == toinen arvo on: " << (ensimmainen == toinen) return 0; Ohjelman tulostus voisi olla vaikka seuraavaa: Syötä merkki: p Syötä toinen merkki: t Lausekkeen ensimmainen < toinen arvo on: 1 Lausekkeen ensimmainen == toinen arvo on: 0 Kuinka se toimii Syötteen pyytäminen ja lukeminen käyttäjältä on jo tuttua. Tulostamme tuloksen käyttämällä < ja == -operaattoreita lauseessa: 113

C++ Ohjelmoijan käsikirja cout << "Lausekkeen ensimmainen < toinen arvo on: " << (ensimmainen < toinen) << endl << "Lausekkeen ensimmainen == toinen arvo on: " << (ensimmainen == toinen) Huomaa, että vertailulausekkeiden ympärillä olevat sulkeet ovat tässä välttämättömät, muutoin kääntäjä ei pysty tulkitsemaan lausetta oikein ja se antaa virheilmoituksen. Lausekkeet vertailevat syötettyjä ensimmäistä ja toista merkkiä. Yllä olevasta tulostuksesta voit nähdä, että arvo true tulostuu lukuna 1 ja arvo false lukuna 0. Jos haluamme tulostaa boolean-arvot sanoina true ja false, voimme käyttää muokkausfunktiota boolalpha. Lisää seuraava lause funktion main() alkuun: cout << boolalpha; Jos käännät ja suoritat esimerkin uudelleen, boolean-arvot tulostuvat sanoilla true ja false. Palataksesi takaisin oletusarvoihin, käytä noboolalpha-muokkausfunktiota. Liukulukuarvojen vertailu Voit luonnollisestikin vertailla myöskin liukulukuja. Tarkastellaan joitakin hieman monimutkaisempia vertailuja. Ensiksi määrittelemme muutaman muuttujan seuraavilla lauseilla: int i = -10; int j = 20; double x = 1.5; double y = -0.25E-10; Katsotaan nyt seuraavia vertailulausekkeita: -1 < y j < (10 - i) 2.0 * x >= (3 + y) Kuten huomaat, voimme käyttää numeerisen arvon palauttavia lausekkeita vertailun operandeina. Koska vertailuoperaattorit ovat kaikki suoritusjärjestyksessä laskuoperaattoreiden jälkeen (katso liite D), yksikään sulkeista ei ole välttämätön, mutta ne tekevät lausekkeesta selkeämmän. Ensimmäisen vertailun tulos on true, koska muuttujan y arvo on hyvin pieni negatiivinen arvo (- 0.000000000025), joka on suurempi kuin -1. Toinen lauseke palauttaa arvon false, koska lausekkeen 10 - i arvo on 20, joka on sama kuin muuttujan j arvo. Kolmas lauseke on true, koska 3 + y on hieman pienempi kuin 3. Voimme käyttää vertailuoperaattoreita kaikkien perustietotyyppien vertailuun, joten nyt tarvitsemme keinon, jolla voimme käyttää vertailun tulosta muuttamaan ohjelman suoritusta. Katsotaanpa tätä heti seuraavaksi. 114

Valinnat ja päätökset If-lause Yksiosaisen if-lauseen avulla ohjelmasi voi suorittaa yksittäisen lauseen tai aaltosulkeiden sisällä olevan lohkon, jos vertailun arvo on true. Tätä havainnollistaa viereinen kuva: If(vertailulauseke) Lause; Seuraava lause; Tai If(vertailulauseke) Lause;... Seuraava lause; Ei Vertailu on true Kyllä Lause tai lohko Seuraava lause If-lauseen perässä oleva lause tai lohko suoritetaan vain, jos vertailulausekkeen arvo. on true. Yksinkertainen esimerkki if-lauseesta on char-tyyppisen muuttujan kirjain arvo testaus: if(kirjain == A ) cout << Ensimmäinen aakkosnumeerinen merkki. cout << Tämä lause suoritetaan aina. Jos muuttujan kirjain arvo on A, vertailulausekkeen arvo on true ja lauseet tulostavat: Ensimmäinen aakkosnumeerinen merkki. Tämä lause suoritetaan aina. Jos muuttujan kirjain arvo ei ole A, vain toisen rivin tulostus suoritetaan. Testattava vertailulauseke on sulkeissa heti if-avainsanan perässä. Huomaa puolipisteen sijainti. Se sijoitetaan if-aivainsanaa ja sulkeissa olevaa vertailulauseketta seuraavan lauseen perään. Sulkeissa olevan vertailulausekkeen perässä ei tule olla puolipistettä, koska if ja vertailulauseke liittyvät niitä seuraavaan lauseeseen tai lohkoon. Ne eivät voi olla olemassa sellaisinaan. Huomaa myös, kuinka if-avainsanan perässä oleva lause on sisennetty merkiksi siitä, että se suoritetaan vain, jos vertailulausekkeen arvo on true. Sisennystä ei tarvita ohjelman kääntämistä varten, mutta se helpottaa tunnistamaan if-avainsanan ja siitä riippuvan lauseen. Joskus tällaiset yksinkertaiset if-lauseet kirjoitetaan yhdelle riville: if(kirjain == A ) cout << Ensimmäinen aakkosnumeerinen merkki. Mielestäni if-avainsanaan liittyvä lause tai lohko kannattaa aina kirjoittaa omalle rivilleen; se on selvempi sillä tavalla. 115

C++ Ohjelmoijan käsikirja Voimme laajentaa esimerkkiä siten, että se muuttaa muuttujan kirjain arvon, jos se sisältää kirjaimen A : if(kirjain == A ) cout << Ensimmäinen aakkosnumeerinen merkki. kirjain = a ; cout << Tämä lause suoritetaan aina. Lohkossa olevat lauseet suoritetaan vain, jos vertailulausekkeen arvo on true. Ilman aaltosulkeita ainoastaan ensimmäinen lause olisi liitettynä if-lauseeseen, ja muuttujaan kirjain arvon a sijoittava lause suoritettaisiin aina. Huomaa, että lohkon jokaisen lauseen perässä on puolipiste, mutta ei lohkon päättävän aaltosulkeen perässä. Lohkossa voi olla niin monta lausetta kuin haluat, tai jopa sisäkkäisiä lohkoja. Jos muuttuja kirjain sisältää arvon A, se muutetaan arvoksi a sen jälkeen, kun on tulostettu sama viesti kuin aikaisemmassakin esimerkissä. Kumpaakaan lausetta ei suoriteta, jos vertailulausekkeen arvo on false. if-lausetta seuraava lause suoritetaan tietysti aina. Kokeile itse - Päätöksen tekeminen Kokeillaan if-lausetta käytännössä. Voimme tehdä ohjelman, joka tarkistaa, kuuluuko syötetty kokonaisluku haluttuun arvoväliin: // Esimerkki 4.2 - if-lauseen käyttö #include <iostream> using namespace std; int main() cout << "Syötä kokonaisluku väliltä 50-100: "; int arvo = 0; cin >> arvo; if(arvo < 50) cout << "Arvo ei ole sallittu - se on pienempi kuin 50." if(arvo > 100) cout << "Arvo ei ole sallittu - se on suurempi kuin 100." cout << "Syötit luvun " << arvo return 0; Tulostus riippuu syötetystä arvosta. Jos arvo on välillä 50-100, tulostus näyttää seuraavalta: Syötä kokonaisluku väliltä 50-100: 77 Syötit luvun 77 116

Valinnat ja päätökset Jos arvo on välin 50-100 ulkopuolella, tulostuu viesti, joka kertoo, että syöte ei ollut halutulla arvovälillä. Jos arvo on alle 50, ohjelma tulostaa: Syötä kokonaisluku väliltä 50-100: 27 Arvo ei ole sallittu - se on pienempi kuin 50. Syötit luvun 27 Jos arvo on suurempi kuin 100, ohjelman tulostus on saman tyyppinen: Syötä kokonaisluku väliltä 50-100: 270 Arvo ei ole sallittu - se on suurempi kuin 100. Syötit luvun 270 Kuinka se toimii Arvon lukemisen jälkeen ensimmäinen if-lause tarkistaa, onko syötetty arvo alle alarajan 50: if(arvo < 50) cout << "Arvo ei ole sallittu - se on pienempi kuin 50." Tulostuslause suoritetaan vain, jos vertailulausekkeen arvo on true, eli silloin, kun muuttujan arvo arvo on pienempi kuin 50. Seuraava if-lause tarkistaa ylärajan: if(arvo > 100) cout << "Arvo ei ole sallittu - se on suurempi kuin 100." Tulostuslause suoritetaan, jos muuttujan arvo arvo on suurempi kuin 100. Viimeinen tulostuslause suoritetaan aina: cout << "Syötit luvun " << arvo Sisäkkäiset if-lauseet Lause, joka suoritetaan, kun if-lauseen vertailulauseke on true, voi olla myös if-lause. Tällaista lausetta kutsutaan sisäkkäiseksi if-lauseeksi. Sisemmän if-lauseen vertailulauseke testataan vain, jos ulomman if-lauseen vertailulausekkeen arvo on true. Sisempi if-lause voi edelleen sisältää if-lauseen. Voit sijoittaa if-lauseita toisen if-lauseen sisälle niin monta kuin haluat. Kokeile itse - Sisäkkäiset if-lauseet Voimme havainnollistaa sisäkkäisiä if-lauseita esimerkillä, joka testaa, onko näppäimistöltä syötetty merkki kirjain. Vaikka tämä esimerkki on aivan järkevä sisäkkäisten if-lauseiden käyttötilanne, siinä on joitakin oletuksia, joita tulee välttää; huomaatko ongelman? Seuraavassa on esimerkin koodi: // Esimerkki 4.3 - Sisäkkäiset if-lauseet #include <iostream> using namespace std; int main() char kirjain = 0; // Syötteen muuttuja 117

C++ Ohjelmoijan käsikirja cout << endl << "Syötä kirjain: "; // Pyydetään syöte cin >> kirjain; // sitten luetaan merkki cout if(kirjain >= 'A') if(kirjain <= 'Z') cout << "Syötit ison kirjaimen." return 0; if(kirjain >= 'a') if(kirjain <= 'z') cout << "Syötit pienen kirjaimen." << endl ; return 0; // Testataan onko 'A' tai suurempi // Testataan onko Z tai pienempi // Testataan onko 'a' tai suurempi // Testataan onko z tai pienempi cout << "Et syöttänyt kirjainta." return 0; Ohjelman tyypillinen tulostus on: Syötä kirjain: H Syötit ison kirjaimen. 118 Kuinka se toimii Ohjelman alussa on tavalliset kommenttirivit ja #include-esikäsittelijäkomento, joka sisällyttää tulostusta/syöttöä tukevan otsikkotiedoston iostream. Varattuaan muistia char-tyyppiselle muuttujalle kirjain ja alustettuaan sen alkuarvoksi nollan, funktio main() pyytää syöttämään kirjaimen. Syöttöä seuraava if-lause tarkistaa, oliko syötetty merkki A tai suurempi: if(kirjain >= 'A') // Testataan onko 'A' tai suurempi if(kirjain <= 'Z') // Testataan onko Z tai pienempi cout << "Syötit ison kirjaimen." return 0; Jos kirjain on suurempi tai yhtä suuri kuin A, suoritetaan sisempi if-lause, joka testaa, onko syöte Z tai pienempi. Jos se on Z tai pienempi, päättelemme, että kyseessä on iso kirjain ja tulostamme viestin. Olemme nyt suorittaneet tarvittavat toimenpiteet, joten suoritamme returnlauseen, joka lopettaa ohjelman suorituksen. Molemmat lauseet ovat aaltosulkeiden sisällä, joten ne molemmat suoritetaan, kun sisemmän if-lauseen vertailulauseke on true.

Valinnat ja päätökset Nämä kaksi sisäkkäistä if-lausetta on muodostettu perustuen kahteen oletukseen kirjainten koodeista. Ensimmäinen oletus on se, että kirjaimet A-Z esitetään koodeilla, joissa A :n koodi on minimi ja Z :n maksimi. Toinen oletus on, että isojen kirjainten koodit ovat peräkkäiset, eli muita kuin kirjainmerkkejä ei ole koodien A ja Z välissä. Ei ole järkevää rakentaa tällaisia oletuksia ohjelmiisi. Esimerkiksi EBCDIC-koodauksessa kirjainmerkkien koodit eivät ole peräkkäiset. Hetken päästä näemme, miten voimme välttää tämän rajoituksen. Seuraava if käyttää aivan samanlaista tapaa kuin ensimmäinenkin if-lause ja tarkastaa, onko syötetty merkki pieni kirjain, tulostaa viestin ja suorittaa return-lauseen. Jos tarkastelit ohjelmaa tarkasti, huomasit, että pienen kirjaimen testaavissa if-lauseissa on vain yhdet aaltosulkeet, kun taas ison merkin testaavassa oli kahdet. Molemmat ovat oikein: kuten muistat, C++:ssa if(vertailulauseke)... on itse asiassa yksi lause, joten sitä ei tarvitse sijoittaa aaltosulkeiden sisään. Voit kuitenkin käyttää toisiakin aaltosulkeita, jos se mielestäsi tekee koodista selkeämmän. Viimeisen if-lohkon perässä oleva tulostuslause suoritetaan vain, jos syötetty merkki ei ollut kirjain. Tämän jälkeen suoritetaan return-lause. Kuten huomaat, sisäkkäisten if-lauseiden suhteet ovat varsin selkeät, koska ne on sisennetty. C++:ssa käytetään yleensä sisennystä selventämään ohjelman logiikkaa. Kuten esimerkin alussa mainitsimme, ohjelma havainnollistaa vain, kuinka sisäkkäiset if-lauseet toimivat, mutta se ei ole hyvä tapa testata merkkejä. Standardikirjaston avulla voimme kirjoittaa ohjelman, joka toimii riippumatta merkkien koodauksesta. Katsotaan seuraavaksi, miten teemme tämän. Merkkien koodauksesta riippumaton merkkien käsittely Standardikirjasto sisältää suuren joukon funktioita, joita voit helposti käyttää ohjelmissasi testaamaan erilaisia asioita. Tarkastelemme omien funktioiden kirjoittamista vasta luvussa 8, mutta se ei estä käyttämästä olemassa olevia funktioita. Ennen kuin jatkamme, käsittelemme pikaisesti ideaa siitä, mitä tapahtuu funktioita käytettäessä. Funktio on nimetty, itsenäinen lohko koodia, joka suorittaa tietyn tehtävän. Usein se tarkoittaa sille välitettyjen tietojen käsittelyä ja käsittelyn tuloksen takaisin palauttamista ohjelmalle. Tällaisissa tapauksissa funktio toimii kuten edellisessä luvussa ollut sizeof()-operaattori: välitimme sille tietoa (muuttujan) ja se palautti tuloksen (tämän muuttujan koon). Funktion kutsu näyttää seuraavalta: FunktionNimi(parametri1, parametri2,... ) Riippuen kyseessä olevasta funktiosta, sille voidaan kutsuttaessa välittää ei yhtään, yksi tai useampia arvoja sijoittamalla ne sulkeisiin funktion nimen perään. Tällä tavalla funktiolle välitettyjä arvoja kutsutaan parametreiksi. Kuten kaikilla arvoilla C++:ssa, myös funktiolle välitettävillä parametreillä ja funktion palauttamalla arvolla on tyyppi, joka sinun tulee ottaa huomioon käyttäessäsi funktiota. Sisällyttämällä ohjelmaasi otsikkotiedoston cctype, saat käyttöösi erittäin käyttökelpoisen joukon funktioita, joilla voit testata merkkejä. Jokaisessa niistä välität funktiolle int-tyyppisen muuttujan tai literaalin. Jos välität char-tyyppisen, se muunnetaan automaattisesti int-tyyppiseksi. 119

C++ Ohjelmoijan käsikirja Funktio isupper() islower() isalpha() Toiminta Testaa, onko iso kirjain 'A' - 'Z'. Testaa, onko pieni kirjain 'a' - 'z'. Testaa, onko pieni tai iso kirjain. isdigit() Testaa, onko numero 0-9. isxdigit() isalnum() isspace() iscntrl() isprint() isgraph() ispunct() Testaa, onko heksadesimaalinen numero 0-9, 'a' - 'f' tai 'A' - 'F'. Testaa, onko kirjain tai numero (ts. aakkosnumeerinen merkki). Testaa, onko tyhjä merkki, joka voi olla välilyönti, uusi rivi, rivinvaihto, sivun vaihto, sarake- tai rivisarkain. Testaa, onko kontrollimerkki. Testaa, onko tulostettava merkki, eli iso tai pieni kirjain, numero, pistetyyppinen merkki (piste, pilkku jne) tai välilyönti. Testaa, onko graafinen merkki, eli mikä tahansa tulostettava merkki, mutta ei välilyönti. Testaa, onko pistetyyppinen merkki, eli mikä tahansa tulostettava merkki, mutta ei kirjain tai numero. Tällaisia ovat välilyönti ja seuraavat: _ [ ] # ( ) < > % : ;.? * + - / ^ & ~! =, \ " ' Jokainen näistä funktiosta palauttaa int-tyyppiset arvon. Paluuarvo on positiivinen (true), jos merkki oli testattavaa tyyppiä ja 0 (false), jos ei ollut. Saatat ihmetellä, miksi nämä funktiot eivät palauta bool-tyyppistä arvoa. Syynä on se, että nämä funktiot olivat osa standardikirjastoa jo ennen kuin bool-tyyppi lisättiin C++-kieleen. Otsikkotiedosto cctype sisältää myös kaksi funktiota merkkien muuntamiseen isoiksi ja pieniksi. Muunnettava merkki tulee välittää funktioille int-tyyppisenä: tolower() Jos välität ison kirjaimen, vastaava pieni kirjain palautetaan, muuten välittämäsi merkki palautetaan muuttamattomana. toupper() Jos välität pienen kirjaimen, vastaava iso kirjain palautetaan, muuten välittämäsi merkki palautetaan muuttamattomana. Kumpikin näistä funktioista palauttaa int-tyyppisen paluuarvon. Voimme toteuttaa näillä funktioilla edellisen esimerkkimme ilman olettamuksia merkkien koodauksesta. Eri ympäristöjen eri merkkikoodit otetaan aina huomioon standardikirjaston funktioissa, joten meidän ei tarvitse huolehtia niistä. Emme myöskään tarvitse sisäkkäisiä iflauseita, jos käytämme näitä standardikirjaston funktioita, eli koodi on selkeämpää. Kokeile itse - Standardikirjaston merkkimuunnokset 120 Kun kerran muutamme edellistä esimerkkiämme standardikirjaston funktioilla, voimme yhtä hyvin myös laajentaa ohjelmaa ja kokeilla muunnosfunktioita:

Valinnat ja päätökset // Esimerkki 4.4 - Standardikirj. merkkien testaus- ja muunnosfunktiot #include <iostream> #include <cctype> // Merkkien testaus ja muunnos using namespace std; int main() char kirjain = 0; // Syötteen muuttuja cout << endl << "Syötä kirjain: "; // Pyydetään syöte cin >> kirjain; // Sitten luetaan merkki cout if(isupper(kirjain)) // Testataan, onko iso kirjain cout << "Syötit ison kirjaimen." cout << "Muuntamalla pieneksi merkiksi saamme " << static_cast<char>(tolower(kirjain)) return 0; if(islower(kirjain)) // Testataan, onko pieni kirjain cout << "Syötit pienen kirjaimen." cout << "Muuntamalla isoksi merkiksi saamme " << static_cast<char>(toupper(kirjain)) return 0; cout << "Et syöttänyt kirjainta." return 0; Ohjelman tyypillinen tulostus on: Syötä kirjain: t Syötit pienen kirjaimen. Muuntamalla isoksi merkiksi saamme T Kuinka se toimii if-lauseet on muutettu käyttämään standardikirjaston funktioita. Emme enää tarvitse sisäkkäisiä if-lauseita, koska aikaisemmin testaamamme kaksi ehtoa on nyt korvattu yhdellä, joko funktiolla isupper() tai islower(). Meitä ei itse asiassa kiinnosta, miten nämä funktiot toimivat. Niitä käyttääksemme meidän tulee vain tietää, mitä ne tekevät, kuinka monta ja minkä tyyppisiä parametrejä niille tulee välittää ja minkä tyyppisen paluuarvon ne palauttavat. Kun meillä on tämä tieto, voimme yksinkertaistaa koodiamme ja tehdä siitä yleiskäyttöisempää. Tämä esimerkkiohjelma toimii riippumatta chartyypin käyttämästä merkkikoodauksesta. 121

C++ Ohjelmoijan käsikirja Huomaa, kuinka käytämme muunnosfunktion palauttamaa arvoa tulostuslauseessa - esimerkiksi: cout << "Muuntamalla isoksi merkiksi saamme " << static_cast<char>(toupper(kirjain)) Funktion toupper() palauttama arvo on int-tyyppinen, joten muunnamme sen eksplisiittisesti char-tyyppiseksi ja lähetämme tulostusvirtaan cout. Jos haluaisimme tallettaa palautetun merkin ja poistaa eksplisiittisen tyypinmuunnoksen, voisimme tallettaa sen takaisin alkuperäiseen muuttujaan kirjain: kirjain = toupper(kirjain); Nyt voisimme tulostaa muunnetun merkin käyttämällä tulostuslauseessa muuttujaa kirjain: cout << "Muuntamalla isoksi merkiksi saamme << kirjain Jos tarvitset wchar_t-tyyppisiä merkkejä, voit käyttää otsikkotiedostoa cwctype. Se sisältää versiot tämän tyyppisille merkeille kaikille samoille funktioille kuin on otsikkotiedostossa cctype. Kunkin funktion nimessä on w is -merkkien perässä: iswupper() iswdigit() iswspace() iswgraph() iswlower() iswxdigit() iswcntrl() iswpunct() iswalpha() iswalnum() iswprint() Näille kullekin tulee välittää wchar_t-tyyppinen merkki ja ne kaikki palauttavat int-tyyppisen arvon aivan samaan tapaan, kuin kaikki tyyppiä char käsittelevät funktiotkin. Vastaavasti wchar_t-tyyppiset muunnosfunktiot ovat towlower() ja towupper(). if- -lause Tähän saakka käyttämämme if-lause suorittaa lauseen, jos vertailulausekkeen arvo on true. Tämän jälkeen ohjelman suoritus jatkuu normaalisti. Saattaisi kuitenkin olla, että haluamme suorittaa tietyn lauseen tai lohkon, jos vertailulausekkeen arvo on false. Jotta voimme tehdä tämän, tarvitsemme lisäyksen if-lauseeseen: tietty toiminta suoritetaan, jos vertailulauseke on true ja toinen toiminta suoritetaan, jos vertailulauseke on false. Tämän jälkeen ohjelman suoritus jatkuu normaalisti. Käyttämällä char-tyyppisiä muuttujia, voimme kirjoittaa if- -lauseen, joka ilmoittaa, oliko merkki aakkosnumeerinen: if(isalnum(kirjain)) cout << Se on kirjain tai numero. cout << Se ei ole kirjain eikä numero. 122 Tässä käytetään otsikkotiedoston cctype funktiota isalnum(). Jos muuttuja kirjain sisältää kirjaimen tai numeron, funktio isalnum() palauttaa positiivisen kokonaisluvun. if-lause tulkitsee

Valinnat ja päätökset tämän arvoksi true, joten ensimmäinen viesti tulostetaan. Jos kirjain sisältää jotain muuta kuin kirjaimen tai numeron, isalnum() palauttaa arvon 0. Tämän if-lause tulkitsee arvoksi false ja -osan tulostuslause suoritetaan. Kokeile itse - if- Seuraavassa esimerkissä käytämme if- -lausetta. Käytetään tällä kertaa numeerisia arvoja: // Esimerkki 4.5 - if- #include <iostream> using namespace std; int main() long numero = 0; // Syötteen muuttuja cout << "Syötä kokonaisluku (pienempi kuin 2 miljardia: "; cin >> numero; cout if(numero % 2L == 0) // Testataan jakojäännös cout << "Numerosi on parillinen." // Jakojäännös on 0 cout << "Numerosi on pariton." // Jakojäännös on 1 return 0; Ohjelman tyypillinen tulostus näyttää seuraavalta: Syötä kokonaisluku (pienempi kuin 2 miljardia: 123456 Numerosi on parillinen. Kuinka se toimii Kun syöte on luettu muuttujaan numero, arvo testataan if-lauseessa ottamalla jakojäännös, kun numero jaetaan ensin kahdella (käyttämällä jakojäännös-operaattoria, jonka tapasimme luvussa 2) ja tarkistamalla onko se 0. Jaettaessa luvulla 2, jakojäännös voi olla vain 1 tai 0 kuten koodissa on kommentoitu. Jos jakojäännös on nolla, if-lauseen vertailulauseke on true ja ensimmäinen tulostuslause suoritetaan. Jos jakojäännös on 1, vertailulauseke on false ja -osan tulostuslause suoritetaan. Kummassakin tapauksessa return-lause päättää ohjelman suorituksen.! Huomaa, että -avainsana kirjoitetaan ilman puolipistettä, aivan kuten lauseen if-osakin. Sisennystä käytetään selventämään lauseiden välisiä suhteita. Näet selvästi, mitkä lauseet suoritetaan, jos vertailulauseke on true ja mitkä, jos se on false. Sinun tulisi aina sisentää ohjelmasi lauseet selventääksesi ohjelman rakennetta. 123

C++ Ohjelmoijan käsikirja Seuraavassa on toinen vaihtoehto vertailulausekkeen koodaamiselle. Palauta mieleen, että nollasta poikkeava arvo vastaa arvoa true, jos se muunnetaan bool-tyyppiseksi ja 0 vastaa arvoa false. Voimme näin käyttää jakojäännös-operaattoria suoraan vertailulausekkeena ilman, että sitä vertaillaan erikseen nollaan. if- -lause näyttäisi tällaiselta: if(numero % 2L) // Testataan jakojäännös cout << "Numerosi on pariton." // Jakojäännös on 1 cout << "Numerosi on parillinen." // Jakojäännös on 0 return 0; If- ja -osat tulee tässä vaihtaa keskenään, koska jos muuttujan numero arvo on parillinen, lauseke (numero % 2L == 0) palauttaa arvon true, mutta lauseke (numero % 2L) muunnetaan arvoksi false. Tämä saattaa aluksi tuntua hieman hämmentävältä, mutta muista, että ensimmäinen versio vastaa seuraavaa: Onko totta, että jakojäännös on 0? Kun taas toinen versio vastaa seuraavaa, koska arvo 1 muunnetaan arvoksi true: Onko jakojäännös 1? if- -lause mahdollistaa valinnan kahden eri vaihtoehdon väliltä. Lauseen rakenne havainnollistetaan seuraavassa kaaviossa: Ei Vertailulauseke on true? if( vertailulauseke ) // Lauseet, kun vertailulauseke on true // Lauseet, kun vertailulauseke on false // Seuraava lause Lause tai lohko falsetilanteessa Kyllä Lause tai lohko truetilanteessa Seuraava lause Toinen If- -lauseen lauseista suoritetaan aina. Vuokaavio kertoo lauseiden suoritusjärjestyksen, kun vertailulausekkeen arvo on true tai false. Kuten kaavio kertoo, ja kuten olemme jo aikaisemminkin nähneet, lauseen tilalle voidaan aina sijoittaa lohko. 124

Sisäkkäiset if- -lauseet Valinnat ja päätökset Olemme jo nähneet, että voit sijoittaa if-lauseita toisen if-lauseen sisälle. Ja koska sinulla ei ole mitään ennakkoluuloja, voit myös sijoittaa if- -lauseita if-lauseiden sisään, if-lauseita if -lauseiden sisään ja myöskin if- -lauseita toisten if- -lauseiden sisään. Tämä antaa meille runsaasti mahdollisuuksia (sekä myöskin vaaran sekaannuksille), joten katsotaan muutamia esimerkkejä. Tarkastellaan ensiksi esimerkkiä, jossa if-lauseen sisällä on if- -lause: if(kahvia == 'k') if(donitseja == 'k') cout << "Meillä on kahvia ja donitseja." cout << "Meillä on kahvia, mutta ei donitseja." Tässä kahvia ja donitseja ovat char-tyyppisiä muuttujia, joiden arvona voi olla k tai e. Donitsien testi suoritetaan vain, jos kahvien testauksen tulos on true, joten tulostettava viesti on oikea kummassakin tilanteessa. -osa kuuluu donitseja testaavaan if-lauseeseen. Tämä saattaa kuitenkin aiheuttaa sekaannusta. Jos kirjoitamme lähes samaan tapaan kuin edellä, mutta sisennämme väärin, voimme saada väärän kuvan lauseen toiminnasta: if(kahvia == 'k') if(donitseja == 'k') cout << "Meillä on kahvia ja donitseja." //Tämä -osa on sisennetty väärin cout << "Meillä ei ole kahvia..." //Väärin! Tässä virheellinen sisennys saa meidät ajattelemaan, että kyseessä on if-lause if- -lauseen sisällä. Näinhän ei tässä ole. Ensimmäinen viesti on oikein, mutta toinen on väärin. Tämä lause voidaan suorittaa vain, jos kahvin testaus on true, koska -osa kuuluu donitsien testaukseen, ei kahvin testaukseen. Tässä virhe on helppo nähdä, mutta monimutkaisempien ja laajempien ifrakenteiden kohdalla tulee muistaa sääntö siitä, mikä if omistaa minkäkin :n. kuuluu aina lähimmälle edellä olleelle if:lle, joka ei vielä omista -osaa. Tässä piilevä sekaannusvaara tunnetaan nimellä riippuvan :n ongelma. Aina kun joukko if- -lauseita näyttää ohjelmassasi hieman monimutkaiselta, voit käyttää tätä sääntöä tilanteen selvittämiseksi. Kun kirjoitat omia ohjelmiasi, voit aina käyttää aaltosulkeita selvennykseksi. Voimme kirjoittaa edellisen esimerkin uudelleen tällä tavalla (vaikka se ei näin yksinkertaisessa esimerkissä olekaan tarpeellista): if(kahvia == 'k') if(donitseja == 'k') cout << "Meillä on kahvia ja donitseja." 125

C++ Ohjelmoijan käsikirja cout << "Meillä on kahvia, mutta ei donitseja." Nyt tilanteen pitäisi olla varsin selvä. kuuluu ehdottomasti donitseja testaavaan iflauseeseen. Sisäkkäiset if-lauseet Nyt kun tiedämme säännöt, if- -lauseeseen sijoitetun if-lauseen ymmärtäminen on helpompaa: if(kahvia == 'k') if(donitseja == 'k') cout << "Meillä on kahvia ja donitseja." if(tee == k ) cout << "Meillä ei ole kahvia, mutta teetä on." 126 Huomaa koodin muotoilu tässä esimerkissä. Kun if-lause sijoitetaan -osaan, voimme kirjoittaa if yhdelle riville. Tätä tapaa käytetään tässä kirjassa. Tässä aaltosulkeet ovat välttämättömät. Jos jätämme ne pois, kuuluu donitseja testaavaan if-lauseeseen. Tämäntapaisessa tilanteessa on helppo unohtaa kirjoittaa ne ja saada aikaan virhetilanne, joka on vaikea löytää. Ohjelma, jossa tällainen virhe on, kääntyy normaalisti, koska koodi on aivan oikein. Ohjelma saattaa jopa toimia oikein tietyissä tilanteissa, mutta ei aina. Jos poistamme aaltosulkeet tästä esimerkistä, saamme oikeat tulokset niin kauan kuin molemmat sekä kahvia että donitseja ovat k. Eli tällöin if(tee == k ) -lausetta ei suoritettaisi koskaan. Lopuksi katsomme vielä if- -lauseeseen sijoitettua if- -lausetta. Tällainen saattaa muodostua varsin sekavaksi, vaikka kyseessä olisikin vain yksi sisäkkäinen if- -lause: if(kahvia == 'k') if(donitseja == 'k') cout << "Meillä on kahvia ja donitseja." cout << "Meillä on kahvia, mutta ei donitseja." if(tee == k ) cout << "Meillä ei ole kahvia, mutta teetä on ja ehkä donitseja..." cout << "Ei kahvia eikä teetä, mutta ehkä donitseja..."

Valinnat ja päätökset Tämän esimerkin logiikka ei ole aivan itsestään selvä, vaikka se onkin sisennetty oikein. Aaltosulkeet eivät ole välttämättömät, koska aikaisemmin mainittu sääntö on voimassa, mutta esimerkki näyttää selvemmältä, jos lisäämme ne: if(kahvia == 'k') if(donitseja == 'k') cout << "Meillä on kahvia ja donitseja." cout << "Meillä on kahvia, mutta ei donitseja." if(tee == k ) cout << "Ei ole kahvia, mutta teetä on ja ehkä donitseja..." cout << "Ei kahvia eikä teetä, mutta ehkä donitseja..." Tällaisen logiikan toteuttamiseen on paljon parempiakin tapoja. Jos sijoitat riittävän monta iflausetta sisäkkäin, teet lähes sataprosenttisen varmasti virheen jossakin kohtaa. Seuraavassa osassa on apuja tällaiseen tilanteeseen. Loogiset operaattorit Kuten olemme juuri huomanneet, kahden tai useamman if-lauseen sijoittaminen sisäkkäin on varsin kömpelöä. Käsittelimme edellä vain kahvin ja donitsien olemassaoloa, mutta käytännössä sinun tulee testata huomattavasti monimutkaisempiakin tilanteita. Voit esimerkiksi etsiä henkilöstötiedostosta henkilöä, joka on yli 21 vuotias, mutta alle 35, nainen, jolla on yliopistotutkinto ja joka on naimisissa ja puhuu hindiä ja urdua. Tällaisen testin toteuttaminen vaatisi jo kaikki maailman if-lauseet. C++:n loogiset operaattorit antavat siistin ja yksinkertaisen ratkaisun. Loogisten operaattoreiden avulla voimme yhdistää useita vertailuja yhteen lausekkeeseen, joten voimme käyttää vain yhtä if-lausetta lähes kuinka monimutkaisen tilanteen testaamiseksi. Niitä on vain kolme erilaista: && looginen AND (JA) looginen OR (TAI)! looginen NOT (EI) Kaksi ensimmäistä, && ja, ovat binäärisiä operaattoreita, joiden operandit ovat bool-tyyppisiä ja palauttavat bool-tyyppisen tuloksen. Kolmas operaattori,!, on unaarinen, joten sen ainut operandi on bool-tyyppinen ja palauttaa bool-tyyppisen tuloksen. Käsittelemme ensin miten kutakin näistä käytetään yleisellä tasolla. Tämän jälkeen katsomme esimerkkiä. On tärkeää, että erotat mielessäsi aikaisemmin näkemämme bittioperaattorit, jotka toimivat kokonaislukutyyppisten operandiensa biteillä, ja nämä loogiset operaattorit, joiden operandien tyyppinä on bool. 127

C++ Ohjelmoijan käsikirja Looginen AND AND-operaattoria && käytetään, kun on kaksi ehtoa, joiden tulee olla true, jotta tulos on true. Haluat olla esimerkiksi rikas ja terve. Kun käytimme aikaisemmin sisäkkäisiä if-lauseita tarkistamaan, oliko merkki iso merkki, testattavan arvon tuli olla sekä suurempi tai yhtä suuri kuin A ja pienempi tai yhtä suuri kuin Z. Molempien ehtojen tulee olla true, jos kyseessä on iso kirjain. Muutoin tulos on false. Voimme näyttää tämän pienessä taulukossa, jossa ylärivillä ja vasemmassa reunassa ovat operandit: Operandit true false true true false false false false Esimerkissämme, jossa oli char-tyyppinen muuttuja kirjain, voimme korvata kahden iflauseen käytön yhdellä if-lauseella, jossa käytetään &&-operaattoria. if(kirjain >= A && kirjain <= Z ) cout << Iso kirjain. Tulostuslause suoritetaan vain, jos molemmat &&-operaattorilla yhdistetyt ehdot ovat true. Lausekkeessa ei tarvita sulkeita, koska vertailuoperaattorit ovat suoritusjärjestyksessä ennen &&- operaattoria. Voit kuitenkin lisätä sulkeet, jos haluat. Voit siis kirjoittaa lauseen seuraavasti: if((kirjain >= A ) && (kirjain <= Z )) cout << Iso kirjain. Nyt ei ole epäilystäkään, etteikö sulkeiden sisällä olevia vertailulausekkeita suoritettaisi ensin. Looginen OR OR-operaattoria käytetään, kun on kaksi ehtoa ja tuloksen halutaan olevan true, kun toinen tai molemmat niistä ovat true. -operaattorin tulos on false vain silloin, kun molemmat sen operandit ovat false. Kaikki muut kombinaatiot muodostavat tuloksen true. Tämä näkyy seuraavasta taulukosta: Operandit true false true true true false true false 128 Esimerkiksi sinut voidaan luokitella luottokelpoiseksi hakiessasi lainaa pankista, jos tulosi ovat vähintään 100 000 mk tai sinulla on käteistä 1 000 000 mk. Tämä voidaan testata seuraavalla if-lauseella:

Valinnat ja päätökset if(tulot >= 100000.00 kateinen >= 1000000.00) cout << "Totta kai, kuinka paljon tarvitset?" Viesti tulostetaan, kun toinen tai molemmat ehdot ovat true. (Parempi vastaus saattaisi olla Miksi haluat lainata rahaa? On outoa, että pankit lainaavat rahaa vain silloin, kun et sitä tarvitse.) Looginen NOT Kolmannella operaattorilla,!, on yksi true tai false -arvoinen operandi, jonka arvon se kääntää. Eli jos boolean-tyyppisen muuttujan testi arvo on true,!testi on false; jos testi on false,!testi on true. Esimerkiksi, jos muuttujan x arvo on 10, niin lausekkeen!(x > 5) arvo on false, koska x > 5 on true. Voimme käyttää!-operaattoria myöskin lausekkeessa, joka oli Charles Dickensin suosikki:!(tulot > menot) Jos tämä lauseke on true, tuloksena on kurjuus - ainakin sitten, kun pankki peruu luottokorttisi. Kaikkia loogisia operaattoreita voidaan käyttää lausekkeissa, joiden arvo on true tai false. Operandit voivat olla yksittäisestä bool-tyyppisestä muuttujasta monimutkaiseen vertailujen ja loogisten operaattoreiden yhdistelmään. Kokeile itse - Loogisten operaattoreiden yhdistäminen Voit yhdistää ehtolausekkeita ja loogisia operaattoreita aivan kuten haluat. Voimme esimerkiksi tehdä ohjelman, joka päättää, oletko lainakelpoinen: // Esimerkki 4.6 - Loogisten operaattoreiden yhdistäminen #include <iostream> using namespace std; int main() int ika = 0; long tulot = 0; long saldo = 0; // Lainanhakijan ikä // Lainanhakijan tulot // Nykyinen pankkitilin saldo // Luetaan perustiedot cout << endl << "Syötä ikäsi vuosissa: "; cin >> ika; cout << "Syötä vuositulosi markoissa: "; cin >> tulot; 129

C++ Ohjelmoijan käsikirja cout << "Mikä on nykyinen pankkitilisi saldo markoissa: "; cin >> saldo; cout // Lainaamme vain yli 21 vuotiaille henkilöille, joiden // vuositulot ovat yli 50 000 mk tai joilla on pankkitilillä // yli 100 000 mk, tai molemmat. if(ika >= 21 && (tulot > 50000 saldo > 100000)) // OK, saat lainaa - mutta kuinka paljon? // Pienempi kahdesta: 2 * tulot tai puolet tilin saldosta long laina = 0; if(2 * tulot < saldo / 2) laina = 2 * tulot; laina = saldo / 2; // Lainan maksimimäärä cout << "Voit lainata maksimissaan " << laina cout << "Valitamme, et ole lainakelpoinen." return 0; Esimerkin tulostus voi olla seuraavanlainen: Syötä ikäsi vuosissa: 25 Syötä vuositulosi markoissa: 52000 Mikä on nykyinen pankkitilisi saldo markoissa: 185000 Voit lainata maksimissaan 92500 Kuinka se toimii Määrittelemme ensin kolme muuttujaa, joihin talletamme ohjelman tarvitsemat syötteet: int ika = 0; // Lainanhakijan ikä long tulot = 0; // Lainanhakijan tulot long saldo = 0; // Nykyinen pankkitilin saldo Tämän jälkeen luemme arvot, joiden avulla määrittelemme lainakelpoisuuden: cout << endl << "Syötä ikäsi vuosissa: "; cin >> ika; cout << "Syötä vuositulosi markoissa: "; cin >> tulot; 130 cout << "Mikä on nykyinen pankkitilisi saldo markoissa: "; cin >> saldo;