ti02 ohjelmointiti02 ohjelmointi 17. toukokuuta 2011 1 hello, world! aloitetaan opiskelu...

41
TI02 Ohjelmointi Kurssimoniste

Upload: others

Post on 06-Aug-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 OhjelmointiKurssimoniste

Page 2: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

Johdanto ja merkinnöistä

Tämän monisteen tarkoituksena on antaa riittävät perustiedot C++-ohjelmoinnin opiskelun aloittamiseen. Käsitelläänyksinkertaisia ohjelmia ja kiinnitetään erityistä huomiota loogiseen ajatteluun ongelmanratkaisussa. Esitettävät ohjelmaton käännetty Windowsin C++ kääntäjällä, mutta ainakin teoriassa niiden pitäisi kääntyä myös Linuxilla yms. muillakäyttöjärjestelmillä.

Moniste seuraa erittäin tarkasti Bjarne Stroustrupin kirjaa

Programming: Principles and Practice Using C++ (Addison-Wesley 2008)

Kurssin tavoitteena on käydä soveltuvin osin läpi kirjan luvut 1–5, mutta jos opiskelijoilla on intoa, niin luku 6 sisäl-tää mahdollisen lisäprojektin. Jokainen tämän monisteen luku sisältää yhden luvun Stroustrupin kirjasta tiivistettynä,alkaen kirjan luvusta 2. Monisteen luvut on nimetty kirjasta hieman poikkeavalla tavalla, sisältäen kuitenkin lähes kaikkitärkeimmät asiat.

Teksti on kirjoitettu LATEX 2ε ladontakielellä. Mikäli mielenkiintoa on, voi ohjelmiston ja peruskäytöstä kysellä allekir-joittaneelta lisää. LATEX -koodia kääntävä ohjelma Windows-koneilla on MikTeX, jonka voi ladata netistä ilmaiseksi.Sopiva editori tekstin kirjoittamiseen on TexnicCenter.

Virolahdella 17. toukokuuta 2011,

Riku Järvinen

Page 3: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

Sisältö

1 Hello, World! 1

1.1 Ensimmäinen ohjelma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Funktio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.3 Koodin kääntäminen ja linkittäminen ohjelmaksi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.4 C++:n standardikirjasto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.5 Virhetyypit sekä ohjelmointi käytännössä . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.6 Vinkkejä: komentorivin käyttö . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

1.7 Kysymyksiä luvusta 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.8 Tehtäviä luvusta 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2 Objektit, tyypit ja arvot 5

2.1 Käyttäjän syötteen lukeminen ja ruudulle tulostaminen . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2.2 Objektit ja tyypit: johdantoa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2.2.1 Esimerkki: Käyttäjän ikä ja nimi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2.3 Operaattorit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.3.1 Esimerkki: Operaattoriharjoitus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.4 Nimet C++:ssa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.4.1 Esimerkki: virheilmoitukset nimissä . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.5 Alkuarvon asettaminen ja sijoittaminen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

2.5.1 Esimerkki: nimiharjoitus 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

2.5.2 Esimerkki: nimiharjoitus 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

2.6 Yhdistelmäoperaattorit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.7 Tyypit ja niiden varaama tila muistissa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

2.8 Tyyppimuunnokset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

2.8.1 Esimerkki: tyyppimuunnokset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

2.9 Kysymyksiä luvusta 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

2.10 Tehtäviä luvusta 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3 Laskentaa 20

3.1 Laskennan perusteet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.2 Ohjelmoinnin yleiset tavoitteet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.3 Ilmaisut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

3.4 Lausekkeet, ehtolauseet ja toistorakenteet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

3.4.1 Ehtolauseet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

i

Page 4: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

3.4.2 Esimerkki: Valuutan muuntaminen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

3.4.3 Esimerkki: valuutan muuntaminen, osa 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

3.4.4 Toistorakenteet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

3.4.5 Esimerkki: aakkosten tulostus ruudulle, osa 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

3.4.6 Esimerkki: aakkosten tulostus ruudulle, osa 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

3.5 Funktiot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

3.6 Vektorit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

3.6.1 Esimerkki: Lämpötilojen mediaanin laskeminen . . . . . . . . . . . . . . . . . . . . . . . . . . 29

3.6.2 Esimerkki: Epämukavien sanojen sensurointi . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

3.7 Esimerkkejä lauserakenteista ja vektoreista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

3.7.1 Esimerkki: Matkan pituuden laskeminen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3.7.2 Esimerkki: Yksinkertainen laskinohjelma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

3.7.3 Esimerkki: lukujen arvaaja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

3.8 Kysymyksiä luvusta 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

3.9 Tehtäviä luvusta 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

4 Bjarne Stroustrupin ajatuksia liittyen ohjelmointiin 37

ii

Page 5: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

1 Hello, World!

Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville tekstin Hello World!

1.1 Ensimmäinen ohjelma

helloworld.cpp

1 / / Ohjelma t u l o s t a a r u u d u l l e t e k s t i n H e l l o World !2

3 #include "../std_lib_facilities.h"

4

5 int main ( )6 {7 cout << "Hello World!\n" ;8 keep_window_open ( ) ;9 return 0 ;

10 }

Käydään koodi läpi rivi riviltä.

1. Merkintä // aloittaa yhden rivin kommentin. Yleensä ohjelman alussa halutaan kertoa, mitä ohjelman olisi tarkoi-tus tehdä (ei tarkkaa selostusta, vain perusidea).

3. Omaan koodiin yhdistetään #include-direktiivillä C++:n standardikirjaston tiedot. Standardikirjastossa on mää-ritetty mm. riviltä 7 löytyvät funktio cout, joka tulostaa tekstiä ruudulle. Merkintä ../ tarkoittaa, että haettu tie-dosto std_lib_facilities.h on yhtä hakemistotasoa ylempänä kuin tiedosto helloworld.cpp. Tiedos-topääte .h puolestaan tarkoittaa ns. header-tiedostoa ja .cpp itse kirjoitettua muokattavaa lähdekooditiedostoa.

5. int main aloittaa varsinaisen ohjelman suorittamisen. Tavalliset sulut () jätetään tyhjiksi. Varsinainen ohjel-makoodi tulee aaltosulkujen {...} sisään eli funktiorunkoon.

6. Aaltosulku aloittaa funktiorungon ja on tavallisesti omalla rivillään tai edellisen rivin lopussa.

7. Standardikirjaston funktio cout ja output-operaattori << tulostavat komentoriville. Tavallinen, kirjoitettavateksti on lainausmerkkien sisällä (tulostetaan juuri sellaisena kuin on, myös tyhjät välit) ja riviä vaihdetaan kir-joittamalla \n lainausmerkkien sisään. Lauseke

cout << "Hello, World!\n" ;

päättyy puolipisteeseen, kuten kaikki lausekkeet C++:ssa.

8. Funktio keep_window_open() pitää ohjelmaikkunan auki: kätevä, sillä muuten ikkuna sulkeutuisi välittömästiohjelman ajamisen jälkeen.

9. Lauseke return 0; ei varsinaisesti tee mitään, vaan ainoastaan esittelee sitä että funktio voi palauttaa jonkinarvon tarvittaessa (vain yhden arvon). Arvoa 0 käytetään joskus tarkistamaan, että ohjelma on tehnyt sen, mitäpitääkin (Linux/Unix-järjestelmissä).

10. Aaltosulku lopettaa main-funktion eli koko ohjelman suorittamisen.

1

Page 6: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

1.2 Funktio

C++:n funktio on määritelty aivan kuten matematiikassa, eli sille voidaan antaa yksi tai useampi argumentti ja se pa-lauttaa täsmälleen yhden arvon. Funktiolla on aina nimi, palautusarvon tyyppi, parametrilista (argumentit) ja funktionrunko, joka sisältää varsinaisen toiminnallisuuden. Funktioilla voidaan automatisoida usein toistuvia toimia, jotka muu-ten vaatisivat pitkän saman koodin kirjoittamista joka kerta erikseen. Funktioiden käyttö selventää koodia loogisesti, sillärutiinitoiminnot on kuitattu useimmiten vain yhdellä rivillä.

1.3 Koodin kääntäminen ja linkittäminen ohjelmaksi

Kirjoitettava koodi eli lähdekoodi pitää muuttaa eli kääntää tietokoneen ymmärtämään muotoon konekielelle (machinecode tai object code). Työn tekee kääntäjäohjelma (compiler), joka

• lukee lähdekoodin // ilman siinä olevia kommentteja

• tarkastaa kieliopin oikeellisuuden

• ilmoittaa virheestä. Jos virhe löytyy, niin käännöstyötä ei tehdä. Tällöin lähdekoodin virhe tulee korjata ja kääntääkoodi uudelleen. Tavallisimpia virheitä ovat mm. lainausmerkin, sulkumerkin tms. puuttuminen, sanojen unohta-minen, väärien muuttujien nimien käyttö, väärien operaattorien käyttö ja puolipisteen puuttuminen suoritettavanlauseen lopusta.

Lyhyesti:

Kääntäjä on yleensä aina oikeassa, ihmiset väärässä.

Kääntäjä on ohjelmoijan paras ystävä koodatessa. Kokemuksen kautta oppii, että ilman kääntäjää menisi erittäin paljonturhaa aikaa yksinkertaisten kirjoitusvirheiden korjaamiseen.

C++ ohjelma koostuu tavallisesti useasta eri osasta. helloworld.cpp käyttää omaa lähdekoodiaan ja lisäksi C++:nstandardikirjaston osia. Itse kirjoitettu ja kääntäjällä käännetty lähdekoodi linkitetään standardikirjaston lähdekoodiin, jalinkitys yhdistää nämä koodit suoritettavaksi tiedostoksi (.exe-tiedosto). Lähdekoodista saadaan .exe-tiedosto kirjoitta-malla komentoriville

g++ helloworld.cpp -o helloworld.exe

Käännöstyön suorittaa ohjelma nimeltä g++, joka on osa GCC:tä (GNU Compiler Collection). Argumentit kannattaakirjoittaa oikeassa järjestyksessä, sillä esimerkiksi komento

g++ -o tiedosto.cpp ohjelma.exe

tuhoaa alkuperäisen lähdekooditiedoston pysyvästi eikä käännä ohjelmaa. Sinua on varoitettu. . .

HUOMIO. Konekielinen koodi ja suoritettava ohjelma eivät ole alustariippumattomia, eli Windowsillakäännetty ja linkitetty ohjelma ei toimi GNU/Linux-koneella.

2

Page 7: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

1.4 C++:n standardikirjasto

Linkkeri yhdistää oman lähdekoodin ja standardikirjaston koodin yhdeksi toimivaksi ohjelmaksi. Standardikirjasto si-sältää yksinkertaisesti koodia, jossa määritellään kielen peruskomponentteja, mm. ruudulle tulostaminen ja käyttäjänsyötteen lukeminen sekä tiedon tallennukseen liittyviä seikkoja. Standardikirjastokoodin voi ladata esimerkiksi BjarneStroustrupin henkilökohtaiselta sivulta

http://www.stroustrup.com/

Tämä versio voi olla vanhentunut, mutta on tehty nimenomaan kurssikirjaa varten joten toimii riittävän hyvin sen kanssa.Standardikirjasto linkitetään omaan koodiin #include-direktiivillä (tarkoittaa käytännössä samaa kuin että koko kir-jaston koodi olisi kopioitu oman koodin alkuun. Tätä halutaan välttää, sillä tekniset yksityiskohdat eivät ole kiinnostaviatässä vaiheessa).

1.5 Virhetyypit sekä ohjelmointi käytännössä

Ohjelmointityössä törmää seuraavanlaisiin virheisiin:

• kääntöajan virheet (compile-time errors)

• linkitysajan virheet (link-time errors)

• suorituksenaikaiset virheet (run-time errors)

Pääsääntönä on, että kääntöajan virheet on helpointa korjata, suorituksen aikaiset virheet työläintä. Virheitä tarkastelem-me jonkin verran kurssin loppupuolella luvussa 5.

Ohjelmointia voi tehdä joko käyttäen komentoriviä ja tekstieditoria tai kehitysympäristöä (IDE, Integrated Develop-ment Environment). IDE:n etuja ovat usein monipuoliset koodin käsittelyominaisuudet, haittoja raskas käyttöliittymä(liian paljon ominaisuuksia) ja ei-niin-suora koodin suorittaminen kuin komentoriviltä. Ohjelmoinnin alussa kannattaakäyttää komentoriviä ja sitten halutessaan voi siirtyä IDEn käyttöön jossakin vaiheessa, kunhan ymmärtää ensin perus-asiat.

1.6 Vinkkejä: komentorivin käyttö

Ohjelmointi suoritetaan tällä kurssilla kokonaan komentoriviltä, sillä samalla se opettaa tuntemaan tietokoneen rakennet-ta hieman paremmin. Komentorivin saa auki painamalla Win-R, kirjoittamalla Suorita-ikkunaan tekstin cmd ja painamal-la Enter. Kansioissa voi navigoida taaksepäin komennolla cd .. ja eteenpäin komennolla cd hakemiston_nimi,esimerkiksi cd Omat Tiedostot. Tabulaattori täydentää sanat, eli voit kirjoittaa vain cd Om ja painaa Tabia, jolloinnimi täydentyy ja Enterillä voit siirtyä ks. hakemistoon.

Komentoriviltä voi suoraan kopioida tekstiä, esimerkiksi kääntäjän virheilmoituksia. Painetaan ALT-SPACE→ ominai-suudet→ pikamuokkaustila. Nyt voidaan valita tekstiä, kopioida sen painamalla Enteriä leikepöydälle ja liittää vaikkapatekstitiedostoon. Tämä on hyödyllistä esimerkiksi silloin, kun haluaa analysoida virhelogeja ja napata niistä osan talteen.

Lisätietoa komentorivin käytöstä löytyy osoitteesta http://www.commandwindows.com.

3

Page 8: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

1.7 Kysymyksiä luvusta 1

1. Miillaisia työkaluja helloworld.cpp esittelee käyttöön?

2. Mikä on kääntäjä?

3. Mitä linkkeri tekee?

4. Mitä ovat .h-päätteiset tiedostot ja miksi niitä tarvitaan?

5. Mitä eroa on lähdekooditiedostolla ja konekielisellä tiedostolla?

6. Mitä etua/haittaa on komentorivin/IDEn käytöstä ohjelmointityössä?

1.8 Tehtäviä luvusta 1

1. Asenna koneelle tarvittavat ohjelmat ja hae Stroustrupin sivuilta standardikirjasto.

2. Kirjoita helloworld.cpp ja aja se komentoriviltä. Korjaa mahdolliset virheet, mikäli niitä ilmenee.

3. Kokeile, millä tavalla kääntäjä reagoi erilaisiin virheisiin. Testaa ainakin seuraavia:

• unohtunut sulku funktiosta main (

• unohtunut lainausmerkki standardikirjaston ympäriltä: "std\_ lib\_ facilities.h

• pääohjelman main väärä nimi

• pääohjelman väärä tyyppi, esimerkiksi double main ()

• kirjoitusvirhe cout→ trout

• "Hello World!\n jälkimmäinen lainausmerkki jätetään pois

• Unohdetaan puolipiste "Hello World!\n" lopusta

• Rivinvaihto lainausmerkkien ulkopuolelle eli "Hello World!"\n

4

Page 9: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

2 Objektit, tyypit ja arvot

Ohjelmointitaito vaatii kielen perusrakenteiden hyvää tuntemusta. Tämän luvun aikana tutuksi tulevat kielen yksinker-taisimmat osa eli mm. objektit, muuttujat, tyypit ja niihin liittyvät operaatiot.

Asioiden esittely voi tuntua ajoittain melko tekniseltä. Suosittelen, että lukiessa ensimmäisellä kerralla kannattaa edetärauhallisesti siten, että ymmärtää käsitteiden merkityksen ja liittymisen toisiinsa mahdollisimman hyvin.

2.1 Käyttäjän syötteen lukeminen ja ruudulle tulostaminen

Luvussa 1 tulostimme tekstiä ruudulle kirjoittamalla cout <<. Käyttäjältä voidaan myös lukea tietoa, jolloin kirjoite-taan cin >>. Esimerkiksi kokonaisluku luetaan näin:

int kokonaisluku ;cin >> kokonaisluku ; / / c i n = s t a n d a r d i n p u t s t r e a m

edellinen sijoittaa muuttujan kokonaisluku arvoksi sen, mitä käyttäjä kirjoittaa ruudulle. Nimen kirjoittamisen jäl-keen painetaan Enter-näppäintä.

Joskus käyttäjältä pyydetään erityisesti jotain syötettä, esimerkiksi tulostamalla ruudulle seuraavanlainen teksti:

cout << "Kirjoita ruudulle, kuinka vanha olet.\n" ;int oma_ika ;cin >> oma_ika ;

Kyselystä käytetään erityistä nimeä kehote (prompt). Huomaa, että muuttujan oma_ika tulee olla määritelty ennen kuinsiihen voidaan lukea arvo. Muuttujan määritelmä (definition) sisältää aina muuttujan tyypin ja nimen sekä mahdollisestialkuarvon: esimerkiksi int oma_ika = 10; on järkevästi kirjoitettu lauseke, joka määrittelee muuttujan oma_ika.

Jos käyttäjältä halutaan lukea useita muuttujan arvoja, esimerkiksi kaksi kokonaislukua ja tulostaa ne sitten ruudulle,voidaan molemmat operaatiot kirjoittaa yhteen sisään- ja ulostulovirtaan:

int luku1 ;int luku2 ;cout << "Kirjoita kaksi lukua ruudulle\n" ;cin >> luku1 >> luku2 ;cout << luku1 << " " << luku2 << "\n" ;

Huomaa, että lainausmerkeissä oleva teksti tulostuu täsmälleen sellaisena kuin se on kirjoitettu. Lainausmerkkejä eikäytetä, kun tulostetaan jonkin muuttujan arvo.

2.2 Objektit ja tyypit: johdantoa

Tiedon tallennuspaikka tietokoneen muistissa on nimeltään objekti (object). Nimetty objekti on muuttuja (variable),jolle voidaan sijoittaa jokin arvo (value). Lauseke (statement), joka määrittelee muuttujan ja sen mahdollisen alkuarvon(initial value), on määritelmä. Esimerkkejä määritelmistä ovat ainakin edellä esitetyt int luku1; ja int oma_ika = 10;,joista jälkimmäinen määrää myös muuttujan alkuarvon.

Muuttujaan tulee sijoittaa sen tyyppiä vastaava arvo, sillä muuten kääntäjä antaa virheilmoituksen. Tyyppejä ovat mm.double (desimaaliluku eli liukuluku), int (kokonaisluku), char (merkki), string (merkkijono) ja bool (totuusarvo elitosi tai epätosi). Lisäksi jokaisella tyypillä on oma literaalinsa eli muuttujan arvon merkitsemistapa, esimerkiksi

5

Page 10: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

double b = 3 . 9 ;int a = 3 9 ;char c = 'c' ;string d = "jotain tekstia"

bool totuus_arvo = true ;

Jos muuttujalle antaa vääräntyyppisen arvon, niin arvoa luettaessa ruudulle voi tulostua täysin mielivaltainen arvo, esi-merkiksi −9837. Kyseessä on se arvo, joka on tietokoneen muistissa ks. muistipaikassa oli täsmälleen sillä hetkellä, kunvääräntyyppistä arvoa yritettiin syöttää. Mikäli haluaa varmistua siitä, että oikeanlainen arvo on sijoitettu, niin kannattaaantaa muuttujalle sopiva alkuarvo (ikää kysyttäessä se voisi olla vaikkapa −1).

Merkkijonomuuttujan (string) lukeminen päättyy C++-kielessä aina välilyöntiin, rivinvaihtoon tai tabulaattorimerkkiin(whitespace). Luettaessa vaikkapa kaksiosaista nimeä tulee kirjoittaa

string etunimi ;string sukunimi ;cin >> etunimi >> sukunimi ;

Huomaa, että syöteoperaattori >> reagoi tyyppiin, joten sille tulee antaa määritellyn muuttujan tyyppiä vastaava arvo,esimerkiksi seuraavasti:

cout << "Kirjoita ruudulle, kuinka vanha olet.\n" ;int oma_ika ;cin >> oma_ika ;cout << "Olet " << oma_ika << " vuotta vanha\n" ;

Tarkastellaan nyt lyhyttä ohjelmaa, joka kysyy käyttäjältä etunimen ja iän.

2.2.1 Esimerkki: Käyttäjän ikä ja nimi

ikajanimi.cpp

1 #include "../std_lib_facilities.h"

2

3 int main ( )4 {5 cout << "Kirjoita etunimesi ja ik\x84si\n" ;6 string etu_nimi ;7 double ika = −1.0; / / a l k u a r v o k s i " mahdoton a rvo "8 cin >> etu_nimi >> ika ;9 cout << "Hei, " << etu_nimi

10 << " (ik\x84 " << ika << " vuotta)" ;11 }

Käydään koodia läpi rivi riviltä.

1. Otetaan standardikirjasto käyttöön yhtä hakemistotasoa ylempää.

5. Kirjoitetaan kehote, joka pyytää käyttäjää kirjoittamaan etunimen ja iän.

6. Määritellään merkkijonomuuttuja etu_nimi.

6

Page 11: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

7. Määritellään desimaalilukumuuttuja ika ja alustetaan se siten, että voidaan tunnistaa myöhemmin mahdollinenvirheellinen syöte (jos käyttäjä syöttää vääräntyyppisen arvon, niin ruudulle tulostuu−1 ja tiedämme, että syötettyarvo oli virheellinen).

8. Luetaan käyttäjältä etu_nimi ja ika.

9. Tulostetaan teksti Hei, ..., missä kolmen pisteen paikalla on käyttäjän kirjoittama nimi.

10. Tulostetaan (ikä ... vuotta)., missä kolmen pisteen paikalla on käyttäjän kirjoittama ikä. Huomaa, et-tä kirjain ä on kirjoitettu lainausmerkkien sisään muodossa x84. Tämä on välttämätöntä, jotta se näkyy oikein(kääntäjä käyttää ilmeisesti eri merkistöä kuin Windows, joten skandit on kirjoitettava ns. heksadesimaalimuodos-sa. Vastaavasti kirjain ö kirjoitettaisiin x94).

2.3 Operaattorit

Muuttujan tyyppi määrittää, millaisia operaatioita muuttujaan voidaan kohdistaa. Kääntäjä antaa virheilmoituksen, jostyyppi ja operaatio eivät sovi yhteen. Esimerkkejä operaatioista:

int numero ;string kirjaimet ;cin >> numero >> kirjaimet ;int numero_2 = numero + 1 ;string kirjaimet_2 = kirjaimet + " ja jotain." ;cout << numero_2 << " " << kirjaimet_2 ;

int-tyypin muuttujaan voidaan lisätä lukuja ja string-tyypin muuttujaan voidaan kasvattaa, jolloin uusi merkkijo-no sisältää alkuperäisen lisäksi annetut uudet merkit. Operaatioiden ja tyyppien yhteensopivuudet oppii kokemuksenkautta ja alkuvaiheessa kannattaa katsoa asiaan liittyviä taulukoita. Valikoima operaattoreita on listattu taulukossa 1.Operaattoreiden toiminta saman kategorian muuttujille (esimerkiksi int ja double) on yleensä samankaltaista. Vaik-ka jokin operaatio ei suoraan olisi sallittu jollekin tyypille, niin voi olla epäsuora keino ks. operaation käyttämiseen.Katsotaan esimerkki operaatioiden käyttämisestä.

2.3.1 Esimerkki: Operaattoriharjoitus

operaattoriharjoitus.cpp

1 #include "../std_lib_facilities.h"

2

3 int main ( )4 {5 cout << "Kirjoita ruudulle liukuluku\n" ;6 double liukuluku ;7 cin >> liukuluku ;8 int liukuluku_toint = liukuluku ; / / t a r v i t a a n moduloa v a r t e n9 cout << "liukuluku == " << liukuluku

10 << "\n3 kertaa liukuluku == " << 3*liukuluku / / r i v i n v a i h t o a l u s s a !11 << "\nliukuluku + liukuluku == " << liukuluku+liukuluku12 << "\nliukuluvun neli\x94 == " << liukuluku*liukuluku13 << "\nliukuluvusta puolet == " << liukuluku / 2

7

Page 12: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

TAULUKKO 1: Valikoima operaattoreita

Operaatio bool char int double string

sijoitus (assignment) = = = = =

lisäys / merkkijonon pidennys + + +

vähennys - -

kertominen ∗ ∗jakaminen / /

jakojäännös %

lisääminen yhdellä ++ ++

vähentäminen yhdellä -- --

lukee lähteestä s muuttujaan x s » x s » x s » x s » x s » x

kirjoittaa arvon x ulostuloon s s « x s « x s « x s « x s « x

yhtä suuri kuin == == == == ==

ei yhtä suuri kuin != != != != !=

suurempi kuin > > > > >

suurempi tai yhtä suuri kuin >= >= >= >= >=

pienempi kuin < < < < <

pienempi tai yhtä suuri kuin <= <= <= <= <=

8

Page 13: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

14 << "\nliukuluvun neli\x94juuri == " << sqrt (liukuluku )15 <<"\nliukuluku modulo 2 on " << liukuluku_toint%216 << endl ;17 }

Ohjelmassa operaattoriharjoitus.cpp tarkastellaan liukuluvun eli desimaaliluvun (double) operaatioita. Kat-sotaan soveltuvin osin koodin tärkeimmät kohdat.

9. Liukuluku muutetaan kokonaisluvuksi eli määritellään kokonaislukumuuttuja liukuluku_toint ja annetaansen arvoksi liukuluvun arvo. Tässä on kyseessä eräänlainen tyyppimuunnos, jossa tietoa häviää: desimaalilukupyöristyy näissä tilanteissa aina alaspäin, esimerkiksi luku 1.9 arvoon 1. Kannattaa olla tarkkana, jos koodissa ontyyppimuunnoksia!

12. Skandikirjain ö on kirjoitettu heksadesimaalina muodossa x94.

14. Liukuluvun neliöjuuri saadaan käyttämällä hyväksi standardikirjaston funktiota sqrt(), joka ottaa argumenttinayhden liukuluvun. Funktion sqrt() sisäisestä rakenteesta ei tarvitse välittää tässä vaiheessa.

15. Modulo eli jakojäännös mittaa sitä, mitä jää jäljelle, kun kokonaisluvuksi muunnettu liukuluku jaetaan kahdella.Tuloksen pitäisi olla joko 0 tai 1 riippuen siitä, onko muuttujan liukuluku_toint arvo parillinen vai pariton.

16. Tulostusvirta cout lopetetaan ja rivi vaihdetaan kirjoittamalla tulostuksen loppuun endl;.

2.4 Nimet C++:ssa

Pääsääntöinä nimivalinnoissa muuttujille, funktioille tms. on, että

• nimi alkaa kirjaimella,

• sisältää vain kirjaimia (pienet ja isot), numeroita ja alaviivoja

• nimissä ei saa olla välilyöntejä.

Iso kirjain on eri asia kuin pieni kirjain ja skandeja ei käytetä nimissä. Noin 70 nimeä on varattu C++:ssa avainsanoille(keywords) ja niitä ei saa käyttää muuttujien, tyyppien, funktioiden ja vastaavien nimissä (esimerkkejä vaikkapa int jadouble). Ei myöskään kannata käyttää standardikirjaston osien nimiä, kuten esim. string tai vastaavaa.

Nimen pitää olla kuvaava, sopivan pituinen ja mielellään sisältää pääosin pieniä kirjaimia. Esimerkkejä hyvistä nimistäovat seuraavat:

tarkastaja_funktio

valuuttamuunnin

Elementtilaskuri

Toinen_vaihtoehto

Kannattaa välttää nimiä, jotka on helppo lukea tai kirjoittaa väärin tai sekoittaa toisiinsa (erityisesti kirjainten 0, O, o, 1,l ja I osalta). Katsotaan seuraavaksi esimerkki siitä, kuinka käy, jos nimen kirjoittaa väärin.

9

Page 14: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

2.4.1 Esimerkki: virheilmoitukset nimissä

nimivirheilmoitukset.cpp

1 / * ========================================================================== * /2 / * * /3 / * n i m i v i r h e i l m o i t u k s e t . cpp * /4 / * ( c ) 1 9 . 2 . 2 0 1 1 Riku J ä r v i n e n * /5 / * * /6 / * D e s c r i p t i o n7 K a t s o t a a n v i r h e i l m o i t u k s i a , kun m u u t t u j i e n j a t y y p p i e n n i m i s s ä on v i r h e i t ä .8 ========================================================================== * /9

10 #include "../std_lib_facilities.h"

11

12 / / l a i t e t a a n kommen t t e ih in v i r h e e l l i n e n kood i j a s i i h e n l i i t t y v ä v i r h e l o g i ,13 / / t ä h ä n a l l e p u o l e s t a a n t o i m i v a kood i .14

15 int main ( )16 {17 string s = "T\x84ss\x84 kokeillaan eri virhetyyppej\x84." ;18 cout << s << '\n' ;19 }20

21 / *22 K i r j o i t e t a a n oh je lman ensimmäinen v e r s i o , j o k a s i s ä l t ä ä p a l j o n v i r h e i t ä :23

24 i n t Main ( )25 {26 S t r i n g s = "T \ x84ss \ x84 k o k e i l l a a n e r i v i r h e t y y p p e j \ x84 . " ;27 cOut << S << ' \ n ' ;28 }29

30 Y l l ä o l e v a kood i t u o s e u r a a v a n l a i s e n v i r h e l o g i n :31

32 k o o d i v i r h e i l m o i t u k s e t . cpp : In f u n c t i o n ' i n t Main ( ) ' :33 k o o d i v i r h e i l m o i t u k s e t . cpp : 1 5 : 5 : e r r o r : ' cOut ' was n o t d e c l a r e d i n t h i s scope34 k o o d i v i r h e i l m o i t u k s e t . cpp : 1 5 : 1 3 : e r r o r : ' S ' was n o t d e c l a r e d i n t h i s scope35

36 E l i k e r t o o , e t t ä v i r h e on f u n k t i o s s a i n t Main ( ) . cOut e i o l e m ä ä r i t e l t y e i k ä S37 o l e m ä ä r i t e l t y . K o r j a t a a n v i r h e e t , e l i l a i t e t a a n c o u t e n s i n o i k e i n , t s .38 s e u r a a v a n n ä k ö i n e n kood i :39

40 i n t Main ( )41 {42 S t r i n g s = "T \ x84ss \ x84 k o k e i l l a a n e r i v i r h e t y y p p e j \ x84 . " ;43 c o u t << S << ' \ n ' ;44 }45

46 Y l l ä o l e v a kood i t u o s e u r a a v a n l a i s e n v i r h e l o g i n :

10

Page 15: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

47

48 k o o d i v i r h e i l m o i t u k s e t . cpp : In f u n c t i o n ' i n t Main ( ) ' :49 k o o d i v i r h e i l m o i t u k s e t . cpp : 1 7 : 1 3 : e r r o r : ' S ' was n o t d e c l a r e d i n t h i s scope50

51 Muute taan S t r i n g−m u u t t u j a n s n imi o i k e i n e l i k o r v a t a a n S −> s .52

53 i n t Main ( )54 {55 S t r i n g s = "T \ x84ss \ x84 k o k e i l l a a n e r i v i r h e t y y p p e j \ x84 . " ;56 c o u t << s << ' \ n ' ;57 }58

59 Y l l ä o l e v a kood i t u o s e u r a a v a n l a i s e n v i r h e l o g i n :60

61 c : / mingw32 / b i n / . . / l i b / gcc / mingw32 / 4 . 5 . 1 / . . / . . / . . / l ibmingw32 . a ( main . o ) : main . c : ( . t62 e x t +0xd2 ) : u n d e f i n e d r e f e r e n c e t o `WinMain@16 '63 c o l l e c t 2 : l d r e t u r n e d 1 e x i t s t a t u s64

65 E l i n y t k ä ä n t ä j ä i l m o i t t a a v i r h e e l l i s e s t ä v i i t t e e s t ä Main−f u n k t i o s s a : k o r j a t a a n66 Main −> main .67

68 i n t main ( )69 {70 S t r i n g s = "T \ x84ss \ x84 k o k e i l l a a n e r i v i r h e t y y p p e j \ x84 . " ;71 c o u t << s << ' \ n ' ;72 }73

74 K ä ä n t ä j ä e i anna v i r h e i l m o i t u s t a , t u l o s t a a n o r m a a l i s t i . Näin o l l e n75 S t r i n g−m u u t t u j a n t y y p p i ( v ä ä r i n k i r j o i t e t t u ) e i o l l u t n ä h t ä v ä s t i e s t e e n ä76 oh je lman t o i m i n n a l l e . K i r j o i t e t a a n l o p u l l i s e e n v e r s i o o n k u i t e n k i n o i k e a o p p i n e n77 koodi , e l i muu te t aan S t r i n g −> s t r i n g .78

79 * /

2.5 Alkuarvon asettaminen ja sijoittaminen

Muuttujan alkuarvon asettaminen (initialization) tapahtuu operaattorilla =. Esimerkkejä ovat mm. seuraavat:

string merkkijono = "jotain merkkej\x84 t\x84ss\x84" ;int luku = 3 2 ;double isoluku = 3934783744*luku ;double viela_isompi_luku = sqrt (isoluku ) ;bool totuus = true ;

Operaattorilla = voidaan myös sijoittaa uusi arvo (assign) jo olemassa olevaan muuttujaan:

a = "merkkijono" ; / / j o m ä ä r i t e l l y n s t r i n g−m u u t t u j a n a a r v o k s i m e r k k i j o n ob = b+3; / / l i s ä t ä ä n b : n a rvoon 3 j a s i j o i t e t a a n summa−a rvo b : n p a i k a l l ec = d%2 / / o l e t t a a , e t t ä c j a d o v a t i n t−t y y p p i ä

11

Page 16: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

Looginen ero sijoittamisen ja alkuarvon asettamisen välillä on se, että alkuarvon asettaminen ”löytää” muuttujan tyhjänä,kun taas sijoittaminen poistaa edellisen arvon ja laittaa tilalle uuden. Katsotaan esimerkkinä ohjelma, joka tarkastaakirjoitetusta lauseesta, ovatko peräkkäiset sanat samoja.

2.5.1 Esimerkki: nimiharjoitus 1

nimiharjoitus.cpp

1 / * ========================================================================== * /2 / * * /3 / * n i m i h a r j o i t u s . cpp * /4 / * ( c ) 2011 Riku J ä r v i n e n * /5 / * * /6 / * D e s c r i p t i o n * /7 / * T a r k a s t a a k i r j o i t e t u s t a l a u s e e s t a , o v a t p e r ä k k ä i s e t s a n a t samoja . * /8 / * ========================================================================== * /9

10 #include "../std_lib_facilities.h"

11

12 int main ( )13 {14 cout << "Kirjoita teksti\x84, niin ohjelma etsii kahdentuneet sanat.\n" ;15 string edellinen = " " ; / / e d e l l i n e n sana : a l k u a r v o e i o l e sana ( f a i l s 1 s t )16 string nykyinen ;17 while (cin>>nykyinen ) {18 if (edellinen == nykyinen ) / / onko e d e l l i n e n saman ku in nyky inen19 cout << "Toistettu sana: " << nykyinen << '\n' ;20 edellinen = nykyinen ;21 }22 }23

24

25 / *26 w h i l e ( c in >> c u r r e n t ) t o t e u t u u n i i n monta k e r t a a , kun o p e r a a t t o r i c in >> c u r r e n t27 on vo imassa e l i n i i n kauan ku in on o l e m a s s a l u e t t a v i a merkke jä k ä y t t ä j ä n28 s y ö t t e e s s ä . S t r i n g−m u u t t u j a l l e o p e r a a t t o r i >> l u k e e t y h j ä l l ä v ä l i l l ä29 ( w h i t e s p a c e ) e r o t e l t u j a s a n o j a . Loopin v o i k a t k a i s t a p a i n a m a l l a C t r l−C30 ( k a t k a i s e e koko oh je lman t o i m i n n a n ) t a i C t r l−Z ( Unix−k o n e i s s a C t r l−D) .31 * /32

33 / *34 kuvaus oh je lman t o i m i n n a s t a l a u s e e l l e " ankka u i u i v e d e s s ä " :35

36 N ä y t ö l l e t u l o s t u u o h j e t e k s t i .37

38 e d e l l i n e n sana on t y h j ä , oh j e lma l u k e e s a n a a ankka39 whi le−l o o p p i on vo imassa . Ohjelma v e r t a a s a n a a ankka t y h j ä ä n j a i f−l a u s e40 j ä ä s u o r i t t a m a t t a , s i l l ä ankka e i o l e sama ku in t y h j ä t i l a41 s t r i n g−m u u t t u j a n e d e l l i n e n a r v o k s i s i j o i t e t a a n nyky inen sana e l i ankka .42

12

Page 17: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

43 e d e l l i n e n on ankka , oh je lma l u k e e k ä y t t ä j ä n s y ö t t ä m ä n sanan u i .44 whi le−l o o p p i , oh j e lma v e r t a a s a n o j a ankka j a ui , i f−l a u s e e i t o t e u d u j a45 m u u t t u j a n e d e l l i n e n a r v o k s i s y ö t e t ä ä n m e r k k i j o n o u i .46

47 e d e l l i n e n on ui , oh j e lma l u k e e s y ö t t e e n u i48 whi le−l o o p p i , oh j e lma v e r t a a s a n o j a u i j a u i j a i f−l a u s e t o t e u t u u , j o l l o i n49 n ä y t ö l l e t u l o s t u u t e k s t i : T o i s t e t t u sana : u i ( r i v i n v a i h t o )50 m u u t t u j a n e d e l l i n e n a r v o k s i s i j o i t e t t a a n sana u i51

52 e d e l l i n e n on ui , oh j e lma l u k e e sanan v e d e s s ä j a v e r t a a u i j a v e d e s s ä53 keskenään , i f−l a u s e e i t o t e u d u , s i j o i t e t a a n e d e l l i n e n m u u t t u j a n a r v o k s i54 v e d e s s ä55

56 whi le−l o o p p i e i t o t e u d u , koska k ä y t t ä j ä n s y ö t t e e s s ä e i o l e enempää s a n o j a .57 * /

Esimerkissä käytettiin if-lausetta, joka toteutuu silloin, kun sen argumenttina eli ()-sulkujen sisällä oleva ehto on tosi.Ehtorakenteista puhumme lisää seuraavassa luvussa.

Ohjelmoinnissa on tyypillistä, että jo olemassa olevaa koodia parannellaan ja muokataan pitkänkin ajan kuluessa. Seu-raavassa on hieman paranneltu versio nimiharjoituksesta, joka kertoo myös sen, kuinka mones sana oli kirjoitettu kaksikertaa.

2.5.2 Esimerkki: nimiharjoitus 2

nimiharjoitus2.cpp

1 / * ========================================================================== * /2 / * * /3 / * n i m i h a r j o i t u s 2 . cpp * /4 / * ( c ) 2011 Riku J ä r v i n e n * /5 / * * /6 / * D e s c r i p t i o n * /7 / * T a r k a s t a a k i r j o i t e t u s t a l a u s e e s t a , o va tko p e r ä k k ä i s e t s a n a t samoja .8 k e r t o o l i s ä k s i , k u i nka mones sana o l i k i r j o i t e t t u k a k s i k e r t a a . * /9 / * ========================================================================== * /

10

11 #include "../std_lib_facilities.h"

12

13 int main ( )14 {15 int sanojen_lkm = 0 ; / / a l u s t e t a a n s a n o i s t a k i r j a a p i t ä v ä l a s k u r i16 cout << "Kirjoita teksti\x84, niin ohjelma etsii kahdentuneet sanat.\n" ;17 string edellinen = " " ; / / e d e l l i n e n sana : a l k u a r v o e i o l e sana18 string nykyinen ;19 while (cin>>nykyinen ) {20 ++sanojen_lkm ; / / a i n a l o o p i n a l u s s a l i s ä t ä ä m c o u n t e r i a y h d e l l ä21 if (edellinen == nykyinen ) / / onko e d e l l i n e n saman ku in nyky inen22 cout << "Sana numero " << sanojen_lkm

13

Page 18: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

23 << " toistettu: " << nykyinen << '\n' ;24 edellinen = nykyinen ;25 }26 }

2.6 Yhdistelmäoperaattorit

Sijoittaminen ja lisääminen/vähentäminen sekä sijoittaminen ja jakaminen/kertominen voidaan yhdistää yhdeksi operaat-toriksi, esimerkiksi

a += 8 ; / / t a r k o i t t a a a = a +8;b −= 7 / / b = b−7;c /= 2 / / c = c / 2 ;d *= 2 / / d = 2*d ;

Binäärioperaatioille eli operaatioille, jotka ovat kahden muuttujan välillä, voidaan aina kirjoittaa em. tavalla.

2.7 Tyypit ja niiden varaama tila muistissa

Kertausta ja hieman uutta:

• Objekti on osa tietokoneen muistia, jonne varastoidaan määrätyn tyypin arvo.

• Muuttuja on nimetty objekti eli nimetty paikka koneen muistissa.

• Tyyppi määrittää muuttujan mahdollisten arvojen joukon sekä ne operaatiot, joita muuttujalle voidaan tehdä

• Arvo on muistissa sijaitseva bittijono, joka tulkitaan tyypin perusteella.

• deklaraatio (declaration) on lauseke, joka antaa nimen objektille eli määrittää muuttujan.

Muistamme, että tyyppejä ovat mm. bool, char, int, double ja string. Tyypistä riippuen tietokone varaa kullekintietyn määrän muistia, yleensä taulukon 2 mukaisesti. Taulukon 2 bittimäärät tarkoittavat binääriarvoja, joten esimerkiksi

TAULUKKO 2: Tyypit ja niiden viemä tila muistissa

Tyyppi tavut (bytes) bitit (bits) tavut graafisesti

bool 1 8 X

char 1 8 X

int 4 32 XXXX

double 8 64 XXXXXXXX

int-tyypin muuttujaa voisi esittää seuraavanlainen bittijono:

10110010 00101110 00001100 00010101

14

Page 19: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

Bittien sisältämän tiedon eli binääridatan tulkinta riippuu täysin tyypistä. Esim. data 10010010 voidaan tulkita jokokirjaimena (char) tai kokonaislukuna (int).

string-tyypin muuttujaan tallentuu tieto merkkijonon merkkien määrästä sekä itse kirjaimista. Merkkijonon varaamabittimäärä riippuu näin ollen sen pituudesta.

Taulukossa 2 bool vie kahdeksan bittiä, vaikka käytännössä se voi sisältää vain kaksi mahdollista arvoa (true tai false).Tämä johtuu tietokonemuistin teknisistä ominaisuuksista: pienin toimiva tiedon tallennusyksikkö on tavu.

2.8 Tyyppimuunnokset

Objektin tyyppi voidaan muuntaa toiseen tyyppiin kahdella tavalla, joko turvallisesti tai ei-turvallisesti (safe andunsafe type conversions). Turvallisessa muunnoksessa tietoa ei häviä, ei-turvallisessa sitä voi hävitä. Tällöin ohjelma voitoimia ei-toivotulla tavalla. Toisaalta, jotkut ohjelmat on suunniteltu toimimaan normaalisti ei-turvallisten muunnostenkautta (ei käsitellä tällä kurssilla). Kun yleisesti puhutaan tyyppien turvallisuudesta (type safety), tarkoitetaan, että kir-joitetussa ohjelmassa muuttujien tyypit on asetettu oikein niin, että tietoa ei vahingossa katoa (ts. ei käytetä ei-turvallisiatyyppimuunnoksia).

Pääsääntöisesti muunnos on turvallinen, jos tietoa siirretään pienemmästä tiedon varaamiseen tarkoitetusta yksiköstäsuurempaan. Esimerkkejä turvallisista muunnoksista ovat mm.

bool → charbool → intbool → doublechar → intchar → doubleint → double

Mikäli int on erittäin suuri, niin muunnos int→ double saattaa aiheuttaa pientä epätarkkuutta tietokoneen lasken-tatehosta riippuen.

Ei-turvallisia muunnoksia ovat mm.

double → intdouble → chardouble → boolint → charint → boolchar → bool

Ongelmana double→ int -muunnoksessa on kokorajoituksen lisäksi pyöristys (aina alaspäin) ja double→ char

-muunnoksessa suuri double ei mahdu chariin, jolloin saadaan epämääräinen arvo. Vastaavasti myös int→ char jne.Esimerkiksi PC:ssä char-arvot ovat välillä [−128, 127] eli 256 eri arvoa (tulee suoraan, kun laskee 28 = 256.

Ei-turvalliset muunnokset ovat olemassa osittain historiallisista syistä (on olemassa koodia, jossa niitä on käytetty ai-emmin, esim. C-kielellä) eli jotkut ohjelmat tarvitsevat niitä toimiakseen oikein. Jos omissa ohjelmissa epäilet sitä, ettämuunnoksessa häviää tietoa, niin kannattaa tarkastaa muuttujan arvo ajamalla ohjelma ennen kuin arvon sijoittaa eteen-päin johonkin lausekkeeseen. Katsotaan esimerkkinä muutamia tyyppimuunnoksia. Ohjelmaa on kommentoitu melkorajusti, mutta kannattaa lueskella kaikki kohdat tarkasti niin huomaa mielenkiintoisia asioita.

15

Page 20: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

2.8.1 Esimerkki: tyyppimuunnokset

tyyppikonversiot.cpp

1 / * ========================================================================== * /2 / *3 t y y p p i k o n v e r s i o t . cpp * /4 / * ( c ) 2 0 . 2 . 2 0 1 1 Riku J ä r v i n e n * /5 / * * /6 / * D e s c r i p t i o n7 T e s t a i l l a a n t y y p p i m u u n n o k s i a : k ä y t t ä j ä n s y ö t t ä m ä l i u k u l u k u muunnetaan8 k o k o n a i s l u v u k s i j a m e r k i k s i j a v e r t a i l l a a n a r v o j a . * /9 / * ========================================================================== * /

10

11 #include "../std_lib_facilities.h"

12

13 int main ( )14 {15 double a = 0 ;16 cout << "\nSeuraavat selitykset p\x84tev\x84t seuravaaville kirjaimille:\n"

17 << "Alkuper\x84inen double on a\n"

18 << "double k\x84\x84nnettyn\x84 int-arvoksi on b\n"

19 << "int k\x84\x84nnettyn\x84 char-merkiksi on c\n"

20 << "char-merkin int-arvo on d.\n"

21 << "k\x84\x84nnetty int-arvo doubleksi on e\n"

22 << "\nKirjoita ruudulle haluttu luku tai luvut!\n" ;23 while (cin>>a ) {24 int b = a ;25 char c = b ;26 int d = c ;27 double e = d ;28 cout << "\na==" << a

29 << "\nb==" << b

30 << "\nc==" << c

31 << "\nd==" << d

32 << "\ne==" << e << "\n" ;33 }34 }

Seuraavassa hieman testituloksia edellisestä ohjelmasta.

1 / * K o k e i l l a a n e r i l a i s i a i n p u t t e j a j a k a t s o t a a n , mi t en numerot m u u t t u v a t .2

3 a==24 b==25 c ==?6 d==27

8 a==3

16

Page 21: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

9 b==310 c ==?11 d==312

13 a==−214 b==−215 c== ¦16 d==−217 e==−218

19 a==−1520 b==−1521 c== ±22 d==−1523 e==−1524

25 ok − oh je lma n ä y t t ä ä a i n a k i n a l u s t a v a s t i t o i m i v a n k u n n o l l a26

27 a ==12728 b==12729 c== ¦30 d==12731

32 a ==12833 b==12834 c==Ç35 d==−12836

37 h a v a i t a a n c h a r i n y l ä r a j a e l i 127 , s e u r a a v a a rvo 128 menee a l a r a j a l l e −12838

39 a==−12840 b==−12841 c==Ç42 d==−12843

44 a==−12945 b==−12946 c== ¦47 d==12748

49 h a v a i t a a n , e t t ä c h a r i n a l a r a j a on −128, s i l l ä −129 menee y l ä r a j a l l e 12750

51 a==152 b==153 c ==?54 d==155

56 a ==25757 b==25758 c ==?

17

Page 22: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

59 d==160

61 a ==51362 b==51363 c ==?64 d==165

66 h a v a i t a a n s y k l i s y y s a r v o i s s a , e l i sama c h a r t u l e e a i n a 256 : n v ä l e i n j a n ä i n67 o l l e n myös sama d e l i t ä s s ä t a p a u k s e s s a ykkönen . Luku 256 t u l e e b i t t i m ä ä r ä s t ä :68 c h a r s i s ä l t ä ä 8 b i t t i ä e l i 2^8=256 e r i l a i s t a a r v o a ( merkk iä ) .69

70 a ==59.971 b==5972 c ==;73 d==5974 e ==5975

76 h a v a i t a a n doub len p y ö r i s t y m i n e n k o k o n a i s l u v u k s i j a t i e d o n häv iäminen77 muunnoksen k a u t t a78

79 a==080 b==081 c==82 d==083 e==084

85 a ==−2.14748 e +00986 b==−214748364887 c==88 d==089 e==090

91 a ==2.14748 e +00992 b==−214748364893 c==94 d==095 e==096

97 huomataan i n t−m u u t t u j a n l u k u a l u e , e l i ( 2 ^ 3 2 ) = 4294967296 , t a r k o i t t a a98 k ä y t ä n n ö s s ä v ä l i ä [−2147483648 , +2147483648] .99 * /

2.9 Kysymyksiä luvusta 2

1. Mitä tarkoittaa termi prompt?

2. Mitä operaattoria käytetään, kun arvo luetaan muuttujaan?

3. Mitä tarkoittaa \n ja mihin sitä käytetään?

18

Page 23: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

4. Mikä lopettaa tekstin syötön string-tyypin muuttujaan?

5. Mikä lopettaa arvon syötön int-tyypin muuttujaan?

6. Mikä on objekti?

7. Mikä on literaali?

8. Mikä on muuttuja?

9. Mitkä ovat tyypilliset koot muuttujille char, int ja double?

10. Mitä mittayksikköä käytetään muistipaikoissa muuttujan varaamalle muistille?

11. Mitä tarkoittaa string-muuttujien yhdistäminen (+) ja kuinka se toimii C++:ssa?

12. Millaisia nimiä C++:ssa voi käyttää? millaisia sallituja nimiä ei kannata käyttää?

13. Mitä tarkoittaa tyyppien turvallisuus (type safety) ja miksi se on tärkeä ominaisuus?

14. Mitä ongelmia voi aiheuttaa muunnos double→ int?

15. Määrittele sääntö, joka perustelee sen, että tyyppimuunnos on turvallinen.

2.10 Tehtäviä luvusta 2

1. Kirjoita ohjelma, joka ei varsinaisesti tee mitään, vaan ainoastaan määrittelee muutamia muuttujia, osa virheelli-sesti ja osa oikein (esimerkiksi int double =0; tai vastaavaa). Katso, kuinka kääntäjä reagoi.

2. Kirjoita ohjelma, joka pyytää käyttäjää syöttämään kaksi kokonaislukua. Ohjelman tulee määrittää luvuista pie-nempi ja suurempi sekä laskea summa, erotus, tulo ja osamäärä sekä kertoa ne käyttäjälle.

3. Muunna edellisen tehtävän ohjelmaa siten, että se kysyy käyttäjältä liukuluvun (double) kokonaisluvun sijasta.Vertaa uuden ja vanhan ohjelman tulostamia arvoja. Eroavatko ne toisistaan?

4. Kirjoita ohjelma, joka kysyy käyttäjältä kolme kokonaislukua ja tulostaa ne pilkuilla erotettuina suuruusjärjestyk-sessä pienimmästä suurimpaan. Jos esimerkiksi käyttäjä kirjoittaa 3 5 1 niin ruudulle tulostuu 1, 3, 5. Jos kaksiarvoa ovat yhtä suuria, niin niiden keskinäisellä järjestyksellä ei ole merkitystä.

5. Tee samantyyppinen ohjelma kuin edellisessa tehtävässä, mutta korvaa numerot string-merkkijonoilla.

6. Kirjoita ohjelma, joka muuntaa kirjaimin kirjoitetut numerot (esimerkiksi ”nolla”) numeroarvoiksi kuten 0. Kunkäyttäjä kirjoittaa numeron kirjaimin, niin ohjelman tulee tulostaa vastaava numeroarvo. Toteuta tämä numeroille0, 1, 2, 3 ja 4 ja laita lisäksi ohjelma tulostamaan teksti ”tuntematon numero” jos käyttäjä syöttää jotain muutakuin edellämainitut.

19

Page 24: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

3 Laskentaa

Luvussa keskitytään mm. ohjelmoinnin yleisiin tavoitteisiin, lausekkeisiin (valinta ja iteraatio), funktioihin sekä vekto-reihin.

3.1 Laskennan perusteet

Laskenta tarkoittaa jonkin ulostulon (output) tuottamista jostakin sisääntulosta (input). Sisääntulo voi olla esim. näp-päimistöltä, hiireltä, syntetisaattorilta, mittausanturilta tai vastaavalta. Ohjelmoinnissa kiinnostavimmat näkökohdat ovatI/O (input/output) toisesta ohjelmasta tai toisesta ohjelman osasta. Perusidea hyvässä ohjelmointisuunnittelussa on mää-rittää se, millä tavalla eri osat toimivat keskenään ja millaisia rooleja niillä on datan tuottamisessa ja käyttämisessä.

Ohjelman osaan, esimerkiksi funktioon, menevää sisääntuloa kutsutaan argumentiksi (argument; näitä voi olla useita)ja ulostuloa tulokseksi tai palautusarvoksi (return value).

3.2 Ohjelmoinnin yleiset tavoitteet

Laskentaprosessin kolme tärkeintä peruselementtiä ovat laskujen oikeellisuus, yksinkertaisuus ja tehokkuus tässäjärjestyksessä. Ohjelmia korjataan ja kehitetään jatkuvasti, joten suunnittelu kannattaa tehdä jo alusta lähtien kunnolla,ennakoiden mahdollisia tulevaisuuden laajennuksia niin hyvin kuin vain voi. Hyvä suunnittelu tarkoittaa

• selkeää rakennetta koodille

• suurien, globaalien muutosten tekemistä tarvittaessa nopeasti ja edullisesti

• verraten pientä virheiden määrää. Tämä säästää myös virheiden korjaamiseen kuluvaa aikaa.

Kaiken kaikkiaan ohjelman vankka, hyvä rakenne säästää turhaa työtä myöhemmin.

Kuinka tällainen perusta voidaan saada aikaiseksi? Ajatuksena on jakaa suuri ohjelma pieniin osiin

1. abstrahoimalla (abstraction): käytetään valmiita kirjastoja, funktioita ja algoritmeja eli ei määritellä itse kaikkimahdollisia tarvittavia työkaluja.

2. erottelemalla toisistaan ohjelman loogiset osat ja käsittelemällä ne omina aliohjelminaan, jotka yhdessä muo-dostavat kokonaisen, toimivan ohjelman.

Miksi suunnittelua tehdään ja kuinka välttämätöntä se on? Kun koodia alkaa olemaan reippaat 1 000 000 riviä, niinohjelman kehittäminen ei onnistu ilman loogista järjestystä. Jos koodarit vaihtuvat, kuten usein tapahtuu, niin uusienhenkilöiden on saatava selvää ohjelman rakenteista ja toiminnoista, yleensä nopealla aikataululla.

3.3 Ilmaisut

Ilmaisu (expression) laskee arvon operandien ja operaattoreiden perusteella ja on ohjelmakoodin perusblokki. Esimer-kiksi muuttujan määrittely muotoa

int luku = 3

on ilmaus, samoin

20

Page 25: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

double c = a + b

mikäli a ja b on määritelty (ja alustettu) aiemmin. Ilmauksesta saadaan lauseke (statement) laittamalla sen perään puo-lipiste, jolloin tässä yhteydessä puhutaan ilmaisulausekkeesta (expression statement).

Ilmauksessa int luku = 3 luku-sana on objektin (muistipaikan) nimi, sen tyyppi on int ja siitä käytetään joskustermiä vasen arvo (left value, lval). Vastaavasti numero 3 on muuttujan luku arvo eli oikea arvo (right value, rval).Ilmaisuissa ovat matematiikan tavalliset säännöt ovat voimassa, kuten mm. +, -, *, / ja niin edelleen. Tämän lisäksi onsuositeltavaa käyttää tarpeen mukaan yhdistelmäoperaattoreita +=, -=, /= ja *= yksinkertaistamaan toimintoja. Arvonlisäämisessä yhdellä kannattaa käyttää ilmausta ++arvo;.

Vakioiden ilmaiseminen C++:ssa tehdään const-merkinnällä, esimerkiksi

const double pi = 3 . 1 4 1 5 9 ;

määrittää vakion π arvoksi 3.14159. Kannattaa määrittää vakio alussa ja käyttää sen nimeä pelkän numeroarvon sijaan,sillä se selventää koodia. Lisäksi vakiota on helpompi muuttaa tarvittaessa (määrittely vain yhdessä paikassa). Pääsään-töisesti vain lukuja 0 ja 1 saa käyttää koodin seassa itsestäänselvissä ja varmasti oikein tulkittavissa jutuissa (esimerkikipalautusarvo, joka kertoo, suorittiko ohjelma toimintonsa normaalisti loppuun saakka).

Operaattoreita on paljon ja niitä oppii käytön kautta. Huomaa, että ilmaus a<b<c ei tarkoita mitään eikä sitä tule käyttää,sillä a<b palauttaa bool-tyypin arvon, joka on true tai false ja sen vertaaminen arvoon c ei ole mielekästä.

Tyyppimuunnoksissa kannattaa kiinnittää huomiota erityisesti jakolaskuun: esimerkiksi 5/2 antaa tulokseksi 2, josmuuttujien tyyppeinä on int, ja 5.0/2 antaa 2.5. Tarvittaessa kääntäjä korottaa int-tyypin muuttujan arvon laskuo-peraation ajaksi double-tyypin arvoksi ja char-tyypin arvon int-tyypin arvoksi, jotta laskussa ei menetetä informaa-tiota. Käytännössä tämä huomataan vaikkapa Celcius-Fahrenheit-konversiossa

double celcius = 0 ;double fahrenheit = 0 ;cin >> celcius ;fahrenheit = 9 . 0 / 5 *celcius + 3 2 ;

jossa on syytä havaita luku 9.0 yläkerrassa (double-tyyppiä).

3.4 Lausekkeet, ehtolauseet ja toistorakenteet

Olemme jo tutustuneet ilmaisulausekkeeseen eli ilmaisuun, jonka perään on laitettu puolipiste. Katsotaan lisäksi hiemanvalinta- ja ehtolauseita (if ja switch) sekä toistorakenteita (while ja for). Näiden avulla saadaan runsaasti lisäätoiminnallisuutta ohjelmiin.

3.4.1 Ehtolauseet

If-lausetta käytetään, kun halutaan valita useasta eri vaihtoehdosta. Lause on rakenteeltaan

if (ilmaus ) lauseke else lauseke

Katsotaan esimerkkinä ohjelma, joka muuntaa valuuttoja toisiksi valuutoiksi.

3.4.2 Esimerkki: Valuutan muuntaminen

21

Page 26: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

valuuttamuunnin.cpp

1 / * ========================================================================== * /2 / * * /3 / * v a l u u t t a m u u n n i n . cpp * /4 / * ( c ) 2011 Riku * /5 / * * /6 / * D e s c r i p t i o n * /7 / * muuntaan d o l l a r e i t a , p u n t i a j a r u o t s i n k r u u n u j a e u r o i k s i * /8 / * ========================================================================== * /9

10 #include "../std_lib_facilities.h"

11

12 int main ( )13 {14 / / m ä ä r i t e l l ä ä n v a l u u t t a k u r s s i t , v a k i o i t a15 const double dollar_euro = 0 . 7 2 1 ;16 const double pound_euro = 1 . 1 7 7 ;17 const double krona_euro = 0 . 1 1 4 ;18 double rahamaara = 0 ;19 char rahayksikko = ' ' ;20 / / k y s y t ä ä n k ä y t t ä j ä l t ä r ahamää rä j a y k s i k k ö21 cout << "\n[Valuuttamuunnin]\n\n"

22 << "Ohjelma muuntaa rahasumman euroiksi. Kirjoita ruudulle"

23 << " raham\x84\x84r\x84 ja\nsen j\x84lkeen yksikk\x94"

24 << " eli jokin seuraavista:\n"

25 << "\n d == USA:n dollari\n"

26 << " k == Ruotsin kruunu\n"

27 << " p == Englannin punta\n"

28 << "\n>> " ;29 cin >> rahamaara >> rahayksikko ;30 / / v a l i n t a l a u s e j a muunnokset31 if (rahayksikko == 'd' )32 cout << "\n" << rahamaara << " USA:n dollaria on yhteens\x84 "

33 << dollar_euro*rahamaara34 << " euroa.\n" ;35 else if (rahayksikko == 'k' )36 cout << "\n" << rahamaara << " Ruotsin kruunua on yhteens\x84 "

37 << krona_euro*rahamaara38 << " euroa.\n" ;39 else if (rahayksikko == 'p' )40 cout << "\n" << rahamaara << " Englannin puntaa on yhteens\x84 "

41 << pound_euro*rahamaara42 << " euroa.\n" ;43 else44 cout << "\nKirjoitit yksik\x94n, jota en tunnista" ;45 }

Ohjelma muuntaa USA:n dollareita, Englannin puntia sekä Ruotsin kruunuja Euroihin. Koodin alussa määritetään vakioi-na muunnoskertoimet dollareista euroihin (dollar_euro), punnista euroihin sekä kruunuista euroihin. Lisäksi määri-

22

Page 27: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

tellään muunnettava rahamäärä sekä kirjaimet, jotka kuvaavat valuuttoja. Kirjain merkitään yksittäisten lainausmerkkien’ ’ sisään (alussa tyhjä arvo).

Tulostetaan kehote ja luetaan käyttäjältä muunnettava määrä sekä yksikkö. Jaetaan mahdolliset tapauksen erilaisiin if-lauseisiin käyttäjän syöttämän yksikön mukaan. Huomaa, että yhtäsuuruusmerkkinä on kaksi tavallista yhtäsuuruusmerk-kiä ja käyttäjän syöttämä kirjain tulee yksittäisten lainausmerkkien sisään. Käytetään else-rakenteen lauseen paikallauutta if-lausetta, jolloin muodostuu sisäkkäisten if-lauseiden rakenne: ohjelma tarkistaa, onko ensimmäinen voimassa,jos ei niin sitten siirtyy aina seuraavaan. Jos käyttäjä syötti jonkin muun yksikön kuin jonkin annetuista, niin viimeinenelse-lause tulostaa ruudulle ilmoituksen siitä, että muunto ei tällä kerralla onnistunut.

Huomio. Jos if-rakenteen ”sisällä” on useita eri lausekkeita, tulee ne laittaa samaan blokkiin seuraavasti:

if (ehto ) {lause1 ;lause2 ;lause3 ;. . .. . .}

Jos blokki unohtuu, niin ehto koskee vain ensimmäistä lauseketta ja loput lausekkeet suoritetaan tarkas-tamatta, onko ehto voimassa. Sama blokkisääntö pätee myös muille vastaavantyyppisille rakenteille (mm.while- ja for-lauseet).

if-lauseen sijaan voidaan käyttää joissakin tapauksissa switch-lausetta, jossa muuttujan mahdolliset arvot käsitelläänselkeästi erillisinä tapauksina. Joskus switch voi auttaa selventäämään koodia paremmin kuin if-lause, sillä se onrakenteeltaan seuraavanlainen:

switch (muuttuja )case case_label_1 :lauseke ;. . .lauseke ;break ;

case case_label_2 :lauseke ;. . . ;break ;. . .

case case_label_n :lauseke ;. . . ;break ;

default ; / / j o s e i o l l u t mikään c a s e n i i n s i t t e n tämä v a i h t o e h t olauseke ;. . . ;break ;

Switch-lauseen jokainen case pitää aina lopettaa lausekkeeseen break;, jotta lausee suoritus päättyy ja palataantakaisin pääohjelmaan. Katsotaan äsken esitetty valuuttaamuunnin switch-muodossa, jotta lauseen käyttö ilmenee pa-remmin. Lisätään ohjelman käyttäjälle mahdollisuus muuntaa myös Japanin jenejä euroiksi.

23

Page 28: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

3.4.3 Esimerkki: valuutan muuntaminen, osa 2

valuuttamuunnin2.cpp

1 / * ========================================================================== * /2 / * * /3 / * v a l u u t t a m u u n n i n 2 . cpp * /4 / * ( c ) 2011 Riku * /5 / * * /6 / * D e s c r i p t i o n * /7 / * muuntaa j e n e j ä , d o l l a r e i t a , p u n t i a j a r u o t s i n k r u u n u j a e u r o i k s i ,8 swi t ch−l a u s e * /9 / * ========================================================================== * /

10

11 #include "../std_lib_facilities.h"

12

13 int main ( )14 {15 / / m ä ä r i t e l l ä ä n v a l u u t t a k u r s s i t , v a k i o i t a16 const double dollar_euro = 0 . 7 2 1 ;17 const double pound_euro = 1 . 1 7 7 ;18 const double krona_euro = 0 . 1 1 4 ;19 const double yen_euro = 0 . 0 0 9 ;20 double rahamaara = 0 ;21 char rahayksikko = ' ' ;22 / / k y s y t ä ä n k ä y t t ä j ä l t ä r ahamää rä j a y k s i k k ö23 cout << "\n[Valuuttamuunnin]\n\n"

24 << "Ohjelma muuntaa rahasumman euroiksi. Kirjoita ruudulle"

25 << " raham\x84\x84r\x84 ja\nsen j\x84lkeen yksikk\x94"

26 << " eli jokin seuraavista:\n"

27 << "\n d == USA:n dollari\n"

28 << " k == Ruotsin kruunu\n"

29 << " p == Englannin punta\n"

30 << " y == Japanin jeni\n"

31 << "\n >> " ;32 cin >> rahamaara >> rahayksikko ;33 / / sw i t ch−l a u s e j a muunnokset34 switch (rahayksikko ) {35 case 'd' :36 cout << "\n" << rahamaara << " USA:n dollaria on yhteens\x84 "

37 << dollar_euro*rahamaara << " euroa.\n" ;38 break ;39 case 'k' :40 cout << "\n" << rahamaara << " Ruotsin kruunua on yhteens\x84 "

41 << krona_euro*rahamaara << " euroa.\n" ;42 break ;43 case 'p' :44 cout << "\n" << rahamaara << " Englannin puntaa on yhteens\x84 "

45 << pound_euro*rahamaara << " euroa.\n" ;46 break ;

24

Page 29: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

47 case 'y' :48 cout << "\n" << rahamaara << " Japanin jeni\x84 on yhteens\x84 "

49 << yen_euro*rahamaara << " euroa.\n" ;50 break ;51 default :52 cout << "\nKirjoitit yksik\x94n, jota en tunnista" ;53 break ;54 }55 }

Ohjelman looginen rakenne on hyvin pitkälti identtinen if-lauseella tehdyn ohjelman kanssa. Muutama yksityiskohtatulee kuitenkin huomioida.

• Switch-lauseen muuttujan arvon tulee (tässä vaiheessa oppimista) olla joko tyyppiä int tai char, ts. se ei voiolla esimerkiksi string-tyyppiä.

• Case labelien tulee olla vakioita, muuttujia ei saa käyttää. Yhdelle tapaukselle voidaan käyttää useampia caselabeleita (vaikkapa parilliset luvut jostakin lukujoukosta).

• Jokainen case päättyy break;-lausekkeeseen.

3.4.4 Toistorakenteet

Kun jokin asia toistetaan useita kertoja pienillä muutoksilla, voidaan käyttää valmiita ohjelmointikielen rakenteita sensijaan, että kirjoitettaisiin hirveä määrä samanlaista koodia koodin perään. Toistorakenteita (repetition) ovat while- jafor-lauseet, ja toistoa varten tarvitaan

• looppi (loop), mitä toistetaan

• looppimuuttuja (loop/control variable), joka pitää kirjaa siitä, montako kertaa looppi on käyty läpi

• looppimuuttujan alkuarvo (initialization value)

• loopin lopettamisehto (termination criterion), esimerkiksi looppimuuttujan jokin maksimiarvo.

while-lausetta toistetaan niin kauan, kun looppimuuttujaan liittyvä alkuehto on voimassa. Tässä kannattaa olla tarkka-na, sillä monta kertaa kone on saatu jumiin ”ikuisella while-loopilla”. Komentoriviohjelman toiminnan saa Window-sissa lopetettua painamalla Ctrl-C, jos näin käy. Tarkastellaan yksinkertaista while-looppia, jossa tulostetaan ruudullekirjaimia ja niitä vastaavia numeroarvoja.

3.4.5 Esimerkki: aakkosten tulostus ruudulle, osa 1

kirjaintaulukko.cpp

1 / * ========================================================================== * /2 / * * /3 / * k i r j a i n t a u l u k k o . cpp * /4 / * ( c ) 2011 Riku J ä r v i n e n * /5 / * * /

25

Page 30: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

6 / * D e s c r i p t i o n * /7 / * t u l o s t a a k i r j a i m i a j a n i i t ä v a s t a a v i a i n d e k s e j ä t a u l u k k o o n * /8 / * ========================================================================== * /9

10 #include "../std_lib_facilities.h"

11

12 int main ( )13 {14 int i = 0 ; / / l o o p p i m u u t t u j a n a l u s t u s15 while (i<26) { / / l o o p p i e h t o j a b l o k i n a l o i t u s16 cout << char ('a'+i ) << '\t' << int ('a'+i ) << "\n" ; / / c h a r ( ' a ' + 1 ) =b j n e .17 ++i ; / / l o o p p i m u u t t u j a n k a s v a t t a m i n e n y h d e l l ä18 }19 }

Huomaa, kuinka ohjelmassa otetaan char-arvo eli merkki annetun indeksin mukaan eli char(’a’+i) ja vastaavallatavalla int-arvo int(’a’+1). Käydään läpi yhteensä 26 aakkosta, aloittaen kirjaimesta a ja tulostetaan kirjain jaindeksi ruudulle. Rakenteen lopussa kasvatetaan looppimuuttujaa i yhdellä kirjoittamalla ++i;.

while-lauseen ohella voidaan käyttää for-lausetta, jossa while-rakenteesta poiketen kontrollimuuttujan (looppimuut-tujan) hallinta on sijoitettu heti for-sanan jälkeen. for-lause on aina yhtäpitävä jonkin while-lauseen kanssa, eli onolemassa while-lause siten, että täysin sama asia voidaan sanoa myös sen kautta. for-lauseen käyttö on järkeväälähinnä yksinkertaisissa ja selkeissä rakenteissa. Kirjoitetaan edellinen kirjaintaulukkoesimerkki nyt käyttämällä for-lausetta.

3.4.6 Esimerkki: aakkosten tulostus ruudulle, osa 2

kirjaintaulukko2.cpp

1 / * ========================================================================== * /2 / * * /3 / * k i r j a i n t a u l u k k o 2 . cpp * /4 / * ( c ) 2011 Riku J ä r v i n e n * /5 / * * /6 / * D e s c r i p t i o n * /7 / * t u l o s t a a k i r j a i m i a j a n i i t ä v a s t a a v i a i n d e k s e j ä t au lukkoon , f o r−l a u s e * /8 / * l i s ä k s i i s o t k i r j a i m e t j a numerot 1−9. * /9 / * ========================================================================== * /

10

11 #include "../std_lib_facilities.h"

12

13 int main ( )14 {15 for (int i=0; i<26; ++i ) / / l o o p p i e h t o j a b l o k i n a l o i t u s16 cout << char ('a'+i ) << '\t' << int ('a'+i ) << "\n" ;17 / / l a i t e t a a n y k s i r i v i v ä l i ä ennen i s o j a k i r j a i m i a18 cout << "\n" ;19 for (int i=0; i<26; ++i ) / / l o o p p i e h t o j a b l o k i n a l o i t u s20 cout << char ('A'+i ) << '\t' << int ('A'+i ) << "\n" ; / / c h a r ( 'A ' + 1 ) =b j n e

26

Page 31: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

21 cout << "\n" ;22 for (int i=0; i<9; ++i )23 cout << char ('1'+i ) << '\t' << int ('1'+i ) << "\n" ;24 }

for-lauseen toistojen määrä ja rakenne ilmoitetaan argumenttina tavallisten sulkujen sisällä. Looppimuuttujan alus-tus, loopin lopetuskriteeri sekä looppimuuttujan kasvattaminen erotetaan toisistaan puolipisteillä tavalliseen tapaan. For-lauseen rakenne toistetaan ainoastaan ensimmäiselle lausekkeelle, joka rakennetta seuraa, tai koko seuraavalle blokille,jos sellainen on olemassa (rajattu kaarisuluilla).

Testaa ohjelman toimintaa käytännössä. Huomaat, että kirjaimien ja numeroiden viereen tulostuvat luvut ovat indeksiar-voja: jokaista char-tyypin muuttujaa eli merkkiä vastaa jokin numeerinen indeksi, jonka perusteella merkki voidaantunnistaa yksikäsitteisesti, kun käytettävä merkistö on tunnettu. Koska char on kooltaan vain yhden tavun, niin erilaisiamerkkejä voidaan sen avulla esittää yhteensä 256 kappaletta. Tästä syystä monet erikoismerkit, kuten mm. skandinaavisetkirjaimet, aiheuttavat ongelmia joissakin sovelluksissa.

3.5 Funktiot

Funktio on nimetty ja järjestetty joukko lausekkeita, jotka yhdessä toteuttavat jonkin loogisen operaation. Funktio voiesimerkiksi laskea annettujen lukujen perusteella arvon ja palauttaa tuloksen (korkeintaan yhden ja tietyn tyyppisen)pääohjelmalle. Esimerkiksi funktio

int toinenpotenssifunktio (int x ) {return x*x ; }

laskee annetun kokonaisluvun x neliön. Tässä tapauksessa funktion käyttö eli kutsuminen tapahtuu kirjoittamalla

toinenpotenssifunktio (luku )

sopivaan osaan koodia. Kutsu toimii kuten sen paikalle olisi kirjoitettu vastaava kokonaisluku. Voidaan vaikkapa kirjoit-taa summauslauseke

int a = 0 ;int b = 3 ;int a += toinenpotenssifunktio (b ) ;cout << a << "\n" ;

Edellinen tulostaa ruudulle arvon 9. Yleisesti ottaen funktion kielioppi eli syntaksi voidaan kirjoittaa seuraavasti:

tyyppi nimi (parametrilista ) {funktiorunko}

Parametrilistaan tulevat ne argumentit, jotka funktiolle pitää antaa, jotta se voi tehdä tehtävänsä. Kaikki tarvittavat ar-gumentit on annettava ja lisäksi niiden tulee olla oikeaa tyyppiä, muuten kääntäjä ilmoittaa virheestä. Parametrilista voiolla myös tyhjä.

Funktio, joka ei palauta mitään, on tyyppiä void. Esimerkiksi

void kirjoita_joitain ( ) {cout << "Jotain\n" ; }

kirjoittaa ruudulle sanan Jotain ja vaihtaa riviä, kun funktiota kutsutaan.

Miksi funktioita käytetään? Tähän on olemassa useita hyviä syitä, jotka tulevat ilmi vasta sitten, kun ohjelmoinnista onenemmän kokemusta. Listataan näistä muutamia.

27

Page 32: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

• Usein toistuvat operaatiot kirjoitetaan lyhyemmin, jolloin koodi on selvempää ja luettavampaa. Tämä säästää aikaaja vaivaa, jos ja kun virheitä ilmenee.

• Funktion kuvaileva nimi tekee koodista ymmärrettävämpää. Esimerkiksi standardikirjaston funktio sqrt() las-kee luvun neliöjuuren ja se on aika paljon helpompi huomata tekstin seasta kuin iso kasa koodia, jossa selitetäänitse laskualgoritmia.

• Funktioiden käyttö parantaa tekstin rakennetta ja helpottaa sen hahmottamista, kun erityyppiset loogiset operaatioton määritelty toisistaan selvästi erilleen.

Hyvä funktio tekee loogisesti yhden asian eli vaikkapa joko laskee tai tulostaa tai jotain muuta. Se ei tee kaikkia näitäasioita, vain yhden. Monimutkainen ja epälooginen funktio aiheuttaa vain sekaannusta, vaatii oman dokumentaationsaeik selvennä koodin rakennetta (tämä oli funktion käytön idea alun perin. . . ).

Funktiorungon tarkastelu ei useinkaan ole tarpeen, jos tiedämme, minkä toimenpiteen funktio suorittaa. Jotta funktioitavoidaan käyttää koodissa, ei niiden täydellisiä määritelmiä tarvitse aina kirjoittaa uudestaan koodin sekaan näkyviin,vaan voidaan käyttää funktiodeklaraatioita (declaration), jotka ovat muotoa

int square (int ) ;

Puolipiste päättää deklaraation. Kun funktio otetaan käyttöön, voi koodin alkuun yksinkertaisesti kirjoittaa

#include int s q u a r e (int ) ;

Varsinainen funktion toiminnallisuus voi olla määritelty kirjoitettavan koodin ulkopuolella (esimerkiksi standardikirjas-ton funktiot). Huomaa tässä deklaraation ja määritelmän (definition) ero: ensimmäinen ei sisällä yksityiskohtaista tietoafunktion rungosta. Deklaraation etu laajoissa ohjelmissa on se, että suuri osa epäoleellisesta koodista voidaan pitää poissanäkyvistä keskityttäessä johonkin oleelliseen .

3.6 Vektorit

Monissa mielekkäissä ohjelmissa tietoa kysytään käyttäjältä ja tallennetaan myöhempää käyttöä varten. Tieto tallenne-taan objekteihin koneen muistiin, ja yksi tällaisista tiedon varastoista on nimeltään vektori (vector). Vektoriin syötetäänlukuja ja se voidaan ajatella ikään kuin taulukon yhtenä rivinä, jossa luvut ovat eri sarakkeissa. Esimerkiksi kokonaislu-kuvektori voidaan kirjoittaa näin:

vector<int> vektori ( 3 ) ;vektori [ 0 ] = 2 ;vektori [ 1 ] = 6 ;vektori [ 2 ] = −29;

Vektorissa vektori on kolme elementtiä ja ne ovat int-tyyppiä. Indeksointi alkaa nollasta. Huomaa, että tyyppi mer-kitään kulmasuluilla <> ja vektorin elementin numero hakasuluilla []. Kun vektorille syötetään tietoa, pitää aina käyttääoikeaa tyyppiä ja viitata jo olemassa olevaan vektorin indeksiin (muuten tulee ”mystinen” Range Error, joka viittaasiihen, että mentiin vahingossa vektorin määrittelyalueen ulkopuolelle). Vektorin voi alustaa myös kirjoittamalla

vector<string> merkkijonovektori ( 2 ,tyhja ) ;

Edellinen laittaa jokaisen elementin alkuarvoksi merkkijonon ”tyhja” ja elementtejä on vektorissa yhteensä kaksi. Vekto-riin tallentuu tieto vektorin koosta (kuinka monta elementtiä se sisältää), elementtien tyypistä sekä elementtien sisällöstä.

28

Page 33: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

Vektoria voi kasvattaa eli sen loppuun voi lisätä tarvittaessa uusia elementtejä. Tämä on tyypillistä, sillä usein ei etu-käteen tiedetä, kuinka monta dataelementtiä yhteensä tulee olemaan, vaikkapa fysikaalisessa mittauksessa. Kirjoitetaanseuraavaa:

vector<double> numerodataa ; / / e i m ä ä r i t ä kokoa , v a i n t y y p i n !numerodataa .push_back ( 3 . 4 ) ; / / l i s ä ä e l e m e n t i n , a rvo 3 . 4 , i n d e k s i [ 0 ]numerodataa .push_back (−8.3) ; / / l i s ä ä e l e m e n t i n , a rvo −8.3 , i n d e k s i [ 1 ]

Funktio push_back() sijoittaa elementin vektorin loppuun. Sitä sanotaan vektorin jäsenfunktioksi (member func-tion) ja sen kutsuminen tapahtuu pistenotaatiolla eli numerodataa.push_back(arvo);. Yleisesti jäsenfunktioi-den käytön syntaksi on muotoa

objektin_nimi .jäsenfunktion_nimi (argumentit )

Muita vektorin jäsenfunktioita ovat mm. seuraavat:

• size(), joka kertoo vektorin koon eli elementtien lukumäärän

• begin(), joka viittaa vektorin ensimmäiseen elementtiin

• end(), joka viittaa vektorin viimeiseen elementtiin

• at(), joka kertoo vektorin elementin sijainnin

Täydellinen lista jäsenfunktioista löytyy helposti netistä, kun etsii tietoa C++:n vektoreista.

begin()- ja end()-funktioiden käyttö on näppärää esimerkiksi algoritmin sort() kanssa, jolla voidaan järjestäävektorin elementit:

vector<int> vektori ( 2 ) ;vektori [ 0 ] = 4 ;vektori [ 1 ] = −2;sort (vektori .begin ( ) ,vektori .end ( ) ) ; / / p i en immäs t ä suur impaan

sort()-algoritmi on osa standardikirjastoa. Se järjestää luvut suuruusjärjestykseen pienimmästä suurimpaan ja esimer-kiksi merkkijonot aakkosjärjestykseen.

Katsotaan vektorin käyttöä parin esimerkin kautta. Ensimmäisessä pyydetään käyttäjää syöttämään lämpötiloja ja laske-taa niiden mediaani ja jälkimmäisessä sovelletaan sort()-algoritmia sensuroimaan epämukavia sanoja.

3.6.1 Esimerkki: Lämpötilojen mediaanin laskeminen

lampotilamediaani.cpp

1 / * ========================================================================== * /2 / * * /3 / * l a m p o t i l a m e d i a a n i . cpp * /4 / * ( c ) 2011 Riku * /5 / * * /6 / * D e s c r i p t i o n * /7 / * Laskee k i r j o i t e t t u j e n l ä m p ö t i l o j e n med iaan in matem . määr . m u k a i s e s t i * /8 / * ========================================================================== * /9

29

Page 34: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

10 #include "../std_lib_facilities.h"

11

12 int main ( )13 {14 vector<double> temps ; / / l ä m p ö t i l a v e k t o r i15 double temp ;16 cout << "Kirjoita l\x84mp\x94tiloja, muu kuin luku lopettaa. \n" ;17 while (cin>>temp ) / / l o o p p i p ä ä t t y y kun s y ö t e t ä ä n muuta ku in luku18 temps .push_back (temp ) ; / / k i r j o i t e t u t l ä m p ö t i l a t t a l t e e n v e k t o r i i n19 sort (temps .begin ( ) ,temps .end ( ) ) ; / / l ä m p ö t i l a t s u u r u u s j ä r j e s t y k s e e n20 if (temps .size ( ) %2 == 0) / / j o s l ä m p ö t i l o j a on p a r i l l i n e n määrä21 cout << "Mediaani on "

22 << 0 . 5 * (temps [temps .size ( ) /2−1]+temps [temps .size ( ) / 2 ] ) << endl ;23 if (temps .size ( ) %2 == 1) / / j o s l ä m p ö t i l o j a on p a r i t o n määrä24 cout << "Mediaani on "

25 << temps [temps .size ( ) / 2 ] << endl ; / / p y ö r i s t ä ä a l a s p ä i n , ok .26 }

Koodin alussa määritellään lämpötilavektori temps, johon käyttäjä lisää lämpötiloja while-loopin kautta. Kun käyttäjäkirjoittaa lämpötilan temp, niin jäsenfunktio push_back(temp) lisää sen vektorin temps viimeiseksi elementiksi.while-looppi katkeaa, kun käyttäjä ei enää syötä lukuja vaan jotain muuta.

Lämpötilat järjestää pienimmästä suurimpaan sort. Mediaania varten tarkastelemme if-lauseen avulla kaksi eri ta-pausta:

• Jos annettuja lukuja on parillinen määrä, niin mediaani on järjestetyn joukon kahden keskimmäisen luvun keskiar-vo.

• Jos lukuja on pariton määrä, niin mediaani on järjestetyn joukon keskimmäinen luku.

Parillisuus testataan ottamalla vektorin koon ja luvun 2 jakojäännös. Mikäli se on nolla, niin vektorissa on parillinenmäärä elementtejä; vastaavasti arvo 1 kuvaa paritonta määrää. Huomaa, että if-lauseen jälkeen ei tarvita blokkimerkintää(kaarisulkuja), sillä ehdon jälkeen tulostetaan vain yksi (vaikkakin kahden rivin mittainen) cout-lauseke.

3.6.2 Esimerkki: Epämukavien sanojen sensurointi

epamukavatsanat.cpp

1 / * ========================================================================== * /2 / * * /3 / * e p a m u k a v a t s a n a t . cpp * /4 / * ( c ) 2011 Riku J ä r v i n e n * /5 / * * /6 / * D e s c r i p t i o n * /7 / * t u l o s t a a VIRHE , kun k ä y t t ä j ä s y ö t t ä ä sanan , j o k a on ns . m u s t a l l a l i s t a l l a8 * /9 / * ========================================================================== * /

10

11 #include "../std_lib_facilities.h"

12

30

Page 35: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

13 int main ( )14 {15 / * s a n a l i s t a e p ä m u k a v i s t a s a n o i s t a , m ä ä r i t e l l ä ä n v e k t o r i n a * /16 vector<string> epamukaviasanoja ( 5 ) ;17 epamukaviasanoja [ 0 ] = "ankka" ;18 epamukaviasanoja [ 1 ] = "kala" ;19 epamukaviasanoja [ 2 ] = "auto" ;20 epamukaviasanoja [ 3 ] = "lentokone" ;21 epamukaviasanoja [ 4 ] = "simulaattori" ;22 vector<string> sanoja ; / / m ä ä r i t t e l e e v e k t o r i n n i m e l t ä s a n o j a23 string sana ;24 cout << "Kirjoita ruudulle sanoja tyhj\x84ll\x84 v\x84lill\x84 erotettuina."

25 << " Kun olet kirjoittanut kaikki haluamasi sanat, paina Enter, Ctrl-Z"

26 << " ja Enter.\n" ;27 while (cin>>sana ) / / l o o p p i l i s ä ä s y ö t e t y t s a n a t v e k t o r i i n28 sanoja .push_back (sana ) ;29 sort (sanoja .begin ( ) ,sanoja .end ( ) ) ; / / j ä r j e s t ä ä s y ö t e t y t sanan a a k k o s j ä r j .30 cout << "\n" ;31 for (int i=0; i<sanoja .size ( ) ; ++i ) / / käy l ä p i s a n a v e k t o r i n32 / * kahden i f−l a u s e e n rakenne , j o k a t a r k a s t a a e n s i n s a n o j e n s a m a n l a i s u u d e n j a33 v i e l ä e r i k s e e n sen , onko sana mikaan v e k t o r i n e p a m u k a v i a s a n o j a s a n o i s t a * /34 if (i==0 | | sanoja [i−1]!=sanoja [i ] ) / / p o i s t a a t o i s t e t u t s a n a t35 if (sanoja [i ] == epamukaviasanoja .at ( 0 ) | |36 sanoja [i ] == epamukaviasanoja .at ( 1 ) | |37 sanoja [i ] == epamukaviasanoja .at ( 2 ) | |38 sanoja [i ] == epamukaviasanoja .at ( 3 ) | |39 sanoja [i ] == epamukaviasanoja .at ( 4 ) )40 cout << "VIRHE" << "\n" ;41 else42 cout << sanoja [i ] << "\n" ;43 }

Alussa tehdään sanalista epämukavista sanoista, joka määritellään vektorina epamukaviasanoja. Lisäksi määritel-lään toinen vektori sanoja, johon tallennetaan käyttäjän syöttämät sanat. sort järjestää käyttäjän syöttämät sanataakkosjärjestykseen, jonka jälkeen sanat käydään läpi for-lauseella.

Ensimmäinen if-lause pitää huolen siitä, että tulostetaan vain kerran useaan otteeseen esiintynyt sana. Toisessa if-lauseessa määritellään tulostukseksi sana VIRHE, mikäli läpikäytävä sana on jokin alussa annetuista epämukavista sa-noista. Muussa tapauksessa (else-rakenne) tulostetaan annettu sana ruudulle ja laitetaan perään rivinvaihto.

3.7 Esimerkkejä lauserakenteista ja vektoreista

Tämä osio sisältää muutamia harjoituksia Stroustrupin kirjan pohjalta. Alkuperäisiin tehtävänantoihin nähden esimerk-kejä voi olla jonkin verran muunneltu ja täydennetty. Koodeja ei ole (ainakaan vielä) kommentoitu koodi-ikkunan ulko-puolella.

Kaikki koodit toimivat Windows-ympäristöissä MinGW:n 32-bittiselle tehdyllä kääntäjällä.

31

Page 36: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

3.7.1 Esimerkki: Matkan pituuden laskeminen

matkanpituus.cpp

1 / * ========================================================================== * /2 / * * /3 / * ex4_3 . cpp * /4 / * ( c ) 2011 Riku * /5 / * * /6 / * D e s c r i p t i o n * /7 / * m ä ä r i t t ä ä e t a p p i e n v ä l i s i ä e t ä i s y y k s i ä j a koko matkan p i t u u d e n . * /8 / * ========================================================================== * /9

10 #include "../std_lib_facilities.h"

11

12 int main ( )13 {14 vector<double> etaisyydet ;15 double etaisyys = 0 ;16 cout << "Kerro matkan etappien et\x84isyydet (km), niin lasken matkan"

17 << " pituuden.\nJokin muu kuin numero lopettaa.\n" ;18 while (cin >> etaisyys )19 etaisyydet .push_back (etaisyys ) ; / / l u e t a a n e t ä i s y y d e t v e k t o r i i n20 double summa = 0 ; / / m ä ä r i t e l l ä ä n summa , johon e t ä i s y y d e t l a i t e t a a n21 for (int i=0;i<etaisyydet .size ( ) ;++i ) / / käydään v e k t o r i l ä p i22 summa += etaisyydet [i ] ; / / l i s ä t ä ä n e t ä i s y y s summaan23 cout << "Koko matkan pituus on " << summa << " km.\n" ;24 double pienin = 10000 ; / / ä l y t t ö m ä n i s o luku , j o k a v a r m a s t i muut tuu25 double suurin = 0 ; / / ä l y t t ö m ä n p i e n i luku , j o k a v a r m a s t i muut tuu26 for (int j=0;j<etaisyydet .size ( ) ;++j ) / / e t s i t ä ä n ä ä r i a r v o t27 { / / b l o k k i , j o t t a k a i k k i l a u s e e t t u l e v a t h u o m i o i d u i k s i28 if (etaisyydet [j ] < pienin )29 pienin = etaisyydet [j ] ;30 if (etaisyydet [j ] > suurin )31 suurin = etaisyydet [j ] ;32 }33 cout << "Pisimm\x84n etapin pituus on " << suurin << " km\n" ;34 cout << "Lyhyimm\x84n etapin pituus on " << pienin << " km\n" ;35 }

3.7.2 Esimerkki: Yksinkertainen laskinohjelma

laskinohjelma.cpp

1 / * ========================================================================== * /2 / * * /3 / * l a s k i n o h j e l m a . cpp * /4 / * ( c ) 4 . 5 . 2 0 1 1 Riku J ä r v i n e n * /5 / * * /

32

Page 37: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

6 / * D e s c r i p t i o n * /7 / * Lask inoh j e lma , j o k a l a s k e e p e r u s l a s k u t o i m i t u k s e t k a h d e l l e l u v u l l e * /8 / * ========================================================================== * /9

10 #include "../std_lib_facilities.h"

11

12 int main ( )13 {14 / / o t s i k k o o h j e l m a l l e15 cout << "\n\n[LASKINOHJELMA]\n\n" ;16 / / k e h o t e k ä y t t ä j ä l l e17 cout << "Kirjoita ruudulle kaksi desimaalilukua ja jokin merkeist\x84 "

18 << "\n+, -, *, / tai %. Ohjelma laskee annettujen lukujen v\x84lisen"

19 << "\nlaskutoimituksen.\n\n"

20 << ">>" ;21 / / m ä ä r i t e l l ä ä n l u v u t22 double a , b ;23 char merkki ;24 / / l u e t a a n l u v u t25 cin >> a >> b >> merkki ;26 cout << "\n" ;27 / / t a r k a s t e l l a a n e r i t a p a u k s e t28 switch (merkki ) {29 case '+' :30 cout << "Lukujen " << a << " ja " << b << " summa on " << a+b << ".\n" ;31 break ;32 case '-' :33 cout << "Lukujen " << a << " ja " << b << " erotus on " << a−b << ".\n" ;34 break ;35 case '*' :36 cout << "Lukujen " << a << " ja " << b << " tulo on " << a*b << ".\n" ;37 break ;38 case '/' :39 cout << "Lukujen " << a << " ja " << b << " osam\x84\x84r\x84 on "

40 << a /b << ".\n" ;41 break ;42 case '%' :43 / / muu te t aan do ub l e i n t−t y y p p i i n moduloa v a r t e n44 int a_toint = a ;45 int b_toint = b ;46 cout << "Lukujen " << a_toint << " ja " << b_toint

47 << " jakoj\x84\x84nn\x94s on " << a_toint%b_toint << ".\n" ;48 break ;49 }50 }

3.7.3 Esimerkki: lukujen arvaaja

33

Page 38: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

arvaaja.cpp

1 / * ========================================================================== * /2 / * * /3 / * a r v a a j a . cpp * /4 / * ( c ) 2011 Riku * /5 / * * /6 / * D e s c r i p t i o n * /7 / * a r v a a numeron v ä l i l t ä 1−100 k y s y m ä l l ä kysymyks iä 7 k a p p a l e t t a * /8 / * ========================================================================== * /9

10 #include "../std_lib_facilities.h"

11

12 int main ( )13 {14 double numero = 5 0 ;15 char merkki = 'a' ;16 cout << "Ajattele jotakin lukua v\x84lilt\x84 1-100. Selvit\x84n, mit\x84"

17 << " numeroa ajattelet. \n" ;18 cout << "Onko ajattelemasi numero \n\nsuurempi kuin 50, \nyht\x84"

19 " suuri kuin 50, vai \npienempi kuin 50?\n\n"

20 << "Kirjoita\n\n + jos on suurempi tai yht\x84suuri"

21 << "\n - jos on pienempi\n = jos ajattelemasi numero on 50.\n\n" ;22 cin >> merkki ;23 while (true ) / / t a r v i t a a n , e t t ä b r e a k v o i l o p e t t a a l o o p i n kun luku l ö y t y y24 {25 if (merkki == '=' )26 {27 cout << "Ajattelit numeroa 50\n" ;28 break ;29 }30 if (merkki == '+' )31 numero = numero + 5 0 . 0 / 2 ; / / m u i s t e t a a n j a k o l a s k u s s a d e s i m a a l i p i l k k u32 if (merkki == '-' )33 numero = numero − 5 0 . 0 / 2 ;34 cout << "Onko ajattelemasi numero suurempi kuin "

35 << numero << "?\n" ;36 cout << "Kirjoita\n\n + jos on suurempi"

37 << "\n - jos ei ole\n" ;38 cin >> merkki ;39 if (merkki == '+' )40 numero = numero+ 5 0 . 0 / 4 ;41 if (merkki == '-' )42 numero = numero−5 0 . 0 / 4 ;43 cout << "Onko ajattelemasi numero suurempi kuin "

44 << numero << "?" ;45 cout << "\nKirjoita\n\n + jos on suurempi"

46 << "\n - jos ei ole\n" ;47 cin >> merkki ;48 if (merkki == '+' )49 numero = numero+ 5 0 . 0 / 8 ;

34

Page 39: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

50 if (merkki == '-' )51 numero = numero−5 0 . 0 / 8 ;52 cout << "Onko ajattelemasi numero suurempi kuin "

53 << numero << "?" ;54 cout << "\nKirjoita\n\n + jos on suurempi"

55 << "\n - jos ei ole\n" ;56 cin >> merkki ;57 if (merkki == '+' )58 numero = numero+ 5 0 . 0 / 1 6 ;59 if (merkki == '-' )60 numero = numero−5 0 . 0 / 1 6 ;61 cout << "Onko ajattelemasi numero suurempi kuin "

62 << numero << "?" ;63 cout << "\nKirjoita\n\n + jos on suurempi"

64 << "\n - jos ei ole\n" ;65 cin >> merkki ;66 if (merkki == '+' )67 numero = numero+ 5 0 . 0 / 3 2 ;68 if (merkki == '-' )69 numero = numero−5 0 . 0 / 3 2 ;70 cout << "Onko ajattelemasi numero suurempi kuin "

71 << numero << "?" ;72 cout << "\nKirjoita\n\n + jos on suurempi"

73 << "\n - jos ei ole\n" ;74 cin >> merkki ;75 if (merkki == '+' )76 numero = numero+ 5 0 . 0 / 6 4 ;77 if (merkki == '-' )78 numero = numero−5 0 . 0 / 6 4 ;79 cout << "Onko ajattelemasi numero suurempi kuin "

80 << numero << "?" ;81 cout << "\nKirjoita\n\n + jos on suurempi"

82 << "\n - jos ei ole\n" ;83 cin >> merkki ;84 if (merkki == '+' )85 numero = numero+ 5 0 . 0 / 1 2 8 ;86 if (merkki == '-' )87 numero = numero−5 0 . 0 / 1 2 8 ;88 / / m ä ä r i t e t ä ä n l o p u l l i n e n numero k o k o n a i s l u k u n a89 int kokonaislukuna_numero = numero ; / / m ä ä r i t e l l ä ä n numero ←↩

k o k o n a i s l u k u n a90 int lopullinen_numero = 0 ; / / a l u s t e t a a n l o p u l l i n e n t u l o s t e t t a v a ←↩

numero91 if (numero−kokonaislukuna_numero >= 0 . 5 ) / / p y ö r i s t y s y l ö s p ä i n92 lopullinen_numero = kokonaislukuna_numero+1;93 if (numero−kokonaislukuna_numero < 0 . 5 ) / / p y ö r i s t y s a l a s p ä i n94 lopullinen_numero = kokonaislukuna_numero ;95 cout << " Ajattelemasi numero on " << lopullinen_numero ;96 break ; / / l o p e t t a a w h i l e ( t r u e ) −l o o p i n97 }

35

Page 40: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

98 }

3.8 Kysymyksiä luvusta 3

1. Mikä on laskutoimitus (computation)?

2. Mitä tarkoittavat sisääntulo (input) ja ulostulo (output) laskutoimitukselle? Anna esimerkki.

3. Mitkä kolme asiaa ohjelmoijan on syytä pitää mielessä laskutoimituksia tehdessään?

4. Mitä ”expression” eli ilmaus tekee?

5. Mikä ero on ilmauksella (expression) ja lausekkeella (statement) monisteen perusteella?

6. Mikä on vakioilmaus (constant expression)?

7. Mikä on literaali (literal)?

8. Mitä operaattoreita voidaan käyttää kokonaisluvuille ja liukuluvuille?

9. Mitä operaattoreita voidaan käyttää kokonaisluvuille, mutta ei liukuluvuille?

10. Mitä operaatioita (joitakin niistä kaikista) voidaan käyttää string-tyypin muuttujille?

11. Milloin ohjelmoijan on syytä käyttää switch-lausetta if-lauseen sijaan?

12. Mitkä ovat tavallisimpia ongelmia/rajoituksia switch-lauseen käytön kanssa?

13. Mitä for-loopin argumentin eri osat tekevät ja missä järjestyksessä ne suoritetaan?

14. Milloin tulee käyttää for-looppia ja milloin while-looppia?

15. Kuinka tulostetaan merkin (char) numeerinen arvo?

16. Mitä tarkoittaa rivi char foo(int x) funktion määrittelyssä?

17. Milloin kannattaa määritellä erillinen funktio jollekin ohjelman osalle?

18. Mikä on vektorin kolmannen elementin indeksi?

19. Kuinka kirjoitetaan for-looppi, joka tulostaa jokaisen vektorin elementin?

20. Mitä tekee vector<char> alphabet(26); ?

21. Kuvaile, mitä push_back() tekee vektorille.

22. Mitä tekevät vektorin jäsenfunktiot begin(), end() ja size()?

23. Kuinka voit järjestää vektorin elementit?

36

Page 41: TI02 OhjelmointiTI02 Ohjelmointi 17. toukokuuta 2011 1 Hello, World! Aloitetaan opiskelu kirjoittamalla yksinkertainen C++-ohjelma nimeltä helloworld.cpp, joka tulostaa komentori-ville

TI02 Ohjelmointi 17. toukokuuta 2011

3.9 Tehtäviä luvusta 3

1. Kirjoita opintukilaskuri, joka kertoo, kuinka paljon tietyn ikäinen henkilö saa valtiolta opintotukea. Ohjelman tuleeottaa syötteinä seuraavat asiat:

• tuen saajan ikä

• asuuko tuen saaja kotona vai omassa asunnossaan

• jos oma asunto asunnon vuokra

Opintotuki koostuu opintorahasta ja asumislisästä. Valtion takaama opintolaina ei suoraan kuulu opintotukeen,eikä sitä tarvitse tässä huomioida. Ajan tasalla olevat tiedot opintotuen ja asumislisän suuruudesta saat KELAnnettisivuilta.

Yksinkertaisuuden vuoksi voidaan olettaa, että tuen saajalla ei ole lapsia, hänen asuntonsa vuokra on ”kohtuulli-nen” (saa tukena 80% vuokrasta) ja hänellä ei ole merkittäviä tuloja, jotka vaikuttaisivat opintotuen suuruuteen.

2. Toteuta luvun 3.7 lukuarvaaja-esimerkki for-lausetta käyttäen. (Vinkki: for-loopin sisällä tarvitset funktiota pow2,i,joka kuvaa kakkosen i:ttä potenssia, kun looppimuuttuja on i).

3. Tavallisella shakkilaudalla on 64 ruutua. Asetetaan riisinjyviä laudalle siten, että ensimmäiseen ruutuun tulee yksijyvä, toiseen kaksi, kolmanteen neljä ja niin edelleen. Kirjoita ohjelma, joka kysyy käyttäjältä täytettävien ruu-tujen lukumäärän ja tulostaa riisinjyvien yhteismäärän näissä ruuduissa. Selkeyden vuoksi kannattaa kirjoittaafor-looppi, jota pyöritetään käyttäjän syöttämään ruutumäärään asti ja tulostetaan ruudulle jokaisen käyntikerranjälkeen jyvien lukumäärä.

4. Mikäli käytit jyvien lukumäärälle int-tyyppiä, niin edellisessä ohjelmassa huomasit kenties sen, että 32. ruu-dun kohdalla ja sen jälkeen määrät eivät enää pidä paikkaansa, koska lukualue loppuu kesken. Kokeile muuttaaint→double ja testaa toimivuutta. Lisää ohjelma tulostamaan ruudulle ilmoitus siitä ruudusta, jossa jyvien koko-naismäärä ylittää 1000., 1000000. ja 1000000000. jyvän rajat.

5. Tee ohjelma, jolla voit pelata konetta vastaan Kivi, paperi, sakset -peliä. Yksinkertaisuuden vuoksi voit antaaohjelmalle arvot, joilla se vastaa käyttäjälle (aina samat arvot, esimerkiksi vektorissa). Jos haluat, niin voit myössyöttää koneelle arvot, joita se käyttää vastatessaan, mahdollisesti eri järjestyksessä kuin ne on syötetty. Ohjelmantulee ilmoittaa käyttäjälle pelin tulos jokaisen yrityksen jälkeen (voitto, tappio, häviö) lyhyellä tulosteella.

4 Bjarne Stroustrupin ajatuksia liittyen ohjelmointiin

Ohjelma pitää olla suunniteltu siten, että käyttäjän syöttämä virheellinen input ei aiheuta merkittäviä ongelmia (antaavirheilmoituksen tms.). Virheitä tosin käsitellään paremmin vasta seuraavassa luvussa.

ohjelmoinnin hyvyyttä ei mittaa mahdollisimman monimutkaisen koodin kirjoittaminen, vaan kyky kirjoittaa vaadituntyön tekevä ja mahdollisimman yksinkertainen koodi.

Tietokone on laite, jota voidaan ohjelmoida tekemään teoriassa millaisia laskutoimituksia tahansa (toimintaa ei ole en-nalta määrätty!). Kun tämä liitetään yhteen reaalimaailman laitteiden kanssa, saadaan laitteet tekemään teoriassa mitätahansa.

37