C/C++  Win32  MFC  Java

C/C++ teoria
Johdanto C++-kieleen
Luokat ja oliot
Luokat tarkemmin
Taulukot, osoittimet ja referenssit
Funktion kuormitus
Operaattorin kuormitus
Perintä
C++:n I/O järjestelmän perusteet
C++:n I/O järjestelmän kehittyneemmät piirteet
Virtuaalifunktiot
Sekalaisia C++ asioita
Tehtävät
Tehtävät 1
Tehtävät 2
Tehtävät 3
Tehtävät 4
Tehtävät 5
Tehtävät 6
Tehtävät 7
Tehtävät 8
Tehtävät 9
Tehtävät 10
Tehtävät 11
 
Tehtäviä
Johdanto C++-kieleen
  • Käytä << ja >> operaattoreita. Tee ohjelma, joka lukee työntekijän työtuntien lukumäärän ja tuntipalkan sekä tulostaa maksettavan palkan.
  • Tee ohjelma, joka muuttaa tuumat senteiksi: Pyydä käyttäjältä tuumat ja tulosta sentit. Toista kunnes annetaan 0.
  • Muuta oheinen ohjelma siten, että se käyttää C++ tyylistä standardi I/O:ta.
    #include <stdio.h>
    
    int	main(void){
    	int a, b, d, min;
    	printf("Enter two numbers: ");
    	scanf( "%d%d", &a, &b );
    	min = a > b ? b : a;
    	for (d = 2; d < min; d++ )
    		if ((( a % d ) == 0 ) && (( b % d ) == 0 )) break;
    	if ( d == min )
     		printf("No common denominators\n");
    	else
    		printf("The lowest common denominator is %d\n", d);
    	return 0;
    }
  • Miksi seuraava ohjelma ei käänny?
    #include <iostream.h>
    
    main (){
    	char s[ 80 ];
    	cout << "Anna merkkijono: ";
    	cin >> s;
    	cout << "Pituus on " ;
    	cout << strlen ( s );
    	return 0;
    }
  • Kuormita neliöjuurifunktiota sroot(), siten että sitä käytetään int, long ja double-tyypeille. Käytä math.h:n sqrt-funktiota itse neliöjuureen.
  • C:ssä on funktiot atof, atol ja atoi. Miksei näitä voi kuormittaa ?
  • Kuormita minimi-funktiota, siten että voidaan ottaa minimi kahdesta merkistä, kokonaisluvusta ja double-luvusta.
  • Kuormita odota-funktiota, siten että odota(10) ja odota("10") molemmat pysäyttävät koneen 10 sekunniksi.
  • Tee funktio rev_str, joka tulostaa merkkijonon väärinpäin. Kuormita funktiota siten, että
    a)
    funktiolle annetaan argumenttina taulukko, jossa on merkkijono, funktio muuttaa merkkijonon alkuperäisen tilalle.
    b)
    funktiolle annetaan kaksi taulukkoa, toisessa on alkuperäinen merkkijono ja toiseen viedään muutettu merkkijono.
    Esim.
    ...char	s1[80], s2[80];
    ...cout	<< "Anna merkkijono: ";
    cin >> s1;
    rev_str( s1, s2 );
    rev_str( s1 );...
  • Tee luokka, joka ylläpitää nimi ja osoiteinformaatiota. Laita luokkaan private-puolelle merkkijonot nimi ja osoite sekä public-puolelle funktiot: talleta ja näytä. Tee pääohjelmaan 3-alkioinen taulukko, joka sisältää ko. luokan olioita sekä lisäys ja tulostus-komennot.
Luokat ja oliot
  • Tee ohjelma, jolla voit testata kykyäsi arvioida kulunutta aikaa: Ohjelma tulostaa kahden näppäimen painalluksen välisen ajan. Ohjelma loppuu, kun painat ESC
    Paina jotain, niin aloitetaan ajan laskenta.// painat jotain
    Paina jotain, niin lopetetaan laskenta.// painat 30 s kuluttua
    Aikaa kului 29.02 sekuntia
    Paina jotain, niin aloitetaan ajan laskenta.// painat jotain
    Paina jotain, niin lopetetaan laskenta.// painat 10 s kuluttua
    Aikaa kului 11.67 sekuntia
    Paina jotain, niin aloitetaan ajan laskenta.// painat ESC
  • Luo luokka nimeltä laatikko, jossa konstruktoriin välitetään laatikon sivujen pituudet. Laita luokkaan funktio, jolla tulostetaan seinien pinta-alat sekä funktio, jolla tulostetaan laatikon tilavuus. Tee testiohjelma ko. luokalle.
  • Tee ohjelma, joka käyttää hyväkseen määrittelemääsi luokkaa viiva. Luokan konstruktorissa määritellään viivan alku-ja loppupisteen koordinaatit sekä piirretään viiva. Destruktorissa pyyhitään viiva pois. Voit tehdä ohjelman grafiikkamoodissa tai tekstimoodissa. Tekstimoodissa piirrä viiva vaikka *:ien avulla.
  • Tee luokka arpakuutio, jossa on jäsenfunktio pyorita. Pyorita generoi satunnaisluvun 1-6 ja näyttää sen. Tee ohjelma, joka käyttää arpakuutiota.
Luokat tarkemmin
  • Kokeile ja havaitse seuraavan ohjelman vika.
    #include <iostream.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    class dyna {
    	int *p;
    public:
    	dyna ( int i );	~dyna();
    	int get() { return *p; }
    };
    
    dyna::dyna( int i ){
    	p = (int *) malloc( sizeof(int) );
    	if (!p) {
    		cout << "Varausvirhe\n";
    		exit(1);
    	}
    	cout << "konstruktorissa\n";
    	printf("varataan: %p\n", p );
    	*p = i;
    }
    
    dyna::~dyna(){
    	cout << "destruktorissa\n";
    	printf("vapautetaan: %p\n", p );
    	free( p );
    }
    
    int neg( dyna ob ){
    	return -ob.get();
    }
    
    main(){
    	dyna	o1(-10);
    	cout << o1.get() << "\n";
    	cout << neg(o1) << "\n";
    	dyna	o2(20);
    	cout << o2.get() << "\n";
    	cout << neg(o2) << "\n";
    	cout << o1.get() << "\n";
    	cout << neg(o1) << "\n";
    	return 0;
    }
  • Olion luonnin ja tuhoamisen havainnollistamiseksi tee ohjelma, joka käyttää luokkaa nimeltä "kuka". Kuka:n konstruktorissa on argumenttina olion tunniste, vaikkapa jokin merkki. Konstruktorissa tulostetaan teksti: Luodaan kuka-tyyppinen olio: 'tunniste'. Destruktorissa tulostetaan teksti: Tuhotaan kuka-tyyppinen olio: 'tunniste'. Ohjelmassa käytetään funktiota "luo_kuka", joka palauttaa "kuka"-tyyppisen olion. Jokaiselle oliolle annetaan eri tunnisteet. Tarkastele ohjelman tulosteita siten, että ymmärrät, mistä on kyse.
  • Oletetaan, että järjestelmässä on 1 tulostin ja kaksi eri luokkaa käyttää ko. tulostinta. Ohjelman muiden osien on tiedettävä, milloin jompikumpi edellisistä luokista käyttää tulostinta. Luo funktio in_use(), joka palauttaa true:n, mikäli jomman kumman luokan olio käyttää tulostinta ja false:n mikäli kumpikaan ei käytä tulostinta.
    Ohje: tee in_use()-funktiosta tulostin1 ja tulostin2 luokkien friend ja määrittele molempiin tulostin luokkiin privaatti jäsen kokonaisluku ( 0 tai 1), jonka nimenä on esimerkiksi tulostaa.
  • Käytä dynaamista pinoa ja kirjoita funktio lataapino(), joka palauttaa pinon, joka on täytetty aakkosilla a...z. Sijoita tämä pino toiseen olioon kutsuvassa rutiinissa ja tulosta pinon sisältö. Pidä luokkien konstruktoreissa ja destruktoreissa sekä muistin vapautuksissa ja varauksissa testitulostukset. Huolehdi siitä, että koko pino mahtuu sijoituksessa uuteen olioon.
  • Kuormita edellisen tehtävän lataapino-funktiota siten, että argumentilla ISOT (=1), pinoon laitetaan isoja kirjaimia.
Taulukot, osoittimet ja referenssit
  • Käytä seuraavaa luokkamäärittelyä ja luo 10 alkioinen taulukko, jossa ch-alkiot on alustettu arvoihin A:sata J:hin. Tulosta taulukko.
    class kirjaimet {
    	char ch;
    public:
    	kirjaimet( char c ) { ch = c; }
    	char hae_kirjain( ) { return ch; }
    };
  • Käytä seuraavaa luokkamäärittelyä ja luo 10-alkioinen taulukko, jossa luku on alustettu arvoihin 0, 1, 2, 3, ... 9 ja nelio arvoihin 0, 1, 4, 9, ... 81. Tulosta taulukko.
    class neliot {
    	int luku, nelio;
    public:
    	neliot( int a, int b ) { luku = a; nelio = b; }
    	void show( ) { cout << luku << ' ' << nelio << "\n"; }
    };
  • Kokeile new:ta ja deleteä se. luot 3 muuttujaa, yksi float, yksi long ja yksi char-tyyppinen. Anna näille dynaamisille muuttujille arvot ja tulosta ne. Vapauta lopuksi varaamasi muisti deletellä.
  • Luo luokka, joka sisältää henkilön nimen ja puhelinnumeron. Luo new:n avulla kyseisen luokan olio, anna arvot nimelle ja puhelinnumerolle, tulosta ne ja tuhoa olio.
  • Tee funktio swap, joka vaihtaa argumentteina välitettyjen muuttujien arvot keskenään. Käytä referenssiä ja kokeile funktiotasi.
  • Tee funktio round, joka pyöristää double-tyyppisen luvun (4.45 -> 4.0, 5.51 -> 5.0 jne ). Käytä standardikirjastofunktiota modf, jolla saat selville kokonaisosan ja desimaaliosan. Käytä referenssiä ja kokeile funktiotasi.
  • Luo luokka ja käytä sitä. Luokka ylläpitää 2-ulotteista turvataulukkoa (raja-arvotarkistukset) kokonaisluvuille.
  • Olkoon määriteltynä seuraava luokka. Luo 2-ulotteinen taulukko (2 x 5) ja anna kaikille alkioille alkuarvot.
    #include <iostream.h>
    
    class a_tyyppi {
    	double	a, b;
    public:
    	a_tyyppi( double  x, double  y ) { a = x; b = y; }
    	void show( ) { cout << a << "  " << b << "\n"; }
    };
  • Muuta sovellustasi siten, että taulukkoa käsitellään osoittimen avulla.
  • Tee funktio kaanteinen, jolle välitetään argumenttina double-tyyppisen muuttujan referenssi. Funktio muuttaa luvun käänteisluvukseen ( 5 -> 0.2, 20 -> 0.05 )
  • Toteuta aiemmin ollut dynaaminen pino siten, että käytät copy-konstruktoria: destruktorissa suoritetaan tilan vapautus, copy-konstruktorissa muodostat identtisen pinon argumenttina olevasta pinon referenssistä (muistivaraukset ja arvojen asetukset).
Funktion kuormitus
  • Kuormita edellistä dateT-luokan konstruktoria edelleen siten, että argumenttina voidaan antaa systeemin tuntema time_t-tyyppinen argumentti.

    HUOM. Kun C++ kehitettiin kuormitukseen käytettiin avainsanaa overload, nykyään tätä ei tarvita, joten sen käyttöä on syytä välttää ( Esimerkiksi dateT-kuormituksessa, ennen kuormitettavia funktioita oli kerrottava: overload dateT; ) Kieliopillisesti tämä on edelleen sallittua, muttei ehkä kauaa uudemmissa kääntäjissä.

  • C:n standardikirjastossa on funktio strtol, jonka viimeisenä argumenttina käytetään useimmiten arvoa 10. Tee omastrtol-funktio, jossa viimeisen argumentin voi jättää pois.
  • Borland C++:n kirjastossa on funktio void clreol(void); joka tyhjentää rivin loppuun kursorin kohdasta lähtien. Tee omaclreol, jolle voidaan antaa argumenttina merkkien lukumäärä, kuinka monta merkkiä tyhjennetään. Jos argumenttia ei anneta kutsussa, tyhjennetään rivi loppuun.
  • Ohessa kuormitettu dif-funktiota, käytä funktion osoitetta ja kokeile.
    int dif( int a, int b ){
    	return a-b;
    }
    
    float dif( float a, float b ){
    	return a-b;
    }
  • Tee funktio takaperin, joka muuttaa merkkijonon takaperin. Funktiolle annetaan 3 argumenttia, ensimmäisessä source-nimisessä argumentissa välitetään muutettava merkkijono, toisessa target-nimisessä palautetaan muutettu merkkijono. Kolmannessa argumentissa count kerrotaan, kuinka monta ensimmäistä merkkiä muutetaan, oletusarvona muutetaan koko merkkijono.
    Esimerkki:
    	source		count		target
    	Kissantassu	6		nassiKtassu
    	Kissantassu	2		iKssantassu
    	Kissantassu	9		satnassiKsu
    	Kissantassu	0		Kissantassu
    	Kissantassu	-		ussatnassiK

    Testaa funktiotasi.

  • Tee funktio jarjesta, joka jarjestaa argumentteina tulleet kaksi kokonaislukua siten, että ensimmäisessä argumentissa palautetaan ( käytä referenssejä) suurempi ja toisessa pienempi. Oletusarvoisesti ensin suurempi, kolmannessa argumentissa voidaan kertoa suunta.
    Esim: 	int x = 1, y = 5;
    	jarjesta( x, y ); // -> x:ssä on 5 ja y:ssä 1
  • Ohessa ohjelman osaa, lisää puuttuvat kohdat (konstruktorifunktiot).
    class samp {
    	int a;
    public:	int
    	get_a() {
     return a;
     }
    };
    
    main(){
    	samp  ob( 88 );
    	samp  taulu [ 10 ];
    	cout << "\n";
    	cout << ob.get_a();
    	cout << "\n";
    	for ( int i=0; i < 10; i++)
    		cout << taulu[ i ].get_a() << " ";
    	return 0;
    }
Operaattorin kuormitus
  1. Tee coord-luokka, joka toteuttaa kaikki aritmeettiset operaatiot (+ , - , / , * , = ) kokonaisluvuille ja coord-tyyppisille olioille. Esim: o1 = ( o2 / o3 + 5 )* 2;
  2. Työstä luvun 3 mjono-esimerkki siten, että käytät copy-konstruktoria ja mjono tyyppinen olio voidaan luoda seuraavasti: mjono ob;.
    Kuormita sijoitusoperaattoria siten, että mjono tyyppisille olioille on mahdollista:mj1 = mj2.
    Kuormita mjonolle sijoitusoperaattoria const char * tyyppiselle oliolle siten, että mj1 = "Kissa" on mahdollista.
    Kuormita + operaattoria siten, että katenoit ko. mjono-tyyppiset merkkijonot ( mj1 = m2 + mj3 ) sekä mjono tyyppinen olio ja const char * tyyppinen olio ( mj1 = mj2 + "Kissa" ).
    Kuormita - operaattoria siten, että merkkijonosta etsitään ja poistetaan annettu mjono tyyppinen merkkijono tai vakiomerkkijono ( mj1 = mj2 - mj3 ja mj1 = mj2 - "Kissa" ).
    Keksi itse lisää tilanteita.
    Laita testitulosteet kaikkialle, missä varaat tai vapautat muistia.
  3. Kuormita < ja > operaattoreita coord-luokassa.
  4. Lisää merkkijonoluokkaan <, >, ==, != jne. operaattoreiden kuormitus.
  5. Käytä friend-operaattorikuormitusta ja coord-luokkaa. Kuormita +, -, /, *, <, >, jne kaikkia, joille keksit järkevän käytön.
  6. Kuormita seuraavaa luokkaa +, -, ++, --, ==, != ja || operaattoreilla, sekä siten että seuraavat yhteenlaskut ovat mahdollisia ob + double ja double + ob.
    class kolmen_piste {
    	int x, y, z;
    public:
    	kolmen_piste( int i, int j, int k )
    		{ x = i; y = j; z = k; }
    	kolmen_piste( )
    		{ x = 0; y = 0; z = 0; }
    	void get( int &i, int &j, int &k )
    		{ i = x; j = y; k = z; }
    };
Perintä
  • Tee luokka johdettu2 (private-muuttujana int d, public-funktioina sopivat set- ja get-funktiot), joka perii luokan johdettu. Kokeile ja selvitä, mitä muuttujia pystytään käsittelemään johdettu2:ssa luokan jäsenfunktioissa ja main:ssa.
    • johdettu perii kanta-luokan public-tyyppisesti ja johdettu2 johdettu-luokan public-tyyppisesti
    • johdettu perii kanta-luokan public-tyyppisesti ja johdettu2 johdettu-luokan private-tyyppisesti
    • johdettu perii kanta-luokan private-tyyppisesti ja johdettu2 johdettu-luokan public-tyyppisesti
    • johdettu perii kanta-luokan private-tyyppisesti ja johdettu2 johdettu-luokan private-tyyppisesti
  • Ohessa osa ohjelmaa. Tee johdetulle luokalle konstruktorifunktio.
    #include <iostream.h>
    #include <string.h>
    
    class mybase {
    	char str[80];
    public:	mybase( char *s ) {
     strcpy( str, s );
     }
    	char *get() {
     return str;
     }
    };
    
    class myderived : public mybase {
    	int len; // merkkijonon pituus
    
    public:	// konstruktori
    	int getlen() {
     return len;
     }
    
    	void show() {
     cout << get() << "\n";
     }
    };
    
    main(){
    	myderived ob("Hello");
    	ob.show();
    	cout << ob.getlen() << '\n';
    	return 0;
    }
  • Käytä seuraavaa koodin osaa ja toteuta sopivat auto_o ja kuormuri konstruktorit:
    #include <iostream.h>
    
    class ajoneuvo {
    	int 	pyorien_lkm;
    	int 	paino;
    public:	ajoneuvo( int y, int a ) {
     pyorien_lkm = y; paino = a;
     }
    	void nayta_ajoneuvo() {
     		cout << " pyöriä: " << pyorien_lkm << "\n";
    		cout << " paino: " << paino << "\n";
    	}
    };
    
    class auto_o : public ajoneuvo {
    	int	matkustajia;
    public:	// konstruktori	
    	void nayta() {
    		nayta_ajoneuvo();
    		cout << " matkustajia: " << matkustajia << "\n";
    	}
    };
    
    class kuormuri : public ajoneuvo {
    	int	kuorman_paino;
    public:	// konstruktori
    	void nayta() {
    		nayta_ajoneuvo();
    		cout << " kuorman paino: " << kuorman_paino << "\n";
    	}
    };
    
    main(){
    	auto_o		toyota( 5, 4, 900 );
    	kuormuri	volvo( 30000, 12, 3000 );
    	cout << "Auto:\n";
    	toyota.nayta();
    	cout << "Kuormuri:\n";
    	volvo.nayta();
    	return 0;
    }
  • Mikä olisi tuloste ohjelman esimerkissä 2, jossa johdettuluokka käyttää samaa argumenttia, jonka se välittää kantaluokkaan, jos kantaluokan määrittely olisi seuraava, muiden osien ohjelmasta pysyessä ennallaan:
    class kanta {
    	int i;
    public:	kanta( int &n ) {
    		cout << "Luodaan kantaluokan olio\n";
    		i = n;
    		n = 5;
    	}	...
  • Luo yleinen luokka: Rakennus, joka ylläpitää tietoa rakennuksen kerrosten ja huoneiden lukumäärästä sekä kokonaispinta-alasta.
    • Luo johdettu luokka: Talo, joka perii rakennuksen ja ylläpitää tietoja makuuhuoneiden ja kylpyhuoneiden lukumääristä.
    • Luo johdettu luokka: Toimisto, joka perii rakennuksen ja ylläpitää tietoja varauloskäytävien ja puhelimien lukumääristä.
    • Tee pääohjelma, jossa kokeilet luokkiesi toimivuutta.
  • Luo luokkahierarkkia, joka ylläpitää tietoja ilma-aluksista. Aloita yleisestä luokasta:ilma_alus, jossa ylläpidetään tietoja matkustajien lukumäärästä ja polttoaineen maksimimäärästä.Luo ilma-aluksesta kaksi johdettua luokkaa: lentokone ja ilmalaiva? (balloon). Lentokoneen ominaisuuksia ovat moottorityyppi (potkuri/suihku) ja maksimilentomatka. Ilmalaivan ominaisuuksia ovat käytetty kaasu (vety/helium) ja maksimikorkeus. Tee pieni ohjelma, jollatestaat luokan toimivuuden.
  • Lisää ohjelmaan puuttuvat osat.
    #include <iostream.h>
    
    class base {
    	int i, j;
    public:	// konstruktori puuttuu	
    	void showij() {
     cout << i << ' ' << j << '\n';
     }
    };
    
    class derived : public base {
    	int k;
    public:	// konstruktori puuttuu
    	void show() {
     cout << k << ' ';
     showij();
     }
    };
    
    main(){
    	derived  ob(1, 2, 3);
    	ob.show();
    	return 0;
    }
C++:n I/O järjestelmän perusteet
  • Tee ohjelma, joka asettaa cout:n liput siten, että positiivisilla luvuillanäytetään etumerkki. Kokeile.
  • Tee ohjelma, joka asettaa cout:n liput siten, että liukuluvuilla näytetäänaina desimaalipiste sekä liukuluvut esitetään eksponenttiesityksenä. Kokeile.
  • Millaisella flags()-funktion kutsulla cout:n liput saadaan oletusarvoisiksi?
  • Tee ohjelma, joka tallettaa cout:n lippujen arvon, asettaa showbase:n ja hex:n,näyttää luvun 100, palauttaa liput alkuperäisiksi ja näyttää uudelleenluvun 100.
  • Tee ohjelma, joka tulostaa luonnollisen logaritmin ja 10-kantaisen logaritmin luvuista 2-100. Tasaa taulukonsarakkeet oikealle ja käytä kentän leveytenä 10:tä. Esitä luvut 5 desimaalilla.
  • Luo funktio: void center( char *s ); Funktio keskittää annetun merkkijonon ruudun keskelle. Oleta, että näyttö on 80 merkkiä leveä ja merkkijono on alle 80 merkkinen.
  • Kokeile itseksesi formaattilippuja ja -funktioita.
  • Tee luvun 8 edellä olevat tehtävät siten, että käytät I/O-manipulaattoreita aina kun mahdollista.
  • Tulosta luku 100 heksadesimaalisena siten, että "0x" näkyy. Käytä setiosflags-manipulaattoria.
  • Seuraavassa on mjono-niminen luokka ja osittainen ohjelma. Lisää insertteri, jokatulostaa merkkijonon. Konstruktoriin ja destruktoriin on laitettu testitulostukset, jotta tiedetään, ettei muistia vapauteta enempää kuin sitä on varattu. Huomaa, että insertterinjälkimmäisen argumentin ei ole pakko olla juuri 'class_name ob'.
    #include <iostream.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    class mjono {
    	char	*p;
    	int	len;
    
    public:	mjono( char *ptr );
    	~mjono();
    };
    
    mjono::mjono( char *ptr ){
    	len = strlen( ptr );
    	if (len > 0){
    		p = new char [len+1];
    		printf("\nVarattu: %p: %d tavua\n", p, len );
    		if (!p) {
    			cout << "Allocation error!\n";
    			exit(1);
    		}
    		strcpy(p, ptr);
    	}
    }
    
    mjono::~mjono(){
    	if (len > 0) {
    		printf("\nVapautetaan: %p: %d tavua\n", p, len );
    		delete p;
    	}
    }
    
    main(){
    	mjono s1("This is a test"), s2("I like C++");
    	cout << s1 << '\n' << s2 << '\n';
    	return 0;
    }
  • Korvaa seuraavassa show-funktio insertterillä.
    #include <iostream.h>
    
    class planet {
    protected:	double distance; // miles from the sun
    		int revolve;	 // in days
    
    public:	planet( double d, int r ){
     distance = d;
     revolve = r;
    }
    };
    
    class earth: public planet {
    	double circumference; // circumference of orbit
    
    public:	earth( double d, int r ): planet( d, r ){
    	circumference = 2*distance*3.1416;
    	}
    	void show();
    };
    
    void earth::show(){
    	cout << "Distance from the sun: " << distance << '\n';
    	cout << "Days in orbit: " << revolve << '\n';
    	cout << "Circumference of orbit: " << circumference << '\n';
    }
    
    main(){
    	earth  ob( 93000000., 365 );
    //	cout << ob;
    	ob.show();
    	return 0;
    }
  • Lisää edellä olleeseen mjono-tehtävään extraktori.
  • Luo luokka, joka ylläpitää kokonaislukua sekä pienintä (>1) lukua, jolla se onjaollinen. Tee luokalle insertteri ja extraktori.
  • Tee ohjelma, joka tulostaa luvun 100 desimaalisena, heksadesimaalisena ja oktaalisena.
    • Käytä ios-formatointilippuja.
    • Käytä I/O-manipulaattoreita
  • Tee ohjelma, joka tulostaa luvun 1000.5364 20 merkin kentässä, tasattuna vasemmalle,kahdella desimaalilla ja täyttömerkkinä *.
    • Käytä ios-formatointilippuja.
    • Käytä I/O-manipulaattoreita
  • Miten saat Borlandin kääntäjän tekemään koodia, jossa I/O-manipulaattoreiden avulla saadaan 4 desimaalia näkymään tulostuksessa cout << 1.234567 << 1234.123456; Vertaa: cout.setf( ios::fixed );
  • Näytä, miten formatointiliput talletetaan cout:ia varten ja miten talletettua arvoa käytetään.Käytä joko jäsenfunktioita tai manipulaattoreita.
  • Lisää seuraavaan ohjelmaan puuttuvat kohdat.
    #include <iostream.h>
    
    class pwr {
    	int	base;
    	int	exponent;
    	double	result;
    public:	pwr ( int b, int e );
    };
    
    pwr::pwr ( int b, int e ){
    	base = b;
    	if ( e < 0 ) e = -e;
    	exponent = e;
    	result = 1;
    	for (; e > 0; e--) result = result * base;
    }
    
    main(){
    	pwr ob(4, 3);
    	cout << ob;
    	cin >> ob;
    	cout << ob;
    	return 0;
    }
  • Luo luokka box, joka ylläpitää tietoja kuutiosta. Tee insertteri joka piirtää laatikon ruudulle (piirto voidaan suorittaa millä metodilla tahansa).
  • Lisää seuraavaan ohjelmaan puuttuvat osat.
    #include <iostream.h>
    #define SIZE 10
    
    class stack {
    	char 	stck[SIZE];
    	int  	tos; // top of stackpublic:
    	stack();
    	void push( char ch );
    	char pop();};
    stack::stack(){
    	tos = 0;
    }
    
    void stack::push( char ch ){
    	if (tos == SIZE) {
    		cout << "Stack is full";
    		return;
    	}
    	stck[ tos ] = ch;
    	tos++;
    }
    
    char stack::pop(){
    	if (tos==0) {
    		cout << "Stack is empty";
    		return 0;
    	}	tos--;
    	return stck[ tos ];
    }
    
    main(){
    	stack	pino;
    	pino.push('a');
    	pino.push('b');
    	pino.push('c');
    	pino.push('d');
    	pino.push('e');
    	cout << '\n';
    	cout << pino.pop() << ' ';
    	cout << pino.pop() << ' ';
    	cout << pino.pop() << ' ';
    	cout << pino.pop() << ' ';
    	cout << pino.pop() << ' ';
    	cout << pino.pop() << ' ';
    	cout << '\n';
    	cout << pino;  // tulostaa pinon ei tyhjennä
    	pino.push('1');
    	pino.push('2');
    	pino.push('3');
    	cout << pino; // tulostaa pinon ei tyhjennä
    	cin >> pino >> pino >> pino; // lukee 3 merkkiä lisää
    	cout << pino; // tulostaa pinon ei tyhjennä
    	return 0;
    }
  • Tee ohjelma, jossa on watch-niminen luokka. Watch ylläpitää (aika luetaan esimerkiksi luonnissa tai jollain funktiolla) kellonaikatietoa.Tee insertteri, joka tulostaa ajan.
  • Tee luokkamäärittelyt inserttereineen ja extraktoreineen sekä pääohjelma. Luokkaylläpitää päivämäärätietoa muodossa pp/kk/vv
C++:n I/O järjestelmän kehittyneemmät piirteet
  • Tee tulostusmanipulaattori td, joka näyttää ajan ja päivämäärän.
  • Tee tulostusmanipulaattori, joka näyttää desimaaliluvut 6 desimaalilla tasattuna oikeaan reunaan 12 merkkisessä kentässä.
  • Tee ohjelma, joka kopioi tekstitiedoston sekä laskee ja tulostaa kopioitujen merkkien lukumäärän. Miksi merkkien lukumäärä poikkeaa tiedoston koosta.
  • Tee ohjelma, joka tallettaa phone-nimiseen tiedostoon seuraavat tiedot:
    Isac Newton, 012 2203 768
    Kalle Kujala, 010 2208 111
    Enrico Fermi, 011 2201 208
  • Tee ohjelma, joka laskee tiedostosta sanojen lukumäärän.
  • Kokeile seuraavaa ohjelmaa ja huomaa, kuinka puskurointi aiheuttaa joissain tilanteissa ei toivottavaa käyttäytymistä (enter on myös merkki ja merkit ovat puskurissa, josta ohjelma saa ne käsittelyyn vasta kun enteriä on painettu):
    #include <iostream.h>
    #include <fstream.h>
    
    main()
    {
    	char Ofname[80], ch;
    
    	cout << "Output Filename: ";
    	cin >> Ofname;
    	ofstream out(Ofname);
    	if (!out) {
    		cout << "Cannot open file " << Ofname;
    		return 1;
    	}
    
    	cout << "Enter $ to stop\n";
    	do {
    		cout << ": ";
    		cin.get( ch );
    		out.put( ch );
    	} while (ch != '$');
    	out.close();
    	return 0;
    }
  • Tee ohjelma, joka kopioi tekstitiedoston sekä laskee ja tulostaa kopioitujen merkkien lukumäärän. Käytä get()/put()/read()/write() funktioita tarpeen mukaan.
  • Tee ohjelma, joka laskee tiedostosta sanojen lukumäärän. Käytä get()/put()/read()/write() funktioita tarpeen mukaan.
  • Tee ohjelma, joka tulostaa annetun luokan (olion) sisällön tiedostoon. Tee tarkoitusta varten insertteri funktio.
    class account {
    	int	custnum;
    	char	name[80];
    	double 	balance;
    public:
    	account( int c, char *n, double b )
    	{
    		custnum = c;
    		strcpy( name, n );
    		balance = b;
    	}
    	// insertteri
    };
  • Tee ohjelma, joka lukee tekstitiedostoa rivi kerrallaan ja näyttää jokaisen rivin näytöllä. (Käytä getline()).
  • Tee ohjelma, joka näyttää tekstitiedoston takaperin.
  • Oletetaan, että tiedosto sisältää parillisen määrän merkkejä. Tee ohjelma, joka vaihtaa tiedostossa perättäisten merkkien paikkaa. Esim: "123456" -> "214365".
  • Lisää aikaisempiin tiedostonkäsittelyohjelmiisi virheen tarkistus. Käytä jatkossa tämän luvun tehtävissä täydellistä virheentarkistusta ja raportointia.
  • Tee tulostusmanipulaattori, joka tulostaa kolme tabulointia ja asettaa tämän jälkeen kentän leveydeksi 20 merkkiä. Testaa toiminta.
  • Tee syöttömanipulaattori nimeltä etsikirjain, joka lukee ja hylkää merkkejä, kunnes tulee ensimmäinen kirjain, jonka manipulaattori laittaa takaisin streamiin.
  • Tee ohjelma, joka kopioi tekstitiedoston muuttaen samalla kaikki isot kirjaimet pieniksi ja pienet isoiksi.
  • Tee ohjelma, joka lukee tekstitiedostoa ja raportoi, kuinka monta kertaa kukin aakkonen esiintyy tiedostossa.
  • Ohessa inventory-niminen luokka. Lisää funktiot store() ja retrieve(). Luo levylle pieni invetory-tiedosto, jossa on muutamia artikkeleita. Käytä suorasaanti I/O:ta ja tulosta näytölle käyttäjän antaman tuotteen tiedot (käyttäjä antaa esimerkiksi tuotteen numeron tai nimen). Laajenna esim. siten että voidaan tulostaa kaikki tuotteet joiden hinta on pienempi kuin käyttäjän määrittelemä tai suurempi tai joita on varastossa alle annetun määrän tms.
    #include <fstream.h>
    #include <iostream.h>
    #include <string.h>
    
    #define SIZE 40
    
    class inventory {
    	char 	item[SIZE]; 	// tuotteen nimi
    	int	onhand;		// lukumäärä varastossa
    	double	cost;		// yksikköhinta
    public:
    	inventory( char *i, int o, double c ) {
    		strncpy( item, i, SIZE-1 );
    		onhand = o;
    		cost = c;
    	}
    	void store( fstream &stream );
    	void retrieve( fstream &stream );
    	friend ostream &operator<<( ostream &stream, inventory ob );
    	friend istream &operator>>( istream &stream, inventory &ob );
    };
    
    istream &operator>>( istream &stream, inventory &ob )
    {
    	cout << "Enter item name: ";
    	stream >> ob.item;
    	cout << "Enter number on hand: ";
    	stream >> ob.onhand;
    	cout << "Enter cost: ";
    	stream >> ob.cost;
    
    	return stream;
    }
    
    ostream &operator<<( ostream &stream, inventory ob )
    {
    	stream << ob.item << ": " << ob.onhand;
    	stream << " on hand at $" << ob.cost << '\n';
    	return stream;
    }
  • Tee pino-luokka merkeille, joka säilyttää pinoa levytiedostossa eikä muistissa olevassa taulukossa.
  • Tee manipulaattori, joka aiheuttaa numeroiden tulostuksen tieteellisessä muodossa ison E-kirjaimen avulla.
  • Tee ohjelma, joka kopioi tekstitiedoston ja samalla muuttaa tabulaattorit oikeaksi määräksi tyhjiä merkkejä. Ohjelma kysyy käyttäjältä, mikä on tabulaation leveys (oletusarvo 8 merkkiä).
  • Tee ohjelma, joka etsii tiedostosta annettua sanaa ja tulostaa näytölle lukumäärän, kuinka monta kertaa sana löytyi.
  • Tee ohjelma, joka etsii tiedostosta annettua sanaa. Ohjelma tulostaa riviä edellisen rivin, sen rivin, jolta sana löytyi ja seuraavan rivin. Mikäli käyttäjä painaa ESC, ohjelma päättyy. Jos käyttäjä painaa ENTER, ohjelma etsii seuraavan paikan, mistä kyseinen sana löytyy. Jne.
Virtuaalifunktiot
  1. Kokeile kappaleen 10.1 esimerkkiä, siten että yrität käsitellä johdetun luokan funktioita sety() ja gety() kantaluokan osoittimen avulla. Näet, millainen virheilmoitus tulee.
  2. Tee ohjelma, jossa on kantaluokka nimeltä num. Kantaluokka ylläpitää kokonaislukua. Kantaluokassa on virtuaalifunktio shownum(). Tee kaksi kantaluokan perivää luokkaa outhex ja outoct. Outhex luokan shownum()-funktio tulostaa luvun heksadesimaalisena ja outoct luokan shownum()-funktio tulostaa luvun oktaalisena.
  3. Tee ohjelma, jossa on kantaluokka: distance. Distance ylläpitää kahden pisteen etäisyyttää double-tyyppisessä luvussa. Distance:ssa on virtuaalifunktio trav_time(), joka tulostaa kyseisen matkan matkustusajan olettaen, että etäisyys on kilometreissa ja matkustusnopeus on 100 km/h. Johdetussa luokassa miles, trav_time()-funktio tulostaa matkustusajan olettaen, että matka on maileja ja nopeus on 60 mailia tunnissa.
  4. Kokeile aitoa virtuaalifunktiota: Johdettu1 perii kantaluokan ja johdettu2 perii edelleen johdettu1:n. Kantaluokassa on aito virtuaalifunktio. Erilaisia tilanteita: johdettu1:ssä ja johdettu2:ssa on vastaavat funktiot. johdettu1:ssä on vastaava funktio, johdettu2:ssa ei ole. johdettu2:ssa on vastaava funktio, johdettu1:ssä ei ole. Koita luoda olioita kaikkiin luokkiin.
  5. Lisää uusi listatyyppi lista esimerkkiin. Tämä lista ylläpitää laskevassa järjestyksessä olevaa listaa.
  6. Muuta lista esimerkkiä siten, että siinä kuormitetaan + ja -- operaattoreita. + vie uuden alkion listaan ja -- hakee alkion.
Sekalaisia C++ asioita
  • Lisää puskuriesimerkkiin tulostusten yhteyteen tulostus siitä kenellä puskuri on hallussa, kuka yrittää tulostaa, kun puskuri on varattu jne.
  • Staattisen muuttujan avulla voidaan pitää kirjaa olioiden lukumäärästä tietyssä luokassa. Staattista muuttujaa kasvatetaan konstruktorissa ja pienennetään destruktorissa. Toteuta tällainen laskenta ja demoa käyttöä.
  • Muuta taulukkopohjaisen tulostuksen ensimmäistä esimerkkiä siten, että se tulostaa kirjoitettujen merkkien lukumäärän ennen päättymistään.
  • Tee ohjelma, joka käyttää taulukkopohjaista tulostusta kopioidakseen taulukon sisällön toiseen taulukkoon. (Kyseinen tehtävä voidaan tietenkin suorittaa huomattavasti tehokkaammin toisin.)
  • Käyttäen taulukkopohjaista I/O:ta tee ohjelma, joka muuttaa merkkijonon sisältönä olevan liukuluvun arvon liukuluvun sisäiseen esitysmuotoon. Siis esimerkiksi merkkijono "123.125" muunnetaan float-tyyppiseksi luvuksi, jonka arvona on 123.125.
  • Käyttäen mjono-luokkaa tee muunnosfunktio integeriin, joka palauttaa merkkijonon pituuden. Kokeile toiminta.
  • Käytä seuraavaa luokkaa:
    
    	class	pwr {
    		int	base;
    		int	exp;
    	public:
    		pwr( int b, int e ) { base = b; exp = e; }
    		// tähän integer muunnos
    	};
    

    tee muunnosfunktio, joka muuttaa pwr-tyyppisen olion integeriksi. Palauttakoon funktio base potenssiin exp kokonaislukuna.

 
Sivutilan tarjoaa Tietokonepalvelu Mikrolahti.