Ohjelmointi 2 2006/ 8.5

Demo C2 vastauksia


1. Linja-auto

// bussi.cpp
// Esimerkki yksinkertaisesta luokasta

#include <iostream.h>
#include <iomanip.h>

class cLinjaAuto {
  int matkustajia;
  int paikkoja;
public:
  cLinjaAuto(int apaikkoja=50) { paikkoja = apaikkoja; matkustajia = 0; }
  int lisaa(int m) {
    matkustajia += m;
    if ( matkustajia > paikkoja ) {
      int yli = matkustajia-paikkoja;
      matkustajia = paikkoja;
      return yli;
    }
    return 0;
  }
  int vahenna(int m) {
    matkustajia -= m;
    if ( matkustajia < 0 ) {
      int vajaa = matkustajia;
      matkustajia = 0;
      return vajaa;
    }
    return 0;
  }
  int tilaa() const { return paikkoja - matkustajia; }
  int Matkustajia() const { return matkustajia; }
  ostream &tulosta(ostream &os=cout) {
    os << "Bussiin mahtuu: " << setw(2) << paikkoja
       << ", matkustajia: "  << setw(2) << matkustajia
       << ", tilaa: "        << setw(2) << tilaa() << endl;
    return os;
  }
};

int main(void)
{
  cLinjaAuto pikkubussi(10),isobussi(45);
  pikkubussi.lisaa(4); pikkubussi.tulosta();
  isobussi.lisaa(30);  isobussi.tulosta();
  int yli = pikkubussi.lisaa(15);
  isobussi.lisaa(yli);
  pikkubussi.tulosta(); isobussi.tulosta();
  if ( isobussi.tilaa() ) cout << "Isoon bussiin mahtuu!" << endl;
  int vajaa = pikkubussi.vahenna(12);
  if ( vajaa < 0 ) cout << "Pikkubussissa ei edes ole näin montaa!" << endl;
  return 0;
}

2. Kulkunevot perinnällä

// kulku2.cpp
// Lentsikka ja laiva perinnän avulla
// vl 23.4.1996, muutos: 25.2.2001 const char * => string
#include <iostream.h>
#include <string>

class cKulkuneuvo {
  string nimi;
  int matkustajia;
  double nopeus;
public:
  cKulkuneuvo(const string &n, int mat, double nop) :
     nimi(n), matkustajia(mat), nopeus(nop) {;}
  virtual string vekotin() const { return "Kulkuneuvo"; }
  virtual void tulosta(ostream &os=cout) const {
    os << vekotin()         << endl;
    os << "  Nimi:        " << nimi                  << endl;
    os << "  Matkustajia: " << matkustajia           << endl;
    os << "  Nopeus:      " << nopeus << " km/h"     << endl;
  }
};

class cLentokone : public cKulkuneuvo {
  double lentokorkeus;
public:
  cLentokone(const string &n, int mat, double nop, double kork) :
     cKulkuneuvo(n,mat,nop), lentokorkeus(kork) {;}
  virtual string vekotin() const { return "Lentokone"; }
  virtual void tulosta(ostream &os=cout) const {
    cKulkuneuvo::tulosta(os);
    os << "  Lentokorkeus " << lentokorkeus << " m " << endl;
  }
};

class cLaiva : public cKulkuneuvo {
public:
  cLaiva(const string &n, int mat, double nop) :
     cKulkuneuvo(n,mat,nop) {;}
  virtual string vekotin() const { return "Laiva"; }
};

int main(void)
{
  cLentokone dc3("DC3",25,320,4500);
  cLaiva fennia("Fennia",1200,40);
  dc3.tulosta();
  fennia.tulosta();
  return 0;
}


3. Koostaminen

/* valuuttsk.cpp */
...
//---------------------------------------------------------------------------
// Koostetaan list-luokasta
// cValuutat, johon lisataan muutama valuutoille ominainen lisapiirre
class cValuutat  {
  list<cValuutta> alkiot;
  static string virhe;
public:
  cValuutat(int koko=0) : alkiot() { ;  }
  const string &valuutta(const char *val) const {
    list<cValuutta>::const_iterator i = find(alkiot.begin(),alkiot.end(),cValuutta(1.0,val));
    if ( i != alkiot.end() ) return i->Valuutta();
    return virhe;
  }
  double kerroin(const cValuutta &val) const {
    list<cValuutta>::const_iterator i = find(alkiot.begin(),alkiot.end(),val);
    if ( i != alkiot.end() ) return i->Maara();
    return 1.0;
  }
  const string &mk() const { return alkiot.begin()->Valuutta(); }
  int lue(const string &nimi) {
    ifstream f(nimi.c_str()); if ( !f ) return 1;
    string rivi;
    while ( getline(f,rivi) ) { alkiot.push_back(cValuutta(rivi)); }
    return 0;
  }
  ostream &tulosta(ostream &os) const {
    copy(alkiot.begin(),alkiot.end(),ostream_iterator<cValuutta>(os,"\n"));
    return os;
  }
};

ostream &operator<<(ostream &os, const cValuutat &v) { return v.tulosta(os); }


4&5. Dynaaminen C++ -taulukko

Tehtävä 5 olikin vahingossa jo tehty :-)
// taul2.cpp
// Malli dynaamisesta taulukosta /vl-96
#include <iostream.h>
#include <iomanip.h>

int poista(int taulukko[],int lkm,int n)         /* indekseillä */
{
  int luku,kirj;
  for (luku=0,kirj=0; luku<lkm; luku++)
    if ( taulukko[luku] != n )
      taulukko[kirj++] = taulukko[luku];
  return kirj;
}

class cTaulukko {
  int max_koko;
  int lkm;
  int *alkiot;
public:
  int varaa(int koko) {
    lkm = 0; max_koko = 0;
    if ( koko <= 0 ) return 0;
    alkiot = new int[koko];
    if ( alkiot ) max_koko = koko;
    return max_koko == 0;
  }
  void vapauta() { if ( max_koko > 0 ) delete [] alkiot; max_koko = 0; }
  cTaulukko(int koko=0) { varaa(koko);  }
  cTaulukko(const cTaulukko &luvut) : max_koko(0) { sijoita(luvut); } // Copy Constructor
  ~cTaulukko() { vapauta(); }
  int lisaa(int n) {
    if ( lkm >= max_koko ) return 1;
    alkiot[lkm++] = n;
    return 0;
  }
  int poista(int n) { // kutsutaan valmista kun sellainen tuli tehtya
    lkm = ::poista(alkiot,lkm,n);  // ::poista tarkoittaa että kuts. glob.
    return lkm;
  }
  ostream &tulosta(ostream &os) const;
  cTaulukko &sijoita(const cTaulukko &luvut);
  cTaulukko &operator=(const cTaulukko &luvut) { return sijoita(luvut); }
};

cTaulukko &cTaulukko::sijoita(const cTaulukko &luvut)
{
  if ( this == &luvut ) return *this;
  if ( max_koko != luvut.max_koko ) {
    vapauta(); varaa(luvut.max_koko);
  }
  lkm = 0;
  for (int i=0; i<luvut.lkm; i++)
    lisaa(luvut.alkiot[i]);
  return *this;
}


ostream &cTaulukko::tulosta(ostream &os) const
{
  for (int i=0; i<lkm; i++)
    os << alkiot[i] << " ";
  return os;
}

ostream &operator<<(ostream &os,const cTaulukko &taul) {
  return taul.tulosta(os);
}

int main(void)
{
  cTaulukko luvut(7);
  luvut.lisaa(0); luvut.lisaa(2); luvut.lisaa(2); luvut.lisaa(4); luvut.lisaa(2);
  cout << luvut << endl;  // 0 2 4 2 2
  cTaulukko taul;
  taul.sijoita(luvut); // tai jopa  taul = luvut;
  cout << taul << endl;   // 0 2 4 2 2
  taul.poista(2);
  cout << taul << endl;   // 0 4 
  return 0;
}



6&7 Lajittele nimet


// henkilots.cpp
// Ohjelmalla luetaan ihmisten nimia ja lajitellaan ne.
// Nimet sailytetaan muodossa etunimi sukunimi, mutta
// lajitellaan sukunimi etunimi perusteella
// Tietorakenteen toteutus STL:n vector-luokalla
// Projektiin lisaksi: mjonot.c
// Vesa Lappalainen 25.4.1999

#include <iostream>
#include <fstream>
#include <string>
#include "mjonotpp.h"

using std::string;
using std::ostream;
using std::ifstream;
using std::ofstream;
using std::cin;
using std::cout;
using std::endl;

class cHenkilo {
  string nimi;
  string avain;
public:
  void sijoita(const string &s) {
    nimi = s;
    string suku(s);
    avain = erota(suku,' ');
    if ( suku != "" ) avain = suku + ' ' + avain;
    jono_isoksi(avain);
  }
  cHenkilo(const string &s) { sijoita(s); }
  void operator=(const string &s) { sijoita(s); }
  ostream &tulosta(ostream &os) const { os << nimi; return os;}
  int vertaa(const cHenkilo &h) const { return avain.compare(h.avain); }
  int operator<(const cHenkilo &h) const { return vertaa(h) < 0; }
};

ostream &operator<<(ostream &os, const cHenkilo &h) { return h.tulosta(os); }

#include <vector>
#include <iterator>
#include <algorithm>
using std::vector;
using std::ostream_iterator;
using std::sort;

class cHenkilot {
  vector<cHenkilo> alkiot;
public:
  cHenkilot() : alkiot() {}
  int lue(const string &nimi) {
    ifstream f(nimi.c_str()); if ( !f ) return 1;
    string rivi;
    while ( getline(f,rivi) ) { alkiot.push_back(cHenkilo(rivi)); }
    return 0;
  }
  ostream &tulosta(ostream &os) const {
    copy(alkiot.begin(),alkiot.end(),ostream_iterator<cHenkilo>(os,"\n"));
    return os;
  }
  int kirjoita(const string &nimi) const  {
    ofstream f(nimi.c_str()); if ( !f ) return 1;
    tulosta(f);
    return 0;
  }
  int kysy_uusia() {
    string s;
    while ( 1 ) {
      cout << "Anna nimi >"; getline(cin,s);
      if ( s == "" ) return 0;
      alkiot.push_back(cHenkilo(s));
    }
  }
  void lajittele() {
    sort(alkiot.begin(),alkiot.end());
  }
};



//---------------------------------------------------------------------------
int main(void)
{
  cHenkilot hlot;
  hlot.lue("henkilot.dat");
  cout << "-----------------------------------------" << endl;
  cout << "Ennen lis,yst,:"                           << endl;
  hlot.tulosta(cout);
  cout << "-----------------------------------------" << endl;
  hlot.kysy_uusia();
  cout << "-----------------------------------------" << endl;
  cout << "Ennen lajittelua:"                         << endl;
  hlot.tulosta(cout);
  cout << "-----------------------------------------" << endl;
  cout << "Lajittelun j,lkeen:"                       << endl;
  hlot.lajittele();
  hlot.tulosta(cout);
  cout << "-----------------------------------------" << endl;
  hlot.kirjoita("henkilot.dat");
  return 0;
}


8&9&10 Pasianssi

/*
** pasi3.cpp
**
** Ohjelmalla pelataan yksinkertaista pasianssia:
**  0. pakka sotketaan
**  1. ruvetaan laskemaan kädessä olevia kortteja pöydälle ja
**     samalla lasketaan 1 2 3 4 .. 13 1 2 3 ..
**  2. Jos laskuissa osutaan saman kortin kohdalle, joka laiteaan
**     pöydälle, EI PELI MENE LÄPI
**
**     Vesa Lappalainen 28.11.1991
**
**  Muutettu olio-ohjelmaksi
**     Vesa Lappalainen 1996
*/
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include "streampr.h"
using std::cout;
using std::setw;
using std::endl;
using std::rand;
using std::randomize;

#include "dosout.h"

/*************************************************************************/
class cHisto {
  int lkm;
  long *esiintymat;
  cHisto(const cHisto &) { }
  void operator=(const cHisto &) { }
public:
  cHisto(int n);
  ~cHisto();
  int lisaa(int i);
  long etsi_max() const;
  int piirra() const;
};


cHisto::~cHisto()
{
   if ( lkm ) delete [] esiintymat;
   lkm =  0; esiintymat = NULL;
}

cHisto::cHisto(int n)
{
  lkm = 0;
  if ( n <= 0 ) return;
  esiintymat = new long[n];
  if ( esiintymat == NULL ) return;
  lkm = n;
  for (int i=0; i<lkm; i++) esiintymat[i] = 0;
  return;
}

int cHisto::lisaa(int i)
{
  if ( i < 0 || lkm <= i ) return 1;
  esiintymat[i]++;
  return 0;
}

long cHisto::etsi_max() const
{
  int i; long m;
  if ( lkm == 0 ) return 0;
  m = esiintymat[0];
  for ( i=0; i<lkm; i++)
    if ( esiintymat[i] > m )
      m = esiintymat[i];
  return m;
}

int cHisto::piirra() const
{
  int i,j,pituus;
  long pisin = etsi_max();
  if ( pisin == 0 ) return 1;
  for (i=0; i<24 /*lkm*/; i++) {
    cout << setw(3) << i << ": ";
    pituus = 60.0*esiintymat[i]/pisin;
    for (j=0; j<pituus; j++) cout << "*";
    cout << endl;
  }
  return 0;
}


/*************************************************************************/
typedef enum {
  Hertta,Pata,Ruutu,Risti
} eMaa;

class cKortti {
  eMaa maa;
  int        arvo;
public:
  cKortti() { set(Hertta,1); }
  eMaa getMaa() { return maa; }
  void setMaa(eMaa m) { maa = m; }
  int getArvo() { return arvo; }
  void setArvo(int a) { arvo = a; } // Lisää tarkistukset
  void set(eMaa m, int a) { setMaa(m); setArvo(a); }
};


class cPakka {
  cKortti kortit[52];
public:
  cPakka() { sotke(); }
  int pelaa_peli();
  void sotke();
  void jarjesta();
};

void cPakka::jarjesta()
{
  eMaa m;
  int a,i=0;

  for (m = Hertta; m <= Risti; m = (eMaa)(m+1))
    for (a = 1; a <= 13; a++) {
      kortit[i++].set(m,a);
    }
}


void cPakka::sotke()
{
  int i,k;
  cKortti apu;

  jarjesta();

  for ( i=51; i>=0; i-- ) {
    k = rand() % (i+1);  /* Satunnaisluku välille [0-i] */
    apu      = kortit[i];
    kortit[i] = kortit[k];
    kortit[k] = apu;
  }
}

int cPakka::pelaa_peli()
{
  int k;
  for (k=0; k<52; k++) {
    if ( kortit[k].getArvo() == (k%13)+1 ) return k+1;
  }
  return 0;
}

/*************************************************************************/
int main(void)
{
  int p,lapi=0;
  long peleja=0;
  cPakka pakka;
  randomize();
  cHisto histo(53);
  cStreamPre(cout,2);

  while (lapi<100) {
    pakka.sotke();
    p = pakka.pelaa_peli();
    peleja++;
    histo.lisaa(p);
    if ( p==0 ) lapi++;
    if ( !(peleja % 1000) ) {
      cout << "Peli "   << setw(5) << peleja
           << ": Läpi " << setw(3) << lapi << " kertaa."
           << "  Tn: "  << setw(5) << 100.0*lapi/peleja << "%" << endl;
    }
  }
  histo.piirra();
  return 0;
}