OHJ-1100 Ohjelmointi I



Samankaltaiset tiedostot
Java-kielen perusteet

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

Ohjelmoinnin perusteet Y Python

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

13. Loogiset operaatiot 13.1

Java-kielen perusteet

Ohjelmoinnin perusteet Y Python

Kääntäjän virheilmoituksia

Ohjelmoinnin perusteet Y Python

Java-kielen perusteita

ITKP102 Ohjelmointi 1 (6 op)

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

etunimi, sukunimi ja opiskelijanumero ja näillä

13. Loogiset operaatiot 13.1

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

Python-ohjelmointi Harjoitus 2

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

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

VIII. Osa. Liitteet. Liitteet Suoritusjärjestys Varatut sanat Binääri- ja heksamuoto

5. HelloWorld-ohjelma 5.1

Osoitin ja viittaus C++:ssa

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

12 Mallit (Templates)

11. Javan toistorakenteet 11.1

Ohjelmoinnin perusteet Y Python

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

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset


Ohjelmoinnin perusteet Y Python

5/20: Algoritmirakenteita III

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

Ehto- ja toistolauseet

Sisällys. 17. Ohjelmoinnin tekniikkaa. Aritmetiikkaa toisin merkiten. for-lause lyhemmin

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

Muuttujien roolit Kiintoarvo cin >> r;

Sisällys. 16. Ohjelmoinnin tekniikkaa. Aritmetiikkaa toisin merkiten. Aritmetiikkaa toisin merkiten

Ohjelmoinnin peruskurssi Y1

16. Ohjelmoinnin tekniikkaa 16.1

16. Ohjelmoinnin tekniikkaa 16.1

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

ITKP102 Ohjelmointi 1 (6 op)

3. Muuttujat ja operaatiot 3.1

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

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

Tutoriaaliläsnäoloista

OHJ-1101 Ohjelmointi 1e

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

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

12. Javan toistorakenteet 12.1

12. Javan toistorakenteet 12.1

Ohjelmoinnin perusteet Y Python

Apuja ohjelmointiin» Yleisiä virheitä

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

13 Operaattoreiden ylimäärittelyjä

Algoritmit. Ohjelman tekemisen hahmottamisessa käytetään

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet, syksy 2006

Ohjelmoinnin perusteet Y Python

Pythonin alkeet Syksy 2010 Pythonin perusteet: Ohjelmointi, skriptaus ja Python

C++ rautaisannos. Kolme tapaa sanoa, että tulostukseen käytetään standardikirjaston iostreamosassa määriteltyä, nimiavaruuden std oliota cout:

Python-ohjelmointi Harjoitus 5

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

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

1. luento. Ohjelmointi (C) T0004 Syksy luento. 1. luento. 1. luento. 1. luento. kurssin sisältö ja tavoitteet työmuodot.

5. HelloWorld-ohjelma 5.1

Ohjelmoinnin perusteet Y Python

LOAD R1, =2 Sijoitetaan rekisteriin R1 arvo 2. LOAD R1, 100

Vasen johto S AB ab ab esittää jäsennyspuun kasvattamista vasemmalta alkaen:

4. Lausekielinen ohjelmointi 4.1

Ohjelmoinnin peruskurssi Y1

Luento 5. Timo Savola. 28. huhtikuuta 2006

Harjoitus 3 (viikko 39)

811120P Diskreetit rakenteet

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

Ohjelmointiharjoituksia Arduino-ympäristössä

Harjoitus 2 (viikko 45)

Tähtitieteen käytännön menetelmiä Kevät 2009 Luento 4: Ohjelmointi, skriptaus ja Python

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

Ohjelmointi 1 Taulukot ja merkkijonot

Tietotyypit ja operaattorit

Ohjelmoinnin peruskurssi Y1

811120P Diskreetit rakenteet

Sisällys. 3. Muuttujat ja operaatiot. Muuttujat ja operaatiot. Muuttujat ja operaatiot

4. Lausekielinen ohjelmointi 4.1

Ohjelmoinnin perusteet Y Python

Ohjelmointi 1. Kumppanit

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

Pong-peli, vaihe Aliohjelman tekeminen. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana

Ohjelmoinnin perusteet Y Python

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

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

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

Johdatus Ohjelmointiin

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

C-ohjelmoinnin peruskurssi. Pasi Sarolahti

Zeon PDF Driver Trial

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

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

Tietueet. Tietueiden määrittely

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

Transkriptio:

OHJ-1100 Ohjelmointi I lukuvuosi 2012 2013 Luentomoniste Ari Suntioinen ari.suntioinen@tut.fi Sisällysluettelo Sisältö OHJ-1100 Ohjelmointi I Mitä on ohjelmointi?....................................... 1 Tietokoneen ohjelmointi..................................... 3 Harhaluulo ohjelmoinnista................................... 5 Oikea malli ohjelmoinnista................................... 7 Algoritmit................................................ 9 Algoritmien muodostaminen................................. 23 Ohjelmointikielistä......................................... 25 Lausekielet............................................... 26 Ohjelman tulkkaaminen..................................... 27 Ohjelman kääntäminen..................................... 28 Kääntäjän toiminta......................................... 29 Ensimmäinen C++-ohjelma................................... 30 Lähdekoodista suoritettavaksi ohjelmaksi........................ 32 Editointi................................................. 33 Emacs-editorin käytöstä..................................... 34 Kääntäminen............................................. 38 Virhetilanteet............................................. 39 Varatut sanat............................................. 42 C++-kielen varatut sanat..................................... 43 Vastusesimerkki............................................ 44 Perustietotyypit............................................ 46 Lausekeet................................................ 48 Operaattorit.............................................. 49 i Sisällysluettelo ii Laskujärjestys eli presedenssi.................................. 50 Sitomisjärjestys eli assosioituminen............................. 52 Yli- ja alivuoto............................................. 53 Celsius Fahrenheit-esimerkki................................. 54 while-silmukka............................................ 58 Vertailuoperaattorit......................................... 60 Muuttujat................................................ 61 Painoindeksiesimerkki....................................... 64 if-rakenne................................................ 68 Loogiset operaattorit....................................... 70 Kertotauluesimerkki........................................ 72 Tulostuksen muotoilu....................................... 77 Aliohjelmat eli proseduurit................................... 78 Kertotauluesimerkki hiukan toisin.............................. 81 Määrittely vs. esittely....................................... 83 Mistä aliohjelmat tulevat?.................................... 85 Miksi aliohjelma on ystävä?................................... 86 Toisen asteen yhtälon ratkaisu-esimerkki......................... 87 Funktiot................................................. 93 Mistä funktiot tulevat?...................................... 97 Matematiikkakirjasto........................................ 99 Miksi reaalilukuja ei saa vertailla ==- ja!=-operaattoreilla?............ 100 Arvo- ja viiteparametrit...................................... 103 Viikonpäiväesimerkki........................................ 106 Merkkijonotietotyyppi (string)................................ 124 Merkkijonokirjaston funktioita................................. 128 Osoitelappuohjelma........................................ 134 Lokalisaatio............................................... 138 Sisällysluettelo iii Sanojenerotteluohjelma..................................... 139 Merkkien käsittely locale-kirjaston avulla......................... 143 Lämpötilagraafiesimerkki.................................... 145 Taulukot................................................. 151 Taulukkoparametrit......................................... 155 Tenttitulosesimerkki........................................ 160 unsigned, short ja long...................................... 169 Perustietotyyppien ääriarvot: limits-kirjasto....................... 172 Tietue- eli struct-tietotyypit................................... 176 Ohjelmointityyli........................................... 179 Tiedon lajittelu............................................ 189 Tiedon etsintä............................................. 196 Tuotekoodiesimerkki........................................ 202 Tietovirrat................................................ 212 Tietovirrat C++:ssa......................................... 215 Tietovirtaongelmien havaitseminen............................. 221 Standardivirrat cin, cout ja cerr................................ 225 Tietovirta funktion parametrina................................ 226 Salasanatiedostoesimerkki.................................... 228 Luettelo- eli enum-tyypit..................................... 239 switch-rakenne............................................ 241 for-silmukka.............................................. 244 do while-silmukka......................................... 245 break, continue ja silmukat................................... 246 Käskyt vs. tieto ja tieto-ohjattu ohjelmointi....................... 248

OHJ-1100 Ohjelmointi I 1 Mitä on ohjelmointi? Ohjelmointi tarkoittaa yleisellä tasolla sitä, kun jokin systeemi, laite, ihminen tms. saadaan suorittamaan jonkun toisen antamat toimenpiteet/käskyt. Ohjelmointia on tämän määritelmän mukaan esim: tallentavan digiboksin ajastaminen, lennonjohto antaa lentäjälle lento-ohjeet, ajo-ohjeiden selittäminen pizza-taxille ja aivopesu (propaganda, mainonta?), Ohjelmoinnin kohteelta (videot, lentokapteeni jne) ohjelmointi vaatii kykyä: 1. vastaanottaa ja ymmärtää annetut ohjeet/käskyt ja 2. suorittaa ne (oikeassa) järjestyksessä. Systeemi on ohjelmoitava, jos sillä on nämä kyvyt. Usein ohjelmoitava systeemi tarvitsee käskyt erittäin tarkasti määritellyssä muodossa, jotta se pystyisi niitä noudattamaan. OHJ-1100 Ohjelmointi I 2 Käytännössä ohjelmointi koostuu vaiheista: 1. ongelman/halutun lopputuloksen ymmärtäminen, 2. ongelman ratkaisun kehittäminen ja 3. ratkaisun yksityiskohtainen selittäminen ohjelmoitavalle systeemille sen ymmärtämässä muodossa. Vaihe 2 on usein hankalin, koska se vaatii näkemystä ja tietämystä siitä, kuinka kyseinen ongelma yleensä ottaen ratkaistaan. Kuten ongelmanratkaisu yleensäkin, vaihe 2 vaatii luovuutta. Vaihe 3 taas vaatii erityistietämystä ongelman ratkaisuun käytettävästä ohjelmoitavasta systeemistä (esimerkiksi sen ymmärtämistä käskyistä jne). OHJ-1100 Ohjelmointi I 3 Tietokoneen ohjelmointi Kurssin nimessä ja tästä eteenpäin sanalla»ohjelmointi» tarkoitetaan tietokoneen ohjelmointia eli sitä prosessia, jolla tietokone saadaan suorittamaan käyttäjän (lue ohjelmoijan) haluamat toiminnot. Tietokone on ohjelmoitava systeemi (vrt. kalvo 1). Käskyt, joita nykyiset tietokoneet suoraan ymmärtävät, ovat erittäin alkeellisia (konekieli). Tyypilliset konekieliset käskyt ovat monimutkaisuudeltaan verrattavissa seuraaviin: aritmeettiset operaatiot (l. peruslaskutoimitukset), lukujen vertailu (pienempi, suurempi, yhtäsuuri), seuraavien suoritettavien käskyjen valinta riippuen vertailun tuloksesta ja luvun siirtäminen paikasta toiseen OHJ-1100 Ohjelmointi I 4 Ennen kuin mitään ongelmaa voi tietokoneella ratkaista, ratkaisu täytyy tavalla tai toisella pukea joukoksi konekielen käskyjä kaikkia ongelmia tietokoneella ei voi ratkaista. Konekieli on erittäin alkeellista hiukankin isomman ongelman selittäminen tietokoneelle pelkästään konekielellä on kohtuuttoman työlästä. On olemassa ns. korkean tason ohjelmointikieliä, joiden käskyt»tekevät enemmän» sama ongelma saadaan esitettyä pienemmässä tilassa ja vähemmällä vaivalla. Tietokoneet ymmärtävät vain omaa konekieltään ennen korkean tason kielisen ohjelman suorittamista se on ensin muutettava konekielelle. Kurssin opetuskieli C++ on korkean tason kieli. Ohjelmointikielistä lisää myöhemmin. Muunkin tyyppisiä käskyjä toki on, mutta niiden suorittamat toiminnot eivät ole merkittävästi noita monimutkaisempia.

OHJ-1100 Ohjelmointi I 5 Harhaluulo ohjelmoinnista Asiaan perehtymättömillä on sellainen käsitys, että ohjelmointi on sitä, kun istutaan tietokoneen ääressä ja syötetään näppäimistöltä koneelle ohjelmaa. Kun naputtelu on ohi, kone suorittaa ohjelman ongelmitta ja näyttää tarvittavan oikean tuloksen. Kun tätä käsitystä ohjelmoinnista vertaa kalvolla 2 esitettyyn yleiseen malliin, niin jotain puuttuu. Harhaluuloinen käsitys koostuu pelkästään yleisen mallin viimeisestä vaiheesta ongelmaa ei välttämättä ole ymmärretty kunnolla eikä sen ratkaisua mietitty loppuun saakka. Tämä väärä lähestymistapa johtaa ikävyyksiin: ongelmaa ei ole ymmärretty ratkaistaan väärä ongelma, ratkaisutapa virheellinen ohjelman antama lopputulos on väärä ja ohjelmaa pitää korjata hukataan aikaa ja rahaa. OHJ-1100 Ohjelmointi I 6 Tämä virheellinen käsitys on lähes kaikilla ohjelmointia aloittelevilla ja siitä kannattaa hankkiutua eroon välittömästi. Harhaluulo on erikoinen myös siksi, että se tuntuu esiintyvän vain ohjelmoinnin yhteydessä. Kaikilla muilla elämänaloilla tuottavaan työhön sisältyy aina paljon suunnittelua ja valmistelua ennen varsinaiseen työhön ryhtymistä suurempi varmuus lopputuloksen kelvollisuudesta ja hukatut resurssit (aika, raha, hermot) minimoidaan. Vaikka virheellinen lähestymistapa saattaakin toimia pienissä ohjelmointiprojekteissa, ongelman koon kasvaessa homma karkaa käsistä, jos sitä ei ole suunniteltu kunnolla. OHJ-1100 Ohjelmointi I 7 Oikea malli ohjelmoinnista Kokemus osoittaa, että seuraava kalvon 2 mallista hiukan kehittyneempi versio kuvaa onnistuneen ohjelmointiprojektin vaiheita: 1. Ongelman ratkaisuvaihe a. Analysointi ja määrittely: ymmärrä ongelma ja selvitä, mitä ratkaisun on tarkoitus tehdä. b. Yleinen ratkaisu (algoritmi): kehitä looginen sarja ohjeita, joita noudattamalla ongelmalle saadaan haluttu lopputulos. c. Tarkistus: testaa kynällä ja paperilla, että kehittämäsi algoritmi todella toimii. 2. Ratkaisun toteutusvaihe a. Konkreettinen ratkaisu: toteuta algoritmi sopivalla ohjelmointikielellä. b. Testaus: suorita ohjelmaa eri syötteillä ja vertaile tuloksia tunnettuihin oikeisiin ratkaisuihin: jos virheitä löytyy, mieti»miksi?» ja korjaa ne. OHJ-1100 Ohjelmointi I 8 3. Ylläpitovaihe a. Käyttö: käytä ohjelmaa suunniteltuun tarkoitukseen. b. Ylläpito: korjaa löytyviä virheitä ja lisää mahdollisia uusia tarvittavia ominaisuuksia. Karkea sääntö: ratkaisuvaihe/toteutusvaihe tulisi olla 50%/50%, kun vertaillaan käytettyä aikaa ja resursseja.»väärää lähestymistapaa» käyttävillä suhde on usein 10%/90% tai huonompi: ongelmaa pohdittu kahvikupin verran ja rynnätty suoraan toteuttamaan.

OHJ-1100 Ohjelmointi I 9 Algoritmit Algoritmi: sarja toimenpiteitä tehtävän/ongelman suorittamiseksi/ratkaisemiseksi. Esimerkiksi seuraava algoritmi esittää, kuinka neliönmuotoisesta paperiarkista taitellaan origami-pulu: OHJ-1100 Ohjelmointi I 10 Seuraava algoritmi taas kertoo, kuinka saadaan keitettyjä perunoita: Algoritmi: Keitetyt perunat 1. pese perunat 2. etsi kattila 3. laita pestyt perunat kattilaan 4. lisää kattilaan vettä kunnes perunat peittyvät 5. laita kattila levylle 6. käännä levy päälle 7. anna kiehua kunnes perunat ovat kypsiä 8. käännä levy pois päältä 9. kaada keitinvesi viemäriin Algoritmilta vaaditaan seuraavat ominaisuudet (ainakin hyvältä algoritmilta): 1. yksikäsitteinen (ei tulkittavissa väärin), 2. yksityiskohtainen (tyhmäkin osaa seurata), 3. saavuttaa tavoitteensa (eli toimii oikein), 4. määrää toimenpiteiden suoritusjärjestyksen (seuraus kohdasta 1) ja 5. sisältää äärellisen määrän toimenpiteitä (muuten tehtävä ei tulisi suoritetuksi). OHJ-1100 Ohjelmointi I 11 Kohdat 1 ja 2 ovat jossain mielessä tulkinnanvaraisia: milloin algoritmi on riittävän yksikäsitteinen ja yksityiskohtainen? Perunoidenkeittoalgoritmin yksikäsitteisyydessä on parantamisen varaa: nykyistä algoritmia joku»tyhmä» tai ilkeämielinen voisi tulkita väärin. Yksikäsitteisempi versio olisi (muutokset lihavoitu): Algoritmi: Keitetyt perunat 1. pese perunat 2. etsi riittävän suuri kattila 3. laita em. pestyt perunat em. kattilaan 4. lisää em. kattilaan vettä kunnes siellä olevat perunat juuri peittyvät 5. laita em. kattila hellan levylle 6. käännä em. levyn maksimiteho päälle 7. anna em. kattilassa olevan veden kiehua kunnes siellä olevat perunat ovat kypsiä 8. käännä em. levy pois päältä 9. kaada keitinvesi em. kattilasta viemäriin OHJ-1100 Ohjelmointi I 12 Yksityiskohtaisuuden suhteen molemmat algoritmit ovat puutteellisia. Esimerkiksi pulun nokan taittelu on sen verran hankala operaatio, että sitä kannattaisi tarkentaa:

OHJ-1100 Ohjelmointi I 13 Henkilö, joka ei ole koskaan kokannut, saattaisi tarvita tarkemmat ohjeet perunoiden keittämiseen: Algoritmi: Keitetyt perunat 1. pese perunat 1.1. laita tulppa tiskialtaaseen 1.2. laita perunat em. tiskialtaaseen 1.3. laske vettä em. tiskialtaaseen kunnes em. perunat peittyvät 1.4. ota juuresharja 1.5. harjaa em. perunat yksitellen \ em. juuresharjalla kunnes puhtaita 1.6. palauta em. juuresharja paikalleen 1.7. avaa em. tulppa ja laske vesi pois 2. etsi riittävän suuri kattila 2.1. avaa kattilakaapin ovi 2.2. valitse sopiva kattila 2.3. ota em. kattila 2.4. sulje em. ovi 2.5. aseta em. kattila tiskipöydälle Algoritmin loppuja kohtia 3 9 voitaisiin tarkentaa samaan tapaan. OHJ-1100 Ohjelmointi I 14 Jos algoritmi ei vieläkään ole riittävän yksityiskohtainen, niin tarkennetaan lisää: Algoritmi: Keitetyt perunat 1. pese perunat 1.1. laita tulppa tiskialtaaseen 1.1.1. etsi tiskialtaan tulppa 1.1.2. ota em. tulppa käteen 1.1.3. paina em. tulppa tiiviisti em. altaan pohjassa olevaan reikään 1.1.4. laske irti em. tulpasta Koko loppualgoritmi voitaisiin tietysti tarkentaa samaan tapaan ja niin edelleen aina vain yksityiskohtaisemmin, kunnes haluttu taso saavutetaan. OHJ-1100 Ohjelmointi I 15 Riittävä yksikäsitteisyys ja yksityiskohtaisuus ovat tulkinnanvaraisia suureita ja riippuvat tilanteesta. Aikuiselle alkuperäinen peruna-algoritmi olisi ollut riittävä, pikkulapselle luultavasti ei. Tietokoneet ovat»rajoittuneita» suunniteltaessa tietokonealgoritmeja niiden on oltava äärimmäisen yksikäsitteisiä ja yksityiskohtaisia. Usein algoritmiin liittyy ehdollisuutta ja toistoa: 1. Jonkin algoritmin osan suorittaminen saattaa riippua olosuhteista (ehdollisuus). 2. Jotain algoritmin osaa saatetaan tarvittaessa suorittaa useita kertoja peräkkäin (toisto). Peruna-algoritmissa on sekä ehdollisuutta että toistoa, joihin törmätään, jos joitain kohtia yritetään vielä entisestään yksityiskohtaistaa. OHJ-1100 Ohjelmointi I 16 Esimerkiksi haluttaessa tarkentaa algoritmin kohtaa»2. etsi kattila» törmätään ehdollisuuteen: Algoritmi: Etsi kattila 2. etsi riittävän suuri kattila 2.1. avaa kattilakaapin ovi 2.1.1. JOS kaapin ovi on kiinni NIIN 2.1.1.1. tartu kaapin kahvaan 2.1.1.2. vedä ovi auki 2.1.1.3. laske irti kahvasta 2.2. valitse sopiva kattila 2.3. ota kattila 2.4. sulje ovi 2.5. aseta kattila tiskipöydälle 2.5.1. JOS tiskipöydällä on tilaa NIIN 2.5.1.1. aseta kattila vapaaseen paikkaan MUUTEN 2.5.1.2. raivaa tilaa kattilan verran 2.5.1.3. aseta kattila raivattuun paikkaan

OHJ-1100 Ohjelmointi I 17 Algoritmissa ehdollisuus on siis esitetty muodossa JOS väite NIIN toimenpiteet 1 MUUTEN toimenpiteet 2 Tätä tulkitaan siten, että mikäli väite on tosi, on algoritmin toteuttamiseksi suoritettava toimenpiteet 1. Mikäli väite taas ei pidä paikkaansa, suoritetaan toimenpiteet 2. Väite voi siis periaatteessa olla mikä tahansa toteamus, kunhan siitä tavalla tai toisella voidaan päätellä, pitääkö se paikkansa vai ei. OHJ-1100 Ohjelmointi I 18 Toistoa peruna-algoritmista löytyy tarkentamalla esimerkiksi kohtaa»7. anna veden kiehua kunnes perunat ovat kypsiä»: Algoritmi: perunoiden keittäminen kypsiksi 7. anna kattilassa olevan veden kiehua kunnes siellä olevat perunat ovat kypsiä 7.1. NIIN KAUAN KUIN vesi ei kiehu 7.1.1. odota hetki 7.1.2. tarkasta joko vesi kiehuu 7.2. NIIN KAUAN KUIN perunat eivät ole kypsiä 7.2.1. odota hetki 7.2.2. ota haarukka 7.2.3. työnnä haarukka johonkin perunaan 7.2.4. JOS ei tuntunut vastusta NIIN 7.2.4.1. totea perunat kypsiksi MUUTEN 7.2.4.2. totea perunat raaoiksi 7.2.5. laita haarukka pöydälle OHJ-1100 Ohjelmointi I 19 Eli toisto voidaan esittää algoritmissa seuraavasti: NIIN KAUAN KUIN väite toimenpiteet jota tulkitaan suoraviivaisesti siten, että toimenpiteitä toistetaan yhä uudelleen niin kauan kuin esitetty väite on tosi. Kuten aiemminkin väite saa olla mitä tahansa, jos siitä vain voidaan päätellä, onko se tosi vai epätosi. Algoritmikielessä»JOS-NIIN-MUUTEN» ja»niin KAUAN KUIN» ovat syntaktisia (l. kieliopillisia) rakenteita, joiden semantiikka (l. merkitys) on ehdollisuus ja toisto. Monista ohjelmointikielistä löytyy vastaavankaltaiset rakenteet»if-then-else» ja»while» jatkon kannalta on selvempää, jos käytämme niitä suomenkielisten rakenteiden sijaan. Tällaista ohjelmointikielen ja puhutun kielen yhdistelmää kutsutaan pseudokoodiksi ja se on erittäin hyödyllinen työkalu. OHJ-1100 Ohjelmointi I 20 Selvyyden vuoksi vielä koko perunankeittoalgoritmi (Huom! Edelleen puutteellinen): Algoritmi: Keitetyt perunat 1. pese perunat 1.1. laita tulppa tiskialtaaseen 1.1.1. etsi tiskialtaan tulppa 1.1.2. ota tulppa käteen 1.1.3. paina tulppa tiiviisti altaan pohjassa olevaan reikään 1.1.4. laske irti tulpasta 1.2. laita perunat tiskialtaaseen 1.3. laske vettä tiskialtaaseen kunnes perunat peittyvät 1.4. ota juuresharja 1.5. harjaa perunat yksitellen juuresharjalla kunnes puhtaita 1.6. palauta juuresharja paikalleen 1.7. avaa tulppa ja laske vesi pois

OHJ-1100 Ohjelmointi I 21 2. etsi riittävän suuri kattila 2.1. avaa kattilakaapin ovi 2.1.1. IF kaapin ovi on kiinni THEN 2.1.1.1. tartu kaapin kahvaan 2.1.1.2. vedä ovi auki 2.1.1.3. laske irti kahvasta 2.2. valitse sopiva kattila 2.3. ota kattila 2.4. sulje ovi 2.5. aseta kattila tiskipöydälle 2.5.1. IF tiskipöydällä on tilaa THEN 2.5.1.1. aseta kattila vapaaseen paikkaan ELSE 2.5.1.2. raivaa tilaa kattilan verran 2.5.1.3. aseta kattila raivattuun paikkaan 3. laita pestyt perunat kattilaan 4. lisää kattilaan vettä kunnes siellä olevat perunat juuri peittyvät 5. laita kattila levylle OHJ-1100 Ohjelmointi I 22 6. käännä levyn maksimiteho päälle 7. anna kattilassa olevan veden kiehua kunnes siellä olevat perunat ovat kypsiä 7.1. WHILE vesi ei kiehu 7.1.1. odota hetki 7.1.2. tarkasta joko vesi kiehuu 7.2. WHILE perunat eivät ole kypsiä 7.2.1. odota hetki 7.2.2. ota haarukka 7.2.3. työnnä haarukka johonkin perunaan 7.2.4. IF ei tuntunut vastusta THEN 7.2.4.1. totea perunat kypsiksi ELSE 7.2.4.2. totea perunat raaoiksi 7.2.5. laita haarukka pöydälle 8. käännä levy pois päältä 9. kaada keitinvesi kattilasta viemäriin OHJ-1100 Ohjelmointi I 23 Algoritmien muodostaminen Hyväksi havaittu tapa algoritmien muodostamiseen on jäsentää kokonaisuutta pienempiin osiin pieniä kokonaisuuksia on helpompi hallita ja kokonaisuus saadaan pienistä osista yhdistämällä, kunhan osien algoritmit ovat oikein muodostettu ja liitetty toisiinsa.»hajoita ja hallitse» Idea on siis jokseenkin sama, joka esiintyi perunankeittoalgoritmia kehiteltäessä. Jäsentämistä jatketaan, kunnes osatoiminnot ovat riittävän yksinkertaisia algoritmin toiminnot ovat monimutkaisuudeltaan samalla tasolla kuin mitä algoritmin suorittava systeemi ymmärtää käskyinään. OHJ-1100 Ohjelmointi I 24 Tietämystä algoritmin suorittavasta systeemistä siis tarvitaan jo algoritmia suunniteltaessa tiedetään, milloin algoritmi on jäsennelty riittävän pitkälle, ja jäsennystä osataan ohjata oikeaan suuntaan niin, että se sopii hyvin halutun systeemin suoritettavaksi. Tietokoneelle algoritmia muodostettaessa ratkaisun kuvaus on kirjoitettava täsmällisesti ja täydellisesti, koska tietokoneelta puuttuu maalaisjärki se ei osaa päätellä epätäsmällisten ohjeiden tarkoitusta Puhuttuun kieleen verrattuna ohjelmointikielet ovat yksinkertaisia ja koska tietokoneelle tarkoitetut algoritmit täytyy aina lopulta pukea ohjelmointikieleksi, jotta ne saadaan suoritettua algoritmin oltava riittävän yksinkertaisessa muodossa, niin että se on helposti esitettävissä ohjelmointikielellä. Algoritmien muodostaminen ei ole helppoa ja sen oppiminen vaatii harjoittelua.

OHJ-1100 Ohjelmointi I 25 Ohjelmointikielistä OHJ-1100 Ohjelmointi I 26 Lausekielet Ohjelmointikieli on se kieli, jolla tietokoneen kanssa voidaan kommunikoida (l. kuvata algoritmit koneelle sen ymmärtämässä muodossa). Se on selkeästi analoginen puhutun kielen kanssa, mutta sangen yksinkertainen. Kaikki tietokoneet ymmärtävät pohjimmiltaan vain omaa konekieltään: sopivassa järjestyksessä koneen muistiin tallennettuja lukuja 0 ja 1 (tosiasiassa jännitetasoja). Tietyssä järjestyksessä esiintyvät nollat ja ykköset tietokone osaa tulkita alkeellisiksi käskyiksi, konekäskyiksi. Lausekielet ovat konekieltä ilmaisuvoimaisempia: niillä halutun tehtävän selittäminen tietokoneelle on helpompaa ja lopputulos ymmärrettävämpää ihmiselle. Yksi lausekielellä kirjoitettu käsky vastaa useita, jopa tuhansia, konekäskyjä. Ennen kuin tietokone voi suorittaa jollain muulla kuin sen omalla konekielellä kirjoitetun ohjelman, se täytyy tavalla tai toisella muuntaa konekieleksi: kääntäminen (compiling) tulkkaaminen (interpreting) Alunperin kaikki ohjelmointi oli puhtaasti konekielellä ohjelmointia: johtoja ja vipuja. Konekieli on kovin hankalakäyttöistä symbolinen konekieli korkean tason ohjelmointikielet (esim. lausekielet). OHJ-1100 Ohjelmointi I 27 Ohjelman tulkkaaminen OHJ-1100 Ohjelmointi I 28 Ohjelman kääntäminen Ohjelman tulkkaaminen perustuu siihen, että ohjelmointikielen tulkki suorittaa ohjelmaa käsky (lause/lauseke) kerrallaan. Etuja: ohjelma voidaan testata pala kerrallaan ja tulkki huolehtii virheilmoituksista ja auttaa virheiden etsinnässä. Ohjelman kääntäminen perustuu siihen, että ohjelmakoodi käännetään kokonaisuudessaan konekielelle erityisellä kääntäjäohjelmalla (kääntäjällä) ennen kuin se voidaan suorittaa. Etuja: syntaksi- ja semanttiset virheet havaitaan aina ja kääntäjää ei enää tarvita uudelleen. Haittoja: ohjelman suoritus vaatii aina tulkin ja ohjelmaan saattaa jäädä virheitä, jos testaus ei ole täydellinen. Haittoja: ajonaikaiset virheet jäävät yleensä ohjelmoijan hoidettavaksi, ohjelman oltava kokonaan valmis ja testaus on hankalampaa.

OHJ-1100 Ohjelmointi I 29 Kääntäjän toiminta OHJ-1100 Ohjelmointi I 30 Ensimmäinen C++-ohjelma Lähdekoodi Kääntäjä Käydään yksityiskohtaisesti läpi pikkuruinen C++-kielinen ohjelma: // Lähdekooditiedosto: forever.cc // // Ohjelma tulostaa näytölle lausahduksen: // " I plan to live forever // or die trying." Konekieli Kirjastot #include <iostream> using namespace std; Linkkeri Suoritettava ohjelma int main( ) { cout << " I plan to live forever" << endl; cout << " or die trying." << endl; OHJ-1100 Ohjelmointi I 31 OHJ-1100 Ohjelmointi I 32 Pienessä ohjelmassa on monta tärkeää asiaa: Teksti //-kirjainyhdistelmästä rivin loppuun on kommentti, joka ei vaikuta ohjelman toimintaan. Lähdekoodista suoritettavaksi ohjelmaksi Varsinaiset ohjelman suorittamat toiminnot ovat main:ia seuraavien aaltosulkeiden sisällä. Käskyt (lauseet) tuntuvat päättyvän ";":een. Jos C++-ohjelmassa halutaan lukea syötteitä tai kirjoittaa tulosteita, sen alkuun on lisättävä #include <iostream> ja using namespace std. cout on C++:ssa olio, johon voidaan <<-operaattorilla ohjata tulosteita, jotka sitten ilmestyvät ohjelmaa suoritettaessa näytölle. Lainausmerkkien väliin kirjoitettua tekstiä kutsutaan merkkijonoksi, mikä tarkoittaa selkokielellä tekstimuotoista tietoa. endl tulostaa rivinvaihdon: seuraavat tulostukset alkavat uudelta riviltä (sen vasemmasta laidasta). C++-ohjelman tekeminen etenee yleensä seuraavasti: 1. suunnitellun algoritmin C++-version kirjoittaminen jollain editorilla 2. tallentaminen tiedostoon, jonka nimi päättyy.cc 3. tiedoston kääntäminen C++-kääntäjällä konekielelle 4. jos tuli käännösvirheitä, niin takaisin editoriin korjaamaan ne 5. käännetyn ohjelman testaaminen, jotta nähdään, toimiiko se oikein 6. jos ei toimi oikein, niin mieti miksi ei ja palaa takaisin editoriin korjaamaan viat 7. muuten ohjelma on valmis

OHJ-1100 Ohjelmointi I 33 Editointi OHJ-1100 Ohjelmointi I 34 Emacs-editorin käytöstä C++-ohjelmia voi kirjoittaa millä tahansa editoriohjelmalla. Ohjelmien editointiin kannattaa kuitenkin, jos mahdollista, käyttää emacs-editoria. Kun emacs:illa käsittelee tiedostoa, jonka nimi päättyy.cc:hen, emacs menee automaattisesti C++-tilaan, joka osaa esimerkiksi sisentää ohjelmakoodin automaattisesti, kun vain painaa tabulaattorinäppäintä. Periaatteessa tällä kurssilla ei ole tarkoitus uppoutua editoriohjelman käyttöön: jonkin editorin tuntemus pitäisi jokaisella olla TiTePk:sta. Seuraavassa kuitenkin pikaopas emacs:in tärkeimpiin ominaisuuksiin. Emacsin saa käyntiin kirjoittamalla: proffa> emacs tiedosto.cc jolloin käsiteltäväksi otetaan tiedosto tiedosto.cc. Jos tiedostoa ei ennestään ole olemassa, se luodaan ensimmäisen talletuksen yhteydessä. C++-lähdekooditiedostojen nimen pitää päättyä.cc:hen, jonka myös emacs tajuaa ja menee sen seurauksena C++-tilaan, jossa on ohjelmien kirjoittamisen avuksi monenlaisia ominaisuuksia. Käynnistyttyään emacs näyttää käsiteltävän tiedoston, jota sitten voidaan muuttaa joko suoraan tekstiä kirjoittamalla tai eri näppäinyhdistelmiin sidotuilla komennoilla. Seuraavaan kerätty pikku lista hyödyllisiä emacsin näppäinyhdistelmiin sidottuja komentoja. OHJ-1100 Ohjelmointi I 35 ZYQR Nuolinäppäimillä kursorin voi liikuttaa tekstin seassa haluamaansa paikkaan. C+x C+s Tallettaa tiedoston levylle. Muista aina tallettaa tiedosto ennen kääntämistä. C+z Keskeyttää emacsin suorituksen ja hyppää proffan komentotulkkiin, jolle voi syöttää UNIXkomentoja, esimerkiksi käännöskomennon. Kun komennot on annettu, pääsee emacsiin takaisin komennolla fg: proffa> fg jolloin emacs palaa samaan tilanteeseen, missä se olic+z:aa painettaessa. C+x C+c Tappaa emacsin lopullisesti: fg-komennolla ei pääse takaisin. OHJ-1100 Ohjelmointi I 36 lineennne Kursori hyppää tiedoston riville nnn. Hyödyllinen Xxgoto..- kun halutaan päästä riville, jolla kääntäjä väitti virheen sijaitsevan. XxcompileE Mahdollistaa käännöskomennon antamisen emacsista. Ehdottaa aluksi komentoa make k, josta pääsee eroon painamalla =-näppäintä riittävän monta kertaa, jonka jälkeen voi naputella haluamansa käännöskomennon aivan, kuten UNIXkomentoriviltä. E :in painalluksen jälkeen emacs avaa uuden ikkunan ja suorittaa annetun komennon siten, että kaikki virheilmoitukset ilmestyvät uuteen ikkunaan. C+xo Siirtää kursorin emacsin ikkunasta toiseen: tällä komennolla pääsee lähdekoodi-ikkunasta virheilmoitusikkunaan ja takaisin.

OHJ-1100 Ohjelmointi I 37 C+c C+c Siirtymällä C+x o:lla virheilmoitusikkunaan, siellä nuolinäppäimillä virheilmoitusrivin päälle ja suorittamalla tämän komennon hyppää emacs siihen kohtaan lähdekooditiedostossa, jolla virhe sijaitsi. C+x1 Emacs sulkee kaikki muut ikkunat, paitsi, sen jossa kursori on. Tällä tavoin pääsee eroon virheilmoitusikkunasta, kunhan muistaa ensin siirtää kursorin lähdekoodi-ikkunaan. C+x b tiedostonnimi E Jos vahingossa tulee sulkeneeksi ikkunan, jossa lähdekoodi oli, saa sen haettua takaisin tällä komennolla: antaa vain tiedostonnimeksi lähdekooditiedoston nimen. T Painamalla tabulaattoria lähdekoodirivillä emacs yrittää sisentää sen siististi parhaan kykynsä mukaan. Vastuu on kuitenkin kirjoittajalla! OHJ-1100 Ohjelmointi I 38 Kääntäminen Ohjelman kääntämiseen käytämme tällä kurssilla ohj1c++-nimistä kääntäjää. ohj1c++:lle luetellaan komentorivillä kaikki C++-kieliset lähdekooditiedostot, ja se kääntää niistä suoritettavan konekielisen ohjelman: proffa> ohj1c++ forever.cc Jos ohjelma on virheetön, tuloksena syntyy ajokelpoinen ohjelma a.out, joka voidaan suorittaa kirjoittamalla sen nimi komentotulkille: proffa>./a.out I plan to live forever or die trying. a.out ei ole kuvaava nimi, mutta ohj1c++:lle voi kertoa, minkä nimisen ohjelman haluaa tuloksena: proffa> ohj1c++ o plan forever.cc proffa>./plan I plan to live forever or die trying. OHJ-1100 Ohjelmointi I 39 Virhetilanteet Periaatteessa ohjelmissa on kolmenlaisia virheitä: kielioppi- eli syntaksivirheitä, semanttisia eli»merkitysvirheitä» ja loogisia eli»ajatusvirheitä». Syntaksivirheet Syntaksivirheet ovat virheitä, jotka syntyvät, kun lähdekoodi ei ole käytetyn ohjelmointikielen kielioppisääntöjen mukaista. Esimerkiksi cout- tai return-komennon (lauseen) lopusta puuttuva ";"-merkki olisi C++:ssa syntaksivirhe. Kääntäjä löytää aina syntaksivirheet. Virheen löydyttyä kääntäjä tulostaa ilmoituksen, joka kertoo virheen syyn ja (suuntaa-antavan) rivinumeron, jolla virhe lähdekooditiedostossa sen mielestä sijaitsi. Tyypillisesti virheilmoitus alkaa sanoilla»syntax error» tai»parse error». OHJ-1100 Ohjelmointi I 40 Semanttiset virheet Semanttiset virheet syntyvät, kun ohjelmakoodi on syntaktisesti oikein, mutta kääntäjä ei silti pysty ymmärtämään sitä. Jos esimerkkiohjelmassa olisi vahingossa kirjoitettu ndl, kun oikea vaihtoehto on endl, olisi tuloksena semanttinen virhe. Semanttiset virheetkin kääntäjä löytää aina. Semanttisesta virheestä tulostuu virheilmoitus, jonka jälkeen kääntäjä tyypillisesti sekoaa ja väittää löytävänsä koodista samalta ja myöhemmiltä riveiltä kaikennäköisiä virheitä korjaa virheet aina kääntäjän ilmoittamassa järjestyksessä.

OHJ-1100 Ohjelmointi I 41 Loogiset virheet Loogiset virheet syntyvät, kun ohjelman kirjoittaja ajattelee jotain väärin tai unohtaa ottaa huomioon jonkun joskus hyvinkin vähäpätöisen seikan. Loogiset virheet ovat tavallisesti kirjoitusvirheitä tai algoritmin suunnittelussa tapahtuneita virheitä. Loogiset virheet ilmenevät siten, että ohjelma toimii väärin. Kääntäjällä ei ole mahdollisuuksia havaita loogisia virheitä, koska se vaatisi ohjelmoijan ajatuksenjuoksun ymmärtämistä. Ainoa tapa välttää loogisia virheitä on ohjelman huolellinen suunnittelu ja kirjoittaminen. OHJ-1100 Ohjelmointi I 42 Varatut sanat Kuten puhutuissa kielissä, on ohjelmointikielissäkin sanoja, joilla on jokin kiinteä merkitys. Ohjelmointikielistä puhuttaessa tällaisia sanoja kutsutaan varatuiksi sanoiksi. Varatuille sanoille on siis ohjelmointikielessä määritelty merkitys, eikä ohjelmoija yleensä voi muuttaa tätä merkitystä, koska tällöin kyseisen sanan alkuperäinen tarkoitus hukkuisi. Joskus kielen varattuja sanoja kutsutaan myös käskyiksi. Sanaa»käsky» käytetään kuitenkin usein hiukan vapaammin, esimerkiksi tarkoittamaan yhtä ohjelman lausetta. Varatut sanat luovat perustan koneen ja ohjelmoijan kommunikoinnille käytettäessä korkean tason ohjelmointikieltä. OHJ-1100 Ohjelmointi I 43 C++-kielen varatut sanat OHJ-1100 Ohjelmointi I 44 Esimerkki Seuraavassa on lueteltu C++-kielen varatut sanat: and dynamic_cast not_eq throw and_eq else operator true asm enum or try bitand explicit or_eq typedef bitor export private typeid bool false protected typename break float public union case for register unsigned catch friend reinterpret_cast using char goto return virtual class if short void compl inline signed volatile const int sizeof wchar_t const_cast long static while continue main static_cast xor default mutable struct xor_eq delete namespace switch do new template double not this Osaan kurssilla tutustutaan, muttei läheskään kaikkiin. // Lähdekooditiedosto: vastukset.cc // // Kommentointi on tärkeä osa ohjelman // kirjoittamista, mutta kalvoilla se vie lii // kaa tilaa, joten vastaisuudessa esimerkit // ovat kommentoituja vain tositarpeessa! #include <iostream> using namespace std; int main( ) { cout << " Sarjaan: " << 5.0 + 10.0 << endl; cout << "Rinnan: " << 5.0 10.0 / ( 5.0 + 10.0) << endl; Luentomateriaalin ohjelmaesimerkeissä varatut sanat on lihavoitu.

OHJ-1100 Ohjelmointi I 45 Kun ohjelma käännetään ja suoritetaan: proffa> ohj1c++ o vastukset vastukset.cc proffa>./vastukset Sarjaan: 15 Rinnan: 3.33333 Siitä opittua: C++-kieli selvästikin ymmärtää lukuja ja sallii niillä laskemisen. cout:in avulla voidaan tulostaa myös lukuja (laskulausekkeen arvoja). C++ ei ole kovin tarkka siitä, kuinka jaamme ohjelmamme riveille. Kuinka sisennetään siististi useamman rivin kokoinen C++-lause. OHJ-1100 Ohjelmointi I 46 Perustietotyypit Tietokoneohjelmat koostuvat kahdenlaisista olioista: tiedosta ja toimenpiteistä, jotka käsittelevät sitä. Jotta ohjelmointikielellä voisi tehdä tietoa käsitteleviä ohjelmia, on oltava joku tapa tiedon esittämiseen ja käsittelyyn perustietotyypit (alkeistietotyypit) tiedon esittämiseen ja varatut sanat ja operaattorit sen käsittelyyn. Yleisesti ottaen tietotyypillä käsitetään joukkoa alkioita, joilla on samat ominaisuudet, eli niitä voidaan käsitellä samoilla operaattoreilla. Perustietotyypit ovat sellaisia tiedon esitysmuotoja, jotka ohjelmointikieli tuntee automaattisesti. Tavallisesti perustietotyyppien alkioiden käsittelyyn on valmiit käskyt konekielessä. OHJ-1100 Ohjelmointi I 47 Kaikella tiedolla on joku tyyppi. Alussa riittää tutustua perustietotyyppeihin, joita C++-kielessä kutsutaan aritmeettisiksi tyypeiksi, eli tyypeiksi, joille voidaan suorittaa normaaleja laskuoperaatioita (kuten yhteen- ja kertolasku). Tälläisia tyyppejä ovat C++:ssä: int kokonaisluvuille ( 2, 123456), double (float) reaaliluvuille (3.1415, 1E10) ja char kirjainmerkeille ( a, \n ). Todellisuudessa C++ käsittelee kirjainmerkkejäkin pieninä kokonaislukuina (vrt. ASCII-koodi ja ISO-8859). Myös merkkijonot (string, tekstimuotoinen tieto, lainausmerkkien sisällä oleva teksti) on käytännössä tässä vaiheessa perustietotyyppi, vaikka todellisuudessa se ei sitä olekaan. OHJ-1100 Ohjelmointi I 48 Lausekeet Lauseke on tietokoneohjelmassa pohjimmiltaan sama kuin se on matematiikassa: jokin kokonaisuus jolle voidaan laskea (eli evaluoida) arvo. Esimerkiksi (8 + 16 4) / 2 on lauseke, jolle evaluoituu arvo 36. Ohjelmointikielissä lauseke on kuitenkin huomattavasti laajempi käsite kuin mihin perusmatematiikassa on totuttu. Lausekkeen lähtöarvoina käsitelty tieto ei välttämättä muodostu luvuista, eikä lopputuloksenkaan tarvitse olla luku. Pidetään mielessä, että ohjelmointikielissä lausekkeella tämä erityisen laaja tulkinta.

OHJ-1100 Ohjelmointi I 49 Operaattorit OHJ-1100 Ohjelmointi I 50 Laskujärjestys (presedenssi) Seuraava taulukko on esittelee lähes kaikki C++-kielen operaattorit, niiden laskujärjestyksen (presedenssin) ja sitomisjärjestyksen (assosioitumisen): ::. > [ ] ( ) muuttuja++ muuttuja ~! lauseke +lauseke ++muuttuja muuttuja &muuttuja lauseke sizeof new delete /% + << >> < <= > >= ==!= & ^ && = = /= %= += = <<= >>= &= = ^= lauseke? lauseke : lauseke lauseke, lauseke Operaattori lasketaan (evaluoidaan) sitä aikaisemmin, mitä ylemmässä lokerossa se on taulukossa. Suluilla evaluointijärjestys voidaan määrätä halutuksi. Jotkut operaattorit (+,, ja &) esiintyvät taulukossa kahteen kertaan: korkeammalla olevat unaari-operaattorit tarvitsevat yhden operandin ja alemmat binääri-operaattorit tarvitsevat kaksi. Esimerkiksi lauseke: a = 1 2+ 3 / 4; evaluoituu samoin kuin jos olisi kirjoitettu: (a = ( (1 2) + ( ( 3) / 4) ) ); Kyseessä siis on aivan sama asia kuin matematiikasta tutuissa laskujärjestyssäännöissä, paitsi että C++:ssa operaattoreita on paljon enemmän. OHJ-1100 Ohjelmointi I 51 OHJ-1100 Ohjelmointi I 52 C++:ssa (lähes) kaikkien operaattorien tuloksena evaluoituu arvo, jota voidaan käyttää operandina muille operaattoreille. Aritmeettisten operaatioiden tulos on samaa tyyppiä kuin niiden operandien tyypit kannattaa olla erityisen varovainen jakolaskuoperaation kanssa, esimerkiksi 1 / 2 tarkoittaa kokonaislukujakolaskua, eli tulos onkin nolla! Jos kokonaislukujen jakolaskusta on tarve saada»tarkka» reaalilukutulos, täytyy toinen operandi muuttaa reaaliluvuksi käsin käyttämällä tyyppimuunnosoperaattoria: static_cast<double>( 1) / 2 jolloin suoritettava laskutoimitus on: 1.0 / 2 eli myös tulos tulee olemaan reaaliluku 0.5. Nyrkkisääntönä: jos operandit ovat eri tyyppiä, tuloksena on esitysalueeltaan laajempi tyyppi. Sitomisjärjestys (assosioituminen) Presedenssisäännöt eivät kerro kaikkea lausekkeen evaluointijärjestyksestä: jos samassa lausekkeessa on peräkkäin useita samalla tasolla olevia operaattoreita. Tällaiset tilanteet ratkaisee operaattorin sitomisjärjestys, joka voi olla: vasemmalta oikealle, jolloin operaatiot suoritetaan vasemmalta oikealle tai oikealta vasemmalle vastaavasti. Taulukossa sitomisjärjestys on merkitty nuolella vasempaan sarakkeeseen. Esimerkiksi: 1 2 3 4 evaluoidaan C++:ssa siis: ( ( (1 2) 3) 4) Sitomisjärjestyksellä on merkitystä esimerkiksi yli- ja alivuototilanteissa ja pyöristysvirheiden kanssa.

OHJ-1100 Ohjelmointi I 53 Yli- ja alivuoto OHJ-1100 Ohjelmointi I 54 Esimerkki Sisäisesti tietokone esittää luvut kaksikantaisina (binäärilukuina) jollain äärellisellä määrällä nollia ja ykkösiä (bittejä) lukualueet, joita se voi esittää, ovat rajallisia. Esimerkiksi useat tietokoneet nykyään esittävät kokonaisluvut (int) 32:lla bitillä, jolloin niiden suurin mahdollinen arvo 2 32 1 (= 4294967295). Tosiasiassa suurin arvo on 2 31 1 (= 2147483647), koska yksi bitti käytetään etumerkin esittämiseen. Tilannetta, jossa laskutoimituksen tuloksena syntyy niin iso luku, ettei tietokone voi sitä esittää, kutsutaan ylivuodoksi. Vastaavasti alivuoto on tilanne, jossa reaaliluvuilla laskettaessa syntyy itseisarvoltaan niin pieni tulos, ettei esitystarkkuus riitä. Eri tietokoneissa on erilaiset lukualueet ja laskentatarkkuudet. Ratkaistava ongelma Tulosta yhden Celsius-asteen välein käyttäjän antaman alarajan ja ylärajan väliltä Celsiuslämpötiloja vastaavat Fahrenheit-lämpötilat. Tulostuksen selkeyttämiseksi numeroi tulostetut rivit. Ratkaisualgoritmi Algoritmi: Celsius Fahrenheit -taulukko kysy käyttäjältä alin tulostettava Celsius-lämpötila alin celsius käyttäjältä luettu syöte kysy käyttäjältä ylin tulostettava Celsius-lämpötila ylin celsius käyttäjältä luettu syöte rivinumero 1 tulostettava celsius alin celsius WHILE tulostettava celsius ylin celsius fahrenheit 1.8 tulostettava celsius + 32; tulosta rivinumero, tulostettava celsius ja fahrenheit rivinumero rivinumero + 1 tulostettava celsius tulostettava celsius + 1 OHJ-1100 Ohjelmointi I 55 Algoritmin toteutus C++:lla #include <iostream> using namespace std; int main( ) { int alin_celsius; int ylin_celsius; cout << "Anna alin tulostettava Celsius lämpötila: "; cin >> alin_celsius; cout << "Anna ylin tulostettava Celsius lämpötila: "; cin >> ylin_celsius; int rivinumero = 1; int tulostettava_celsius = alin_celsius; while (tulostettava_celsius <= ylin_celsius) { double fahrenheit = 1.8 tulostettava_celsius + 32; cout << rivinumero << ": " << tulostettava_celsius << " C = " << fahrenheit << " F" << endl; rivinumero = rivinumero + 1; ++tulostettava_celsius; OHJ-1100 Ohjelmointi I 56 Käännös ja suoritus proffa> ohj1c++ o celsius celsius.cc proffa>./celsius Anna alin tulostettava Celsius-lämpötila: 10 Anna ylin tulostettava Celsius-lämpötila: 10 1: 10 C = 14 F 2: 9 C = 15.8 F 3: 8 C = 17.6 F 4: 7 C = 19.4 F 5: 6 C = 21.2 F 6: 5 C = 23 F 7: 4 C = 24.8 F 8: 3 C = 26.6 F 9: 2 C = 28.4 F 10: 1 C = 30.2 F 11: 0 C = 32 F 12: 1 C = 33.8 F 13: 2 C = 35.6 F 14: 3 C = 37.4 F 15: 4 C = 39.2 F 16: 5 C = 41 F 17: 6 C = 42.8 F 18: 7 C = 44.6 F 19: 8 C = 46.4 F 20: 9 C = 48.2 F 21: 10 C = 50 F

OHJ-1100 Ohjelmointi I 57 Mitä siitä opittiin Ohjelman käyttöön voidaan määritellä»tiedon tallennuspaikkoja» eli muuttujia (esimerkiksi: alin_celsius, rivinumero ja fahrenheit). Muuttujaan voidaan tallettaa arvo sijoitusoperaattorilla (=) tai lukemalla käyttäjän näppäimistösyötettä (cin >>). Myöhemmin ohjelmassa esiintyvä muuttujan nimi korvataan siihen kaikkein viimeisimpänä sijoitetulla arvolla (poikkeuksia on: =-operaattorin vasen operandi ja ++). while-silmukkarakenteella voidaan toistaa joitain käskyjä halutun monta kertaa. ++-operaattori kasvattaa kokonaislukuoperandinsa arvoa yhdellä (tämä on vain osatotuus asiasta). +-operaattori toimii oikein vaikka toinen operandi olisikin double- ja toinen int-tyyppinen. OHJ-1100 Ohjelmointi I 58 while-silmukka while-silmukan yleinen muoto on: while ( ehto ) { suoritettava_lause 1 ; suoritettava_lause n ; tai jos suoritettavia lauseita on vain yksi: while ( ehto ) suoritettava_lause; tässäkin tapauksessa saa käyttää aaltosulkuja. while toistaa rungossaan olevia lauseita niin kauan kuin ehto evaluoituu ennen uutta kierrosta todeksi. Heti, kun ehdosta evaluoituu ennen uutta kierrosta epätosi, ohjelman suoritus jatkuu while-rakennetta seuraavasta käskystä. OHJ-1100 Ohjelmointi I 59 Ehto evaluoidaan aina ensimmäisenä ennen uuden kierroksen aloittamista jos se on heti aluksi epätosi, silmukan runkoa ei suoriteta kertaakaan. Ehto voi olla mikä tahansa lauseke, jolle evaluoituu arvo tosi tai epätosi lauseke, jossa käytetään vertailu- tai loogisia operaattoreita (==,!=, <, <=, >, >=,!, &&, ). C++:ssa on erillinen perustietotyyppi bool, jonka lailliset arvot ovat true (tosi) tai false (epätosi) edellä lueteltuja operaattoreita sisältävistä lausekkeista evaluoituu arvo, joka on tyypiltään bool. Myös bool-tyyppistä muuttujaa voi käyttää ehtona. Historiallisena jäänteenä C-kielestä kokonaisluvut tulkitaan totuusarvoiksi luku 0 on epätosi ja kaikki muut luvut tosia. Jatkossa opitaan myös, että joissain tilanteissa muitakin tietotyyppejä voi käyttää ehtona. OHJ-1100 Ohjelmointi I 60 Vertailuoperaattorit C++-kielessä on perustietotyyppien vertailuun käytettävissä seuraavat vertailuoperaattorit: Operaattori Merkitys == yhtäsuuri kuin!= erisuuri kuin < pienempi kuin <= pienempi tai yhtäsuuri kuin > suurempi kuin >= suurempi tai yhtäsuuri kuin Kaikki vertailuoperaattorit ovat binäärioperaattoreita: ne vertailevat kahta tietoalkiota. Vertailun tuloksena evaluoituu bool-tyyppinen arvo true (tosi) tai false (epätosi) riippuen siitä, pitikö vertailulausekkeessa esitetty väite paikkansa vai ei.

OHJ-1100 Ohjelmointi I 61 Muuttujat Muuttujia voi ajatella tiedon tallennuspaikkoina. Toisaalta ne ovat myös jollekin tietoalkiolle annettuja nimiä. Kolmanneksi niitä voi ajatella muistipaikan sisällölle annettuna symbolisena nimenä. Muuttujilla on kolme ominaisuutta: tyyppi ja nimi, jotka kerrotaan muuttujaa määriteltäessä, esimerkiksi: int rivinumero; ja arvo, joka yleensä asetetaan =-operaattorilla, esimerkiksi: rivinumero = 1; Muuttujat pitää aina määritellä (ja vain kerran), ennen kuin niitä voi käyttää. Pääsääntöisesti muuttujiin voi tallettaa vain tietoa, joka on saman tyyppistä kuin muuttujan oma tyyppi. OHJ-1100 Ohjelmointi I 62 Poikkeus: aritmeettisia tietotyyppejä C++ osaa automaattisesti muuntaa toisikseen, jos se on mahdollista. On oikein sanoa: int i = 5.5; huomaa kuitenkin pyöristysvirheet ja ylivuodot. Määrittelyn jälkeen ohjelmassa esiintyvän muuttujan nimen paikalle evaluoituu siihen viimeisimpänä sijoitettu arvo (muutamia poikkeuksia on, kuten aiemmin todettiin). Muuttujia voi C++:ssa määritellä kahdessa paikassa: Minkä tahansa lohkon (eli aaltosulkuparin { ) sisällä sellaisessa kohdassa, jossa voisi olla lause. Tällaista muuttujaa kutsutaan paikalliseksi muuttujaksi ja se on käytettävissä vain sen lohkon sisällä (sulkevaan -merkkiin saakka), jossa se on määritelty. Kaikkien lohkojen ulkopuolella, jolloin kyseessä globaali muuttuja. Älä käytä globaaleja muuttujia! OHJ-1100 Ohjelmointi I 63 Muuttujan nimen pitää alkaa merkillä A Z tai a z, mutta loput merkit voivat olla myös numeroita tai alaviivoja (_). Muuttuja voi olla myös vakiomuuttuja, joka käyttäytyy aivan kuin normaali muuttuja, mutta sen arvoa ei määrittelyn jälkeen voi muuttaa. Vakiomuuttujia määritellään lisäämällä varattu sana const määrittelyn eteen: const int paino = 115; Tällaisille vakioille pitää alustaa arvo määrittelyn yhteydessä, sillä se ei myöhemmin ole mahdollista. Muista aina muuttujaa määritellessäsi pysähtyä miettimään, minkälaista tietoa siihen on tarkoitus tallentaa tiedon tyyppi määrää muuttujan tyypin. Literaalit ovat tietoalkioita, joilla on vain tyyppi ja arvo mutta ei nimeä. Literaaleja voi kutsua myös nimettömiksi vakioiksi. Esimerkiksi literaaleja ovat seuraavat: x, 12345, 1.2345 ja "DFW". OHJ-1100 Ohjelmointi I 64 Esimerkki Ratkaistava ongelma Tee ohjelma, joka laskee (miespuolisen) käyttäjän painoindeksin ja kertoo, onko henkilöllä yli-, ali- tms painoa. Ohjelman toiminta näytää seuraavalta: proffa>./painoindeksi Mies, anna painosi kiloina: 115 Pituutesi metreinä: 1.92 Painoindeksi on: 31.1957 eli paljon ylipainoa Taustatietoa Painoindeksi lasketaan seuraavalla kaavalla: painoindeksi = paino kg pituus 2 m ja miehille sen arvoa tulkitaan seuraavasti: Painoindeksi indeksi 20.7 Tulkinta alipainoa 20.7 < indeksi 26.4 normaali 26.4 < indeksi 27.8 lievää ylipainoa 27.8 < indeksi 31.1 ylipainoa 31.1 < indeksi paljon ylipainoa

OHJ-1100 Ohjelmointi I 65 Ratkaisualgoritmi Algoritmi: Painoindeksi kysy käyttäjän paino kiloina paino käyttäjän syöte kysy käyttäjän pituus metreinä pituus käyttäjän syöte painoindeksi paino / (pituus pituus) tulosta painoindeksin arvo IF painoindeksi 20.7 THEN tulosta "alipainoa" ELSE IF 20.7 < painoindeksi 26.4 THEN tulosta "normaali" ELSE IF 26.4 < painoindeksi 27.8 THEN tulosta "lievää ylipainoa" ELSE IF 27.8 < painoindeksi 31.1 THEN ELSE tulosta "ylipainoa" tulosta "paljon ylipainoa" OHJ-1100 Ohjelmointi I 66 Algoritmin toteutus C++:lla #include <iostream> using namespace std; int main( ) { double paino; double pituus; cout << "Mies, anna painosi kiloina: "; cin >> paino; cout << "Pituutesi metreinä: "; cin >> pituus; double indeksi = paino / (pituus pituus); cout << "Painoindeksi on: " << indeksi << " eli "; if ( indeksi <= 20.7 ) { cout << "alipainoa" << endl; else if ( 20.7 < indeksi && indeksi <= 26.4 ) { cout << "normaali" << endl; else if ( 26.4 < indeksi && indeksi <= 27.8 ) { cout << "lievää ylipainoa" << endl; else if ( 27.8 < indeksi && indeksi <= 31.1 ) { cout << "ylipainoa" << endl; else { cout << "paljon ylipainoa" << endl; OHJ-1100 Ohjelmointi I 67 Mitä siitä opittiin C++-kielen if-rakenteella saadaan aikaan ehdollista suoritusta: joidenkin käskyjen suorittaminen riippuu ohjelmoijan määräämästä ehdosta. Looginen operaattori && (ja-operaattori) saa operandeinaan kaksi totuusarvoa ja evaluoituu todeksi vain, jos molemmat operandit olivat tosia. OHJ-1100 Ohjelmointi I 68 if-rakenne If-rakenne on monipuolisin tapa toteuttaa ehdollista suoritusta (haarautumista) C++-kielessä. If-rakenteen yleinen muoto on: if ( ehto 1 ) { suoritettava_lause 1.1 ;... suoritettava_lause 1.i ; else if ( ehto 2 ) { suoritettava_lause 2.1 ;... suoritettava_lause 2.j ; //... tarvittava määrä else-if:ejä tähän... else { suoritettava_lause n.1 ;... suoritettava_lause n.k ;

OHJ-1100 Ohjelmointi I 69 Ehtoja lähdetään tutkimaan ylhäältä alas, ja kun löytyy ehto, joka evaluoituu todeksi, suoritetaan siihen liittyvät lauseet ja jatketaan if-rakennetta seuraavasta lauseesta. Else-haaran lauseet suoritetaan vain, jos mikään edeltävä ehto ei evaluoitunut todeksi. Else if- ja else-haarat eivät ole pakollisia. If ei välttämättä suorita mitään haaraa, jos else puuttuu, eikä mikään ehto evaluoidu todeksi. Aaltosulut eivät ole pakollisia, jos haarassa on vain yksi suoritettava lause. OHJ-1100 Ohjelmointi I 70 Loogiset operaattorit Usein silmukan ehto tai if-rakenteen haaran valitsemiseen käytetty ehto on monimutkaisempi kuin yhden vertailuoperaattorin tulos. Mielivaltaisia ehtorakennelmia saadaan aikaan yhdistelemällä sopivasti loogisia operaattoreita:! ei-operaattori (unaarinen), tosi jos operandi on epätosi. && ja-operaattori (binäärinen), tosi jos molemmat operandit ovat tosia. tai-operaattori (binäärinen), tosi jos edes toinen operandi on tosi. Edellä kuvatun kolmen operaattorin sijaan voi käyttää myös varattuja sanoja not, and ja or. Ja- ja tai-operaattoreita voi olla monta perätysten presedenssi edellisen taulukon mukaan laskeva ja sitomisjärjestys &&- ja -operaattoreilla ja!-operaattorilla OHJ-1100 Ohjelmointi I 71 Ja- ja tai-operaattorit ovat oikosulkuoperaattoreita: toisin kuin aritmeettiset operaattorit, ne eivät aluksi evaluoi molempia operandejaan, vaan suorittavat evaluoinnin operandi kerrallaan vasemmalta oikealle ja lopettavat heti, kun tulos on pääteltävissä. Tällä on merkitystä tilanteissa, joissa halutaan pukea ehdoksi lauseke, jonka evaluointi ei kaikissa tilanteissa ole laillista. Jos esimerkiksi halutaan testata onko muuttujan luku arvo tasan jaollinen muuttujan jakaja arvolla: int luku; int jakaja; // if ( jakaja!= 0 && luku % jakaja == 0 ) { // OHJ-1100 Ohjelmointi I 72 Esimerkki Ratkaistava ongelma Tee ohjelma, joka tulostaa seuraavan söötin kertotaululunttilapun: + + + 1 2 3 4 5 6 7 8 9 + + + 1 1 2 3 4 5 6 7 8 9 2 2 4 6 8 10 12 14 16 18 3 3 6 9 12 15 18 21 24 27 4 4 8 12 16 20 24 28 32 36 5 5 10 15 20 25 30 35 40 45 6 6 12 18 24 30 36 42 48 54 7 7 14 21 28 35 42 49 56 63 8 8 16 24 32 40 48 56 64 72 9 9 18 27 36 45 54 63 72 81 + + + jossa &&-operaattorin oikosulkuominaisuus takaa sen, ettei ehtolausekkeessa koskaan yritetä ottaa jakojäännöstä nollan kanssa.

OHJ-1100 Ohjelmointi I 73 Ratkaisualgoritmi Algoritmi: Kertotaulun tulostus tulosta erotinvaakarivi tulosta sarakkeiden otsikkorivi tulosta erotinvaakarivi luku 1 WHILE luku 9 tulosta luvun kertotaulurivi luku luku + 1 tulosta erotinvaakarivi Joitain algoritmin kohtia voisi yksityiskohtaistaa, mutta se ei ole esimerkin opetuksellinen pointti, joten tyydytään yllä esitettyyn. OHJ-1100 Ohjelmointi I 74 Algoritmin toteutus C++:lla #include <iostream> #include <iomanip> using namespace std; void TulostaErotinVaakarivi( ) { cout << "+ " << "+ +" << endl; void TulostaOtsikkorivi( ) { cout << " x 1 2 3 4 5 6 7 8 9 " << endl; void TulostaKertotaulurivi( int kertoja) { cout << " " << kertoja << " "; int kerrottava = 1; while (kerrottava <= 9) { cout << setw(3) << kertoja kerrottava; ++kerrottava; cout << " " << endl; OHJ-1100 Ohjelmointi I 75 int main( ) { TulostaErotinVaakarivi( ); TulostaOtsikkorivi( ); TulostaErotinVaakarivi( ); int luku = 1; while (luku <= 9) { TulostaKertotaulurivi( luku); ++luku; TulostaErotinVaakarivi( ); OHJ-1100 Ohjelmointi I 76 Mitä siitä opittiin Lisäämällä ohjelman alkuun rivi #include <iomanip> saadaan käyttöön valmiita työkaluja, joilla tulostuksen ulkoasua voidaan ohjailla. Esimerkiksi tulostuskentän leveys saadaan asetettua setw ohjauskomennolla. Ohjelman monimutkaisuutta voidaan helpommin hallita jakamalla sen toiminnot osiin aliohjelmien (proseduurien) avulla: jokainen aliohjelma toteuttaa jonkun ohjelman osatoiminnon, joka saadaan suoritettua aliohjelmaa kutsumalla. Aliohjelmalle voidaan tarvittaessa välittää myös parametreja, jotka»hienosäätävät» sen toimintaa.