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\tuoterek.cpp - esimerkki tiedoston lukemisesta C-funktiolla
// tuoterek.cpp
/*
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
Projektiin: tuoterek.cpp,ALI\mjonot.c
*/
#include <iostream.h>
#include <iomanip.h>
#include <strstream.h>
#include <fstream.h>
#include <stdio.h>
#include <string.h>
#include <string>
using namespace std;
#include <mjonot.h>
#include <mjonotpp.h>
//---------------------------------------------------------------------------
class cTuote {
string nimike;
double hinta;
int kpl;
public:
int alusta(const char *n,double h,int k=0) {
nimike = n; hinta = h; kpl = k; return 0;
}
int alusta(const char *rivi) { // Alustaa jonosta Volvo|4500|3
istrstream sstr((char *)rivi);
return lue(sstr);
}
int alusta() { return alusta("",0,0); }
cTuote() { alusta(); }
cTuote(const char *rivi) { alusta(rivi); }
int lue(istream &is) {...}
ostream &tulosta(ostream &os) const { ... }
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); }
istream &operator>>(istream &is,cTuote &tuote) { tuote.lue(is); return is; }
//---------------------------------------------------------------------------
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 char *s=NULL);
};
int cTuotteet::etsi(const string &tnimi) const
{
int i;
for (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].alusta(tnimi.c_str(),0.0,0);
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 char *s)
{
char rivi[80];
if ( s ) nimi = s;
ifstream f(nimi.c_str()); if ( !f ) return 1;
while ( f.getline(N_S(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;
}
- Piirrä kuva cTuotteet - luokan tietorakenteesta.
- Miten voisit perinnän avulla saada tiedoston tuote_pao.cpp luokasta
cTuote tiedoston tuoterek.cpp vastaavan luokan (tietysti eri nimelle,
esim. cRekTuote). Mitä muutoksia olisi hyvä tehdä
alkuperäisessä cTuote- luokassa.
- Lisää tuoterek.cpp- ohjelmaan tunnistenumeron käsittely
mahdollista tulevaa relaatiokäyttöä varten.
- Kirjoita mittakaavaohjelma, jossa on vakiotaulukko
- y
- ks
|
- 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!