Ylös Edellinen Seuraava Otsikkosivu Hakemisto Sisällys

17.8 Esimerkki tiedoston lukemisesta

Seuraavaksi kirjoitamme ohjelman, jossa tulee esiin varsin yleinen ongelma: tietueen etsiminen joukosta. Kirjoitamme edellisiä esimerkkejä vastaavan ohjelman, jossa tavallisen tulostuksen sijasta tulostetaan kunkin tuoteluokan yhteistilanne.

tiedosto\luetrek.cpp - esimerkki tiedoston lukemisesta

	// luetrek.cpp c
	/*
	  Ohjelma lukee tiedostoa tuotteet.dat, joka on muotoa:
	
	    Volvo |  12300 | 1
	    Audi  |  55700 | 2
	    Saab  |   1500 | 4
	    Volvo | 123400 | 1
	
	  Ohjelma tulostaa kuhunkin tuoteluokkaan kuuluvien tuotteiden
	  yhteishinnat ja kappalemäärät sekä koko varaston yhteishinnan
	  ja kappalemäärän.  Eli em. tiedostosta tulostetaan:
	
	-------------------------------------------
	Volvo                 135700    2
	Audi                  111400    2
	Saab                    6000    4
	-------------------------------------------
	Yhteensä              253100    8
	-------------------------------------------
	
	  Vesa Lappalainen 15.3.1996
	  Muutettu 30.12.2001/vl : enemmän C++-maiseksi
	  Projektiin: luetrek.cpp,ALI\mjonot.c
	*/
	
	#include <iostream>
	#include <iomanip>
	#include <fstream>
	#include <string>
	#include "mjonotpp.h"
	#include "dosout.h"
	using namespace std;
	
	//---------------------------------------------------------------------------
	class cTuote {
	  string nimike;
	  double hinta;
	  int    kpl;
	  void alusta()                           { nimike=""; hinta=0.0; kpl=0;      }
	public:
	  cTuote()                                { alusta();                         }
	  cTuote(string &st)                      { setAsString(st);                  }
	  cTuote(const string &s)                 { setAsString(s);                   }
	  cTuote(const char *s)                   { setAsString(s);                   }
	
	  int setAsString(string &st) {
	    string pala;
	    alusta();
	    nimike = erota(st,'|'); poista_tyhjat(nimike); if ( nimike == "" ) return 1;
	    pala = erota(st,'|');   if ( !luvuksi(pala,hinta) ) return 1;
	    pala = erota(st,'|');   if ( !luvuksi(pala,kpl) )   return 1;
	    return 0;
	  }
	  int setAsString(const string &s)    { string st(s); return setAsString(st); }
	  int setAsString(const char *s)      { string st(s); return setAsString(st); }
	  ostream &tulosta(ostream &os) const {
	    ios::fmtflags oldf = os.setf(ios::left);
	    os << setw(20) << nimike << " " << setiosflags(ios::right)
	       << setw(7)  << hinta  << " "
	       << setw(4)  << kpl;
	    os.flags(oldf);
	    return os;
	  }
	  void ynnaa(const cTuote &tuote) {
	    hinta += tuote.hinta * tuote.kpl;
	    kpl   += tuote.kpl;
	  }
	  cTuote &operator+=(const cTuote &tuote) { ynnaa(tuote); return *this;       }
	
	  const string &Nimike() const            { return nimike;                    }
	};
	
	ostream &operator<<(ostream &os,const cTuote &tuote)
	  { return tuote.tulosta(os); }
	
	//---------------------------------------------------------------------------
	const int MAX_TUOTTEITA = 10;
	
	class cTuotteet {
	  string nimi;
	  int    tuotteita;
	  cTuote tuotteet[MAX_TUOTTEITA];
	  cTuote yhteensa;
	public:
	  cTuotteet(const char *n) : nimi(n), yhteensa("Yhteensä") { tuotteita = 0;  }
	  ostream &tulosta(ostream &os) const;
	  int etsi(const string &tnimi) const;
	  int lisaa(const string &tnimi);
	  int ynnaa(const cTuote &tuote);
	  int lue(const string &s);
	  int lue() { return lue(""); }
	};
	
	int cTuotteet::etsi(const string &tnimi) const
	{
	  for (int i=0; i<tuotteita; i++)
	    if ( tuotteet[i].Nimike() == tnimi ) return i;
	  return -1;
	}
	
	int cTuotteet::lisaa(const string &tnimi)
	{
	  if ( tuotteita >= MAX_TUOTTEITA ) return -1;
	  tuotteet[tuotteita].setAsString(tnimi);
	  return tuotteita++;
	}
	
	int cTuotteet::ynnaa(const cTuote &tuote)
	{
	  if ( tuote.Nimike() == "" ) return 1;
	  int i = etsi(tuote.Nimike());
	  if ( i < 0 ) i = lisaa(tuote.Nimike());
	  if ( i < 0 ) return 1;
	
	  tuotteet[i] += tuote;
	  yhteensa    += tuote;
	
	  return 0;
	}
	
	int cTuotteet::lue(const string &s)
	{
	  string rivi;
	
	  if ( s != "" ) nimi = s;
	  ifstream f(nimi.c_str());  if ( !f ) return 1;
	
	  while ( getline(f,rivi) ) {
	    cTuote tuote(rivi);
	    if ( ynnaa(tuote) )
	      cout << "Rivillä \"" << rivi << "\" jotain pielessä!" << endl;
	  }
	  return 0;
	}
	
	
	ostream &cTuotteet::tulosta(ostream &os) const
	{
	  int i;
	  os << "\n\n\n";
	  os << "-------------------------------------------\n";
	  for (i=0; i<tuotteita; i++)
	    os << tuotteet[i] << "\n";
	  os << "-------------------------------------------\n";
	  os << yhteensa << "\n";
	  os << "-------------------------------------------\n";
	  os << "\n\n" << endl;
	  return os;
	}
	
	
	int main(void)
	{
	  cTuotteet varasto("tuotteet.dat");
	
	  if ( varasto.lue() ) {
	    cout << "Tuotteita ei saada luetuksi!" << endl;;
	    return 1;
	  }
	
	  varasto.tulosta(cout);
	
	  return 0;
	}

Tehtävä 17.154 Tietorakenne

Piirrä kuva cTuotteet - luokan tietorakenteesta.

Tehtävä 17.155 Perintä

Miten voisit perinnän avulla saada tiedoston luerek.cpp luokasta cTuote tiedoston luetrek.cpp vastaavan luokan (tietysti eri nimelle, esim. cRekTuote). Mitä muutoksia olisi hyvä tehdä alkuperäisessä cTuote- luokassa.

Tehtävä 17.156 Tunnistenumero

Lisää luetrek.cpp- ohjelmaan tunnistenumeron käsittely mahdollista tulevaa relaatiokäyttöä varten.

Tehtävä 17.157 Mittakaava

Kirjoita mittakaavaohjelma, jossa on vakiotaulukko
yks
mm
mm
cm
dm
m
inch
1.0
10.0
100.0
1000.0
25.4
ja jonka toiminta näyttäisi seuraavalta:
	...
	Mittakaava ja matka>1:10000 10 cm[RET]
	Matka maastossa on 1.00 km.
	Mittakaava ja matka>1:200000 20[RET]
	Matka maastossa on 4.00 km.
	Mittakaava ja matka>loppu[RET]
	Kiitos! 
Muuta ohjelmaa siten, että yksiköiden muunnostaulukko luetaan ohjelman aluksi tiedostosta muunnos.dat.
Muuta ohjelmaa vielä siten, että mikäli mittakaava jätetään antamatta, käytetään edellisellä kerralla annettua mittakaavaa ja ensimmäinen luku onkin matka.
	...
	Mittakaava ja matka>1:10000 10 cm[RET]
	Matka maastossa on 1.00 km.
	Mittakaava ja matka>0.20 dm[RET]
	Matka maastossa on 0.20 km.
	Mittakaava ja matka>loppu[RET]
	Kiitos! 


Ylös Edellinen Seuraava Otsikkosivu Hakemisto Sisällys