Esimerkki luokkahierarkiasta: C++-kielen IOstream-kirjasto



Samankaltaiset tiedostot
Operaattoreiden ylikuormitus. Operaattoreiden kuormitus. Operaattoreiden kuormitus. Operaattoreista. Kuormituksesta

12 Mallit (Templates)

Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot. Tiedostot

Binäärioperaatiot Tiedostot ja I/O

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

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

Binäärioperaatiot Tiedostot ja I/O

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

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

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

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

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

13 Operaattoreiden ylimäärittelyjä

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

Osoitin ja viittaus C++:ssa

Moduli 5: Kehittyneitä piirteitä

Kääntäjän virheilmoituksia

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

C-kieli mahdollistaa hyvin tiiviin ja samalla sekavan tavan esittää asioita, kuitenkin hyvän ohjelman tulisi olla mahdollisimman helppolukuinen ja

Ohjelmointi 1 Taulukot ja merkkijonot

Olio-ohjelmointi Geneerisyys. 1. Johdanto

Virtuaalifunktiot ja polymorfismi

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

Osoittimet. Mikä on osoitin?

Ohjelmoinnin jatkokurssi, kurssikoe

12. Näppäimistöltä lukeminen 12.1

815338A Ohjelmointikielten periaatteet Harjoitus 3 vastaukset

Ohjelmoinnin perusteet Y Python

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

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

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

Taulukot. Jukka Harju, Jukka Juslin

Olio-ohjelmointi 2. välikoe HYV5SN

Ohjelmoinnin perusteet Y Python

Periytyminen. Luokat ja olio-ohjelmointi

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. I Johdanto ohjelmointiin C++kielellä

Harjoitustyö: virtuaalikone

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

Ohjelman virheet ja poikkeusten käsittely

Syöttö- ja tulostusoperaatiot

8. Näppäimistöltä lukeminen 8.1

Muuttujien roolit Kiintoarvo cin >> r;

Sisällys. JAVA-OHJELMOINTI Osa 6: Periytyminen ja näkyvyys. Luokkahierarkia. Periytyminen (inheritance)

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

7. Näytölle tulostaminen 7.1

Ohjelmoinnin perusteet Y Python

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

Java-kielen perusteet

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

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

9/20: Puhu mun stdinille

Ohjelmoinnin peruskurssi Y1

Ohjelmoinnin perusteet Y Python

Sokkelon sisältö säilötään linkitetyille listalle ja tekstitiedostoon. Työ tehdään itsenäisesti yhden hengen ryhmissä. Ideoita voi vaihtaa koodia ei.

Pythonin Kertaus. Cse-a1130. Tietotekniikka Sovelluksissa. Versio 0.01b

ITKP102 Ohjelmointi 1 (6 op)

Sisältö Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 26.2

Ohjelmoinnin perusteet Y Python

Maahan on pudonnut omenoita, ja Uolevi aikoo poimia niitä. Tiedät jokaisesta omenasta, kuinka painava se on.

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

Java-kielen perusteet

C++ -ohjelmointikieli vs. muut kielet

Standardi mallikirjasto

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

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

Merkkijonot ja C++ Antti-Juhani Kaijanaho. 5. maaliskuuta Vanhojen C++-kääntäjien käyttäjät, huomio! 2 Merkkijonojen perusteet

C++ -ohjelmointikieli vs. muut kielet C C++ C vs. C++: Hello World. C++ -ohjelman kääntämisen vaiheet kuin C-kieli

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Harjoitus 3 (viikko 39)

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

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

Java-kielen perusteita

Ohjelmoinnin peruskurssi Y1

TTY Ohjelmointi I & II C++-kirjastoreferenssi versio 2.2

Ohjelmoinnin perusteet Y Python

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

811120P Diskreetit rakenteet

INSIDE C++ Ohjelmoijan käsikirja. Ivor Horton WROX PRESS

2. C-kieli ja ongelmanratkaisu

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmointiharjoituksia Arduino-ympäristössä

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

Työ tehdään itsenäisesti yhden hengen ryhmissä. Ideoita voi vaihtaa koodia ei.

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

Metodien tekeminen Javalla

ITKP102 Ohjelmointi 1 (6 op)

T Sovellusohjelmat Matlab osa 4: Skriptit, funktiot ja kontrollirakenteet

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

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

Rajapinnasta ei voida muodostaa olioita. Voidaan käyttää tunnuksen tyyppinä. Rajapinta on kuitenkin abstraktia luokkaa selvästi abstraktimpi tyyppi.

Ohjelmoinnin perusteet Y Python

812336A C++ -kielen perusteet,

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

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

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

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

Ohjelmoinnin perusteet Y Python

Transkriptio:

Esimerkki luokkahierarkiasta: C++-kielen IOstream-kirjasto Tässä materiaalissa tutustutaan tarkemmin C++:n luokkahierarkiaan. Koska kyseessä on oliopohjainen kieli, C++:n luokat on järjestetty hierarkisesti aikaisemmin tarkasteltuja periytymissääntöjä noudattaen. Hierarkiassa on yksi tai joissain tapauksissa useampia kantaluokkia, joista periytyy johdettuja luokkia. Virta eli stream on abstrakti käsite, joka tarkoittaa laitetta, johon ohjelmassa tapahtuvat syöttö- ja tulostusoperaatiot kohdistuvat. Virta voidaan ajatella loppumattomaksi merkkien virraksi, jota luetaan ja johon tulostetaan. Virrat ovat yleensä liitetty (assosioitu) johonkin fyysiseen laitteeseen kuten esimerkiksi tiedostoon, näppäimistöön, näyttöön tai tietoliikenneporttiin. Oletusarvoisesti merkkejä luetaan standardisyötöstä (stdin) joka on yleensä näppäimistö ja kirjoitetaan standarditulostuslaitteelle (stdout) joka on tietokoneen näyttö. Merkkien lisääminen virtaan tarkoittaa siis konkreettisesti merkkien lähettämistä jollekin fyysiselle laitteella ja lukeminen virrasta merkkien vastaanottamista laitteelta. Koko C++-kielen syöttö- ja tulostusjärjestelmä eli I/O-järjestelmä voidaan esittää oheisen luokkahierarkia mukaisesti. Kaaviossa luokat ovat valkealla pohjalla ja luokan metodit mustalla.

Kantaluokka on nimeltään ios_base ja se on määritelty otsikkotiedostossa <ios>. ios_base-luokan johdettu luokka on nimeltään ios. Tästä on edelleen johdettu luokat istream ja ostream. Luokkien määritykset sisältävät otsikkotiedostot (header files) eli kirjastot on kaaviossa ilmoitettu < >-merkkien sisällä. Yhdessä kirjastossa (esim <fstream>) voi siis olla määriteltynä monta luokkaa (kuvassa ifstream, fstream, ofstream ja filebuf). Syöttövirta <istream> Istream-oliot lukevat (read) ja tulkitsevat (interpret) syötteikseen saamiaan merkkejä (esimerkiksi näppäimistöltä tai tiedostosta). Luokalla on kahdentyyppisiä jäsenfunktioita: Muotoiltu syöttö (formatted input) o Nämä funktiot lukevat merkkejä käyttäen ylikuormattua >> operaattoria ja muuntavat ne määrätyn tyyppiseksi tiedoksi. o Esimerkkinä tämän tyyppisestä syötöstä on cin-metodi. Muotoilematon syöttö (unformatted input) o Nämä eivät tulkitse lukemiaan merkkejä tietyn tyyppiseksi tiedoksi.

o Lukevat syöttövirrasta merkkejä käyttäen metodeja get, getline, peek, read, readsome, manipuloivat get-osoitinta tai hakevat tietoa viimeisestä muotoilemattomasta syöttöoperaatiosta (gcount). Tulostusvirta <ostream> Ostream-oliot kirjoittavat (write) ja muotoilevat merkkejä määritellylle tulostuslaitteelle (esimerkiksi näyttö tai tiedosto). Myös nämä voidaan jakaa kahteen ryhmään: Muotoiltu tulostua (formatted output) o Jäsenfunktiot tulkitsevat ja muotoilevat tulostettavat merkit käyttäen ylikuormattua << operaattoria. o Esimerkkinä tämän tyyppisestä tulostuksesta on cout-metodi. Muotoilematon tulostua (unformatted output) o Jäsenfunktiot kirjoittavat dataa siinä muodossa kuin ne sen saavat, ilman tyyppimuunnoksia tai muotoiluja. o Metodeja put, write, seekp, tellp Muotoiltu syöttö- ja tulostus tarkoittavat käytännössä ASCII-muotoisen tiedon käsittelyä ja muotoilematon binäärisen tiedon käsittelyä (erityisesti tiedostojen tapauksessa). Syöttö- ja tulostusvirta <iostream> Luokkahierarkiakaaviosta nähdään, että paljon käyttämämme iostream-luokka on johdettu sekä luokasta istream (input stream) että ostream (output stream). Tällaista periytymistä sanotaan moniperinnäksi (multiple inheritance).

iostream-luokka perii sekä istream- että ostream-luokkien kaikki jäsenfunktiot. Siten se voi hoitaa samalla kertaa sekä syöttö- että tulostustoiminnot. Jokaisessa kirjoittamassamme C++-ohjelmassa on ollut alussa rivi #include<iostream>. Tällä esikääntäjän direktiivillä on siis otettu käyttöön fyysinen, kovalevylle tallennettu iostream-otsikkotiedosto, joka sisältää varsinaisen iostream-luokan toteutuksen eli implementoinnin. Puskuriluokka <streambuf> Palataan vielä luokkahierarkiakuvaan. Kuvasta nähdään, että kantaluokista ios tai ios_base ei ole nuolta luokkaan streambuf, vaikka se luokkahierarkiassa on samalla tasolla istream- ja ostream-luokkien kanssa. Luokka streambuf toimii kantaluokkana kaikille ns. puskuroitua tietoa käsitteleville luokille (stream buffers). Tällaista puskuroitua tietoa tuottavat esimerkiksi vaikkapa tietokoneeseen USB- tai sarjaportin kautta kytketyt mittauslaitteet. Myöskin tiedostojen luku ja kirjoitus käyttää hyväkseen puskuria. Puskuri on fyysisesti tietokoneen muistissa oleva muistialue, joka varataan dynaamisesti tiedon väliaikaistallennukseen ja jonka odotetaan olevan ajan tasalla ulkoisen tiedonlähteen tuottaman tiedon kanssa. Esimerkiksi mittauslaite tallentaa tietoa puskurin toiseen päähän samalla kun sitä luetaan tietokoneen työmuistiin toisesta päästä. Streambuf on ns. abstrakti kantaluokka. Abstraktista kantaluokasta ei voi luoda suoraan luokan instansseja eli olioita, vaan abstraktista luokasta on johdettava luokkia, joiden avulla varsinaiset oliot luodaan (tuntiesimerkkinä käytetty muoto-luokka oli itse asiassa abstrakti luokka).

Streambuf-luokalla on kaksi johdettua luokkaa: filebuf ja stringbuf eli tiedostopuskuri- ja merkkijonopuskuriluokat. Tiedostovirta <fstream> Fstream-kirjasto käsittele tiedostoon kirjoitusta ja lukua. Luokkahierarkiasta nähdään, että se sisältää luokat: ifstream o Johdettu istream-luokasta o Input File Stream, lukee tietoa tiedostosta ofstream o Johdettu ostream-luokasta o Output File Stream, kirjoittaa tietoa tiedostoon fstream o Johdettu iostream-luokasta o Sekä luku että kirjoitus toteutettuna samassa luokassa filebuf o Johdettu luokasta streambuf o Tiedostopuskuri o Fyysisen tiedoston yhdistäminen väliaikaismuistiin Merkkijonovirta <sstream> Luokassa sstream eli string stream tarjoaa käyttöliittymän merkkijonojen käsittelyyn virtoina. Tämä kirjasto mahdollistaa automaattiset ja turvalliset tietotyyppimuunnokset.

Tyyppimuunnoksista esimerkkinä olisi vaikkapa ohjelma, joka odottaa käyttäjältä syötteekseen liukulukua. Jos käyttäjä syöttääkin merkkijonon, ohjelma kaatuu ajonaikaiseen virheeseen tai jää ikuiseen silmukkaan. Turvallinen vaihtoehto on lukea kaikki tieto ensin sisään merkkijonoina ja vasta ohjelmassa yrittää muuttaa tieto halutun tyyppiseksi. Jos muunto ei onnistu, kysytään uudestaan niin kauan että onnistuu. C-kielessä vastaava toteutus tehtiin funktioilla atoi(), sprintf() ja sscanf(). Niiden toteutukseen liittyy pari pahaa ongelmaa: C:ssä ei ole string-luokkaa. Vaikka C mahdollistaa dynaamisen muistinvarauksen ja dynaamiset taulukot, käytännössä niiden käyttö on niin hankalaa että merkkijonot yleensä määritellään vakiomittaisiksi (tyyliin char mj[100];). Jos tyypinmuunnoksen tulos on pidempi kuin taulukon koko, tapahtuu ylivuoto. Tätä ylivuotobugia monet crackerit hyödyntävät pyrkiessään murtautumaan koneisiin verkon yli. Puutteellinen tyyppiturvallisuus (type safety). Stdio-kirjaston funktioissa ei ole tyypin tarkistusmekanismeja. Siten ohjelmat jotka käyttävät vääriä muotoilumääreitä (%d, %s, jne ) aiheuttavat ohjelman joutumisen epämääräiseen tilaan eli ylikirjoittavat muistia väärästä paikasta. Merkkijonovirtakirjasto sisältää seuraavat luokat: istringstream o Johdettu luokasta istream o Merkkijonojen käsittely syöttövirtoina ostringstream o Johdettu luokasta ostream o Merkkijonojen käsittely tulostusvirtoina Stringstream o Johdettu luokasta iostream

o Merkkijonojen käsittely syöttö- ja tulostusvirtoina Stringbuf o Johdettu luokasta streambuf o Puskuriluokka merkkijonojen tallennukseen tietokoneen muistiin. Esimerkkejä Katsotaan seuraavaksi muutama esimerkki IOstream-kirjaston luokkien käytöstä. Esimerkki 1: Merkkitiedon kirjoitus tiedostoon. Ohjelma lukee käyttäjän syöttämiä merkkejä yksitellen niin kauan kuin syötetään EOF eli CTRL-Z. Teksti tallentuu tiedostoon teksti.txt. #include <iostream> #include <fstream> using namespace std; int main() char c; ofstream tiedosto; int lkm=0; tiedosto.open("d:\\teksti.txt"); while ((c=cin.get())!=eof) tiedosto << c; lkm++; tiedosto.close();

cout << "Kirjoitettiin " << lkm << " merkkiä."<< endl; system("pause"); return 0; Esimerkki 2: Luetaan tekstitiedostoa merkki kerrallaan. #include <iostream> #include <fstream> using namespace std; int main() char c; ifstream tiedosto; int lkm=0; tiedosto.open("d:\\teksti.txt"); while ((c=tiedosto.get())!=eof) cout << c; lkm++; tiedosto.close(); cout << "Luettiin " << lkm << " merkkiä."<< endl; system("pause"); return 0;

Esimerkki 3: Ohjelma kysyy käyttäjältä tuotteen hinnan ja kappalemäärän merkkijonoina, muuttaa ne liukuluvuksi ja kokonaisluvuksi sekä tulostaa kokonaishinnan. #include <iostream> #include <sstream> using namespace std; int main () string mjono; float hinta=0; int maara=0; cout << "Hinta: "; getline (cin,mjono); stringstream(mjono) >> hinta; cout << "Kappalemäärä: "; getline (cin,mjono); stringstream(mjono) >> maara; cout << "Kokonaishinta: " << hinta*maara << endl; system("pause"); return 0; Esimerkki 4: Ohjelmassa määritellään stringstream-olio s ja sijoitetaan siihen kaksoistarkkuuden liukulukumuuttujan d arvo. <sstream>-kirjasto käyttää ylikuormattuja << ja >> operaattoreita. #include <sstream> using namespace std; int main()

double d=123.456; stringstream s; string str; s << d; // insert d into s s >> str; //insert string Esimerkki 5: Seuraavassa ohjelmassa määritellään stringstream-olio ja sijoitetaan double-tyyppisen muuttujan d arvo 123.456 siihen käyttäen << operaattoria. Luku voidaan muuttaa string-merkkijonoksi käyttämällä >> operaattoria. #include <iostream> #include <sstream> using namespace std; int main () double d=123.456; stringstream s; string val; s << d; // tallennetaan d s:ään s >> val; //muunnetaan s:n sisältämä arvo merkkijonoksi //val sisältää arvon 123.456 merkkijonona //tulostetaan normaalisti cout:lla: cout << d << " " << val << endl; system("pause"); return 0; Päinvastainen muunnosta stringistä doubleksi on yhtä yksinkertainen.