815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 5 Vastaukset



Samankaltaiset tiedostot
815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

T Olio-ohjelmointi Osa 5: Periytyminen ja polymorfismi Jukka Jauhiainen OAMK Tekniikan yksikkö 2010

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

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

12 Mallit (Templates)

Osoitin ja viittaus C++:ssa

Taulukot. Jukka Harju, Jukka Juslin

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU

Luokassa määriteltävät jäsenet ovat pääasiassa tietojäseniä tai aliohjelmajäseniä. Luokan määrittelyyn liittyvät varatut sanat:

Geneeriset luokat. C++ - perusteet Java-osaajille luento 6/7: Template, tyyppi-informaatio, nimiavaruudet. Geneerisen luokan käyttö.

Metodien tekeminen Javalla

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Osoittimet. Mikä on osoitin?

Java-kielen perusteet

Mallit standardi mallikirjasto parametroitu tyyppi

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Lyhyt kertaus osoittimista

Jakso 4 Aliohjelmien toteutus

A TIETORAKENTEET JA ALGORITMIT

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

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

815338A Ohjelmointikielten periaatteet Harjoitus 4 vastaukset

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

ITKP102 Ohjelmointi 1 (6 op)

tietueet eri tyyppisiä tietoja saman muuttujan arvoiksi

Luokat. Luokat ja olio-ohjelmointi

Luento 4 Aliohjelmien toteutus

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

Jakso 4 Aliohjelmien toteutus

Java-kielen perusteet

Tehtävä 1. TL5302 Olio-ohjelmointi Koe Malliratkaisuja. Tässä sekä a)- että b)-kohdan toimiva ratkaisu:

1. Olio-ohjelmointi 1.1

ITKP102 Ohjelmointi 1 (6 op)

Java-kielen perusteet

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

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. V Geneerisyys

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

T Olio-ohjelmointi Osa 3: Luokka, muodostin ja hajotin, this-osoitin Jukka Jauhiainen OAMK Tekniikan yksikkö 2010

Olio-ohjelmointi Syntaksikokoelma

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

Ohjelmoinnin perusteet Y Python

Listarakenne (ArrayList-luokka)

1. Omat operaatiot 1.1

Tietotyypit ja operaattorit

Muuttujien roolit Kiintoarvo cin >> r;

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

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

Luento 4 Aliohjelmien toteutus

Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes)

15. Ohjelmoinnin tekniikkaa 15.1

Harjoitustyö: virtuaalikone

18. Abstraktit tietotyypit 18.1

Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto

Yksikkötestaus. import org.junit.test; public class LaskinTest public void testlaskimenluonti() { Laskin laskin = new Laskin(); } }

Aliohjelmatyypit (2) Jakso 4 Aliohjelmien toteutus

Luento 4 Aliohjelmien toteutus

13 Operaattoreiden ylimäärittelyjä

Virtuaalifunktiot ja polymorfismi

Taulukot. Taulukon määrittely ja käyttö. Taulukko metodin parametrina. Taulukon sisällön kopiointi toiseen taulukkoon. Taulukon lajittelu

TIE Ohjelmistojen suunnittelu

Tietueet. Tietueiden määrittely

Ohjelmoinnin jatkokurssi, kurssikoe

Ohjelmointi 1 Taulukot ja merkkijonot

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

Periytyminen. Luokat ja olio-ohjelmointi

Operaattoreiden uudelleenmäärittely

Jakso 4 Aliohjelmien toteutus

4. Luokan testaus ja käyttö olion kautta 4.1

815338A Ohjelmointikielten periaatteet Harjoitus 2 vastaukset

Jakso 4 Aliohjelmien toteutus. Tyypit Parametrit Aktivointitietue (AT) AT-pino Rekursio

JUnit ja EasyMock (TilaustenKäsittely)

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

Luento 4 Aliohjelmien toteutus. Tyypit Parametrit Aktivointitietue (AT) AT-pino Rekursio

Olio-ohjelmoinnissa luokat voidaan järjestää siten, että ne pystyvät jakamaan yhteisiä tietoja ja aliohjelmia.

Luento 4 (verkkoluento 4) Aliohjelmien toteutus

C++11 Syntaksi. Jari-Pekka Voutilainen Jari-Pekka Voutilainen: C++11 Syntaksi

Javan perusteita. Janne Käki

Olio-ohjelmointi Javalla

7. Oliot ja viitteet 7.1

Rakenteiset tietotyypit Moniulotteiset taulukot

C# olio-ohjelmointi perusopas

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

Osoittimet ja taulukot

Mikä yhteyssuhde on?

Monipuolinen esimerkki

ITKP102 Ohjelmointi 1 (6 op)

9. Periytyminen Javassa 9.1

15. Ohjelmoinnin tekniikkaa 15.1

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

11. oppitunti III. Viittaukset. Osa. Mikä on viittaus?

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

Loppukurssin järjestelyt

9. Periytyminen Javassa 9.1

1 Tehtävän kuvaus ja analysointi

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

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

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

Ohjelman virheet ja poikkeusten käsittely

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Transkriptio:

815338A Ohjelmointikielten periaatteet 2015-2016. Harjoitus 5 Vastaukset Harjoituksen aiheena ovat aliohjelmat ja abstraktit tietotyypit sekä olio-ohjelmointi. Tehtävät tehdään C-, C++- ja Java-kielillä. Ellei koneellasi ole kääntäjää, voit suorittaa ohjelman osoitteessa https://ideone.com/ tai http://www.tutorialspoint.com/codingground.htm. C++-koodia voi suorittaa myös osoitteessa http://cpp.sh/. Tehtävä 1. C -kielessä voidaan saada pinon sisältö näkymään (väärin)käyttämällä printf - funktiota. Kun funktiota kutsutaan ilman parametreja seuraavasti: printf("pinossa on nyt:\n%p\n%p\n%p\n%p\n"); saadaan pinosta 16 ylintä tavua heksamuodossa näkyviin. Kirjoita C-kielinen funktio #include <stdio.h> #include <string.h> void stack_fun(char *strparam) { char mjono[8]; printf("pinossa:\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n" ); strcpy(mjono,strparam); printf("pinossa:\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n%p\n" ); ja kutsu tätä jokin merkkijono parametrina. Etsi merkkijonosi merkkien ASCII -koodit taulukosta. Löydätkö merkkejä pinosta? Mitä tapahtuu, jos parametrimerkkijono on pitempi kuin 7 merkkiä? Mitä seuraamuksia tällä voi olla (muista että myös paluuosoitetta säilytetään pinossa)? Vastaus. Harjoituksen yhteyteen linkitetyssä tiedostossa T1_Pinomuisti.c on ohjelma, jonka pääohjelmassa kutsutaan funktiota call_fun(), joka sisältää paikallisen muuttujana funktiolle stack_fun() välitettävän merkkitaulukon. Taulukon koko on määritelty vakiona PUSKURIN_KOKO, jonka arvo on ohjelmassa nyt 8. Taulukkoon kopioidaan pieniä a- kirjaimia, joiden ASCII-koodi heksalukuna on 61. Pinomuistin tulostuksesta huomataan, että koodit näkyvät pinossa, josta on varattu tila funktion paikalliselle merkkitaulukolle. Koska funktio strcpy kopioi merkkejä, kunnes lähdemerkkijonosta löytyy lopettava nollamerkki, lähdemerkkijonon merkkejä kopioidaan pinomuistiin mahdollisesti varatun tilan yli. Kun merkkejä tulee riittävästi, kopioidaan pinossa säilytettävän paluuosoitteen päälle, mikä johtaa ohjelman kaatumiseen. Kun käänsin ohjelman gcc-kääntäjällä, ohjelma kaatui, kun PUSKURIN_KOKO oli 17. Arvo voi vaihdella kääntäjäkohtaisesti ja kääntäjän asetusten mukaan. Harjoitusluokassa ohjelma kaatui jo, kun PUSKURIN_KOKO oli 9, mutta kun funktioon stack_fun() lisättiin 2-paikkainen taulukko paikalliseksi muuttujaksi, arvoa voitiin kasvattaa huomattavasti ennen ohjelman

kaatumista. Tämä johtuu tavasta, jolla kääntäjä varaa pinosta muistia paikallisille muuttujille. Testaa asiaa omalla kääntäjälläsi. Tehtävä 2. C++- kielessä (toisin kuin C:ssä) funktioita voidaan ylikuormittaa. Lisäksi kääntäjä saattaa tehdä funktion parametreille automaattisia tyypinmuunnoksia. Testaa ensin seuraavaa funktiota kutsumalla sitä pääohjelmasta ainakin seuraavan tyyppisillä parametreilla: double, float, int, short int ja char. Ovatko nämä kaikki kutsut sallittuja? #include <iostream> using namespace std; void tulosta(double x){ cout << "Doublen tulostus:"<< endl; cout << "Parametri = " << x << endl; Kirjoita sitten funktiosta samannimiset versiot, joissa parametrin tyyppi on doublen asemasta int ja short int. Voidaanko näin menetellä? Jos voidaan, niin tutki mitä funktiota kutsutaan milläkin parametrilla. Vastaus. Funktiota voidaan kutsua kaikilla tehtävässä mainituilla parametrityypeillä. Tällöin tapahtuu parametrin automaattinen tyypinmuunnos double-tyyppiseksi. Tiedostossa T2_CppOverloading.cpp, joka on linkitetty harjoituksen yhteyteen, on kirjoitettu funktiosta ylikuormitettu versio kaikille mainituille parametrityypeille. Ajettaessa ohjelmaa huomataan, että kutsu ohjautuu tyypinmukaiselle versiolle funktiosta. Kun funktiosta jätetään ainoastaan versio, jonka parametri on char-tyyppinen, huomataan että tässäkin tapauksessa funktiota voidaan kutsua kaikilla ohjelman parametrityypeillä. Nyt kutsussa tapahtuu automaattinen kaventava tyypinmuunnos, jollaisia on yleensä syytä varoa. Tehtävä 3. Kirjoita C++ -kielellä geneerinen aliohjelma, joka laskee mitä tahansa numeerista tietoa sisältävän taulukon alkioiden summan. Testaa aliohjelmaasi int- ja double-tyyppisillä taulukoilla. Ohje: Katso mallia luentojen geneerisestä lajittelufunktiosta. Vastaus. Harjoituksen yhteyteen linkitettyyn tiedostoon T3_CppGenerics.cpp on toteutettu vaadittu funktio. Huomaa template-mekanismin ja tyyppiparametrin käyttö.

Tehtävä 4. Kuten muistetaan, pino on tietorakenne, joka säilöö alkioita LIFOperiaatteella (Last In First Out). Pinoon viimeksi laitettu alkio otetaan siis ensimmäiseksi pois. Pino voidaan toteuttaa taulukkoa käyttämällä C++ -luokkana, jonka runko on seuraava: class Pino { private: int *pino_osoitin; int koko; int huippu; ; Pino (int pinonkoko); ~Pino (); void push(int luku); void pop( ); int top( ); bool empty( ); Pino ::Pino (int pinonkoko) { pino_osoitin = new int [pinonkoko]; koko = pinonkoko; huippu = -1; Pino ::~Pino () { delete [] pino_osoitin; void Pino ::push(int luku) { /* metodin runko */ void Pino ::pop( ) { /* metodin runko */ int Pino ::top( ) { /* metodin runko */ bool Pino ::empty( ) { /* metodin runko */ Tämä runko on harjoituksen yhteyteen linkitetyssä tiedostossa pino.cpp. (Yleensä C++luokat laaditaan niin, että luokan määrittely on omassa otsikkotiedostossaan ja metodien toteutukset omassa lähdekooditiedostossaan, mutta yksinkertaisuuden vuoksi kirjoitetaan nyt kaikki koodi yhteen tiedostoon.) Täydennä metodien rungot ja testaa luokkaasi ohjelmassa. Huomaa: Tässä versiossa pinon on tarkoitus toimia siten, että päällimmäinen alkio saadaan kutsumalla funktiota top, kutsu ei poista alkiota pinosta, vaan se poistetaan kutsumalla metodia pop, joka ei palauta mitään. Metodin empty avulla voidaan kysyä onko pino tyhjä. Vastaus. Vaadittu ohjelma on linkitetyssä tiedostossa T4_pino.cpp. Kommentteja on seuraavan tehtävän vastauksen yhteydessä.

Tehtävä 5. Kirjoita Java-versio tehtävän 1 pinosta. Vertaa toteutuksia. Java-kielisen ohjelman runko on harjoituksen yhteyteen linkitetyssä tiedostossa pino.java. Vastaus. Vaadittu ohjelma on linkitetyssä tiedostossa T5_pino.java. Luokan koodi on varsin paljon C++-koodin kaltainen. Seuraavia muodollisia eroja voidaan havaita: C++-luokan määrittely sisältää tyypillisesti vain jäsenmuuttujat ja metodien esittelyt. Metodien toteutukset kirjoitetaan luokan määrittelystä erilleen. Javassa myös metodien toteutukset kuuluvat luokan määrittelyyn. Javassa jokaiselle jäsenmuuttujalle ja metodille kirjoitetaan näkyvyysmääre, C++:ssa näkyvyysmääre koskee kaikkia jäseniä, kunnes uusi määre kohdataan. C++:ssa luokkaan kirjoitetaan tavallisesti hajotin, niin tässäkin tapauksessa, jossa sitä tarvitaan vapauttamaan kekodynaamisesti varattu taulukko. Javassa luokan vastaavaa, finalize-metodia tarvitsee vain harvoin toteuttaa. C++-version pääohjelmassa pino voidaan luoda paikalliseksi muuttujaksi, kun Java-ohjelmassa olio on aina varattava kekomuistista. Tehtävä 6. C++ -ohjelmassasi on seuraavat luokkien määrittelyt: #include <iostream> using namespace std; class Base { virtual void metodi() = 0; ; class Sub : public Base { void metodi(); ; void Sub::metodi() { cout << "Olen Sub-luokan metodi." << endl; ja seuraavat funktiot: void kutsu(base b){ void kutsu(base &b){ void kutsu(base *b){ Mikä tai mitkä näistä funktioiden määrittelyistä ovat sallittuja? Miksi? Tee ohjelma, johon jätetään sallittujen funktioiden määrittelyt ja niitä kutsutaan pääohjelmasta käyttäen

parametrina pääohjelmassa luotua Sub-luokan oliota. Lisää funktioihin luokan metodin kutsu ja tarkkaile ohjelman toimintaa. Vastaus. Vaadittu ohjelma on linkitetyssä tiedostossa T6_CppAbstrClass.cpp. Luokan Base metodi on puhtaasti virtuaalinen (eli abstrakti metodi). Siten luokastakin tulee abstrakti, eikä siitä voi luoda oliota. Näin ollen funktio void kutsu(base b){ ei ole mahdollinen, koska sen parametri on arvoparametri, jolloin parametri on metodin paikallinen muuttuja, johon todellinen parametri kopioidaan. Luokasta Base ei kuitenkaan voi tehdä oliota, joten koodia ei voi kääntää. Sen sijaan viiteparametri ja osoitinparametri voi viitata jonkin Base-luokan aliluokan olioon. Aliluokka voi olla sellainen, josta on mahdollista luoda olioita, joten kaksi muuta funktiota ovat sallittuja. Esimerkkikoodin pääohjelmassa luodaan Sub-luokan olio paikallisena muuttujana. Huomaa, että viiteparametrisen funktion kutsussa parametri annetaan oliona, kun taas osoitinparametrisen funktion kutsuun annetaan olion muistiosoite. Kummassakin tapauksessa metodikutsu funktiossa sidotaan dynaamisesti Sub-luokan metodiin. Kolmanneksi ohjelmassa luodaan Sub-luokan olio kekodynaamisesti ja asetetaan kantaluokan (eli Base-luokan) osoitin osoittamaan luotiin olioon. Kun funktiota kutsu() kutsutaan mainittu osoitin parametrina, tapahtuu dynaamisen sidonnan ansiosta Subluokan metodin kutsu samoin kuin aiemmissakin tapauksissa.