Cpp tehtäviä

Mureakuha

Loikkaa: valikkoon, hakuun

Sisällysluettelo

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>
 
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ä
  1. funktiolle annetaan argumenttina taulukko, jossa on merkkijono, funktio muuttaa merkkijonon alkuperäisen tilalle.
  2. 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>
#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>
 
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

  • Tee coord-luokka, joka toteuttaa kaikki aritmeettiset operaatiot (+ , - , / , * , = ) kokonaisluvuille ja coord-tyyppisille olioille. Esim: o1 = ( o2 / o3 + 5 )* 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.
  • Kuormita < ja > operaattoreita coord-luokassa.
  • Lisää merkkijonoluokkaan <, >, ==, != jne. operaattoreiden kuormitus.
  • Käytä friend-operaattorikuormitusta ja coord-luokkaa. Kuormita +, -, /, *, <, >, jne kaikkia, joille keksit järkevän käytön.
  • 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>
#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>
 
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>
 
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>
#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>
 
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>
 
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>
#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>
#include <fstream>
 
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>
#include <iostream>
#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.

Tämän dokumentin kopiointi, levittäminen sekä muokkaaminen on sallittua GNU Free Documentation Licensen version 1.2 tai uudemman Free Software Foundationin julkaiseman version mukaisesti, ilman muuttumattomuuslauseketta tai kansitekstejä. Tätä koskee vastuuvapaus.
Kopio lisenssistä (englanniksi) löytyy täältä.

Alkuperäinen (c) Petteri Hämäläinen

Henkilökohtaiset työkalut