// mato.cpp // // Vesa Lapplainen 7.2.1999 // Muutokset: // 8.2.1999/vl: korjattu delete alkiot delete [] alkiot; // 10.2.1999/vl: caElain -destruktori virtuaaliseksi // globaali gElainTarhanElaimet => cElainAlkion // staattinen osoitin ja ElainAlkio luo Elaimet-luokan // edustajan jos sita tarvitaan. ElainAlkio // "tappaa" Elaimet kun viimeinen ElainAlkio poistuu. // // Malliohjelma, jossa naytetaan, miten voidaan tehdä luokkia, jotka // lukevat itsensa tiedostosta ja luovat tiedostossa olevan tunnuksen // mukaan eri jälkelaisten esiintymia. // Esimerkkiohjelma lukee seuraavan muotoista tiedostoa: // kissa:Misse;15;Miauuu // kissa:Mirri;6 // koira:Musti;3 // mato:Mato Matala;5;;45 // // Luokat: // caElain - abstarkti kantaluokka elaimille // cElainAlkio - luo ja tallettaa yhden elain-luokan edustajan // osaa luoda vastaavan edustajan // cElaintarhanElaimet - luokka, joka tallettaa malliksi yhden kunkin luokan // esiintyman. // cElaintarha - tallettaa kantaluokan jälkeläisiä // cKissa,cKoira - mallijälkeläisiä // cMato - mallijälkeläinen, jossa mm. uusia attribuutteja // // Tässä esimerkissä kukin elain tietää oman "tunnuksensa". Tallä tavoin // tallettaminen saadaan helpommaksi, koska talletuksessahan pitää elaimen // tyyppi kirjoittaa tiedostoon. // // Jos talletusta ei tarvita, voisi tunnus olla myos cElainAlkio:ssa // Jos olisi varmaa, etta kaytetyssa C++:n versiossa olis kaytossa // esim. typeid, voisi luokan nimi olla talloinkin cElainAlkiossa // ja cElaintarhanElaimet osaisi etsia vastaavaa luokan edustajaa // omasta taulukostaan ja palauttaisi edustajan "tunnuksen". // // Uuden jalkelaisen tekemiseksi pitaa tehda luokka, jossa on esim: //------------------------------------------------------------------------------ // class cKoira : public caElain { // virtual const char *aanahdys() const { return "Hau"; } // public: // virtual caElain *luo_samanlainen(string &s) const { return new cKoira(s); } // cKoira(string &s) : caElain(s) {} // }; // ja lisata luokkaa vastaavaan .cpp-tiedostoon rivi: // static cElainAlkio koira("koira",new cKoira(tyhja)); // // Jos luokassa on uusia attribuutteja, jotka pitaa myos tallettaa, pitaa // uudelleenmaaritella (override) metodit: // virtual void setAsString(string &s); // virtual string getAsString() const; #include #include #include #include //------------------------------------------------------------------------------ // Apufunktioita merkkijonojen käsittelyyn //------------------------------------------------------------------------------ string erota(string &jono, char merkki=' ',bool etsi_takaperin=false) { size_t p; if ( !etsi_takaperin ) p = jono.find(merkki); else p = jono.rfind(merkki); if ( p == string::npos ) { string alku = jono; jono.erase(0,jono.length()); return alku; } string alku = jono.substr(0,p); jono.erase(0,p+1); return alku; } int erota_int(string &jono, char merkki=' ',bool etsi_takaperin=false) { string ijono(erota(jono,merkki,etsi_takaperin)); int i=0; sscanf(ijono.c_str(),"%d",&i); return i; } string AsString(int i) { char s[50]; sprintf(s,"%d",i); return string(s); } //------------------------------------------------------------------------------ // Kantaluokka //------------------------------------------------------------------------------ class caElain { string tunnus; string nimi; int ika; string aantely; virtual const char *aanahdys() const = 0; public: virtual caElain *luo_samanlainen(string &s) const = 0; virtual void setAsString(string &s) { nimi = erota(s,';'); // nimi = *(new string(erota(s,';'))); ika = erota_int(s,';'); // aantely = *(new string(erota(s,';'))); aantely = erota(s,';'); } virtual string getAsString() const { return nimi + ";" + AsString(ika) + ";" + aantely; } caElain() { string s(""); setAsString(s); } caElain(string &s) { setAsString(s); } virtual ~caElain() {} string aantelyAsString() const { if ( aantely != "" ) return aantely; else return aanahdys(); } void aantele(ostream &os=cout) const { os << aantelyAsString(); } void setTunnus(const string &s) { tunnus = s; } const string &getTunnus() const { return tunnus; } }; //------------------------------------------------------------------------------ class cElaintarhanElaimet; class cElainAlkio { caElain *elain; static cElaintarhanElaimet *pElaimet; public: cElainAlkio(const string &viite,caElain *e); virtual ~cElainAlkio(); int compare(const string s) const { return elain->getTunnus().compare(s); } caElain *luo(string &s) const { caElain *uusi = elain->luo_samanlainen(s); uusi->setTunnus(elain->getTunnus()); return uusi; } static cElainAlkio *etsi(const string &luokka); }; class cElaintarhanElaimet { int lkm; int max_lkm; cElainAlkio **alkiot; public: cElaintarhanElaimet(int ml) { max_lkm = ml; lkm = 0; alkiot = new cElainAlkio *[ml]; } virtual ~cElaintarhanElaimet() { delete [] alkiot; } int lisaa(cElainAlkio *uusi) { if ( lkm >= max_lkm ) return 1; alkiot[lkm] = uusi; lkm++; return 0; } cElainAlkio *etsi(const string &viitenimi) const; int poista(cElainAlkio *ea); }; cElainAlkio *cElaintarhanElaimet::etsi(const string &viitenimi) const { for (int i=0; icompare(viitenimi) == 0 ) return alkiot[i]; return NULL; } int cElaintarhanElaimet::poista(cElainAlkio *ea) { for (int i=0; ietsi(luokka); } cElainAlkio::cElainAlkio(const string &viite,caElain *e) :elain(e) { if ( !pElaimet ) pElaimet = new cElaintarhanElaimet(20); e->setTunnus(viite); pElaimet->lisaa(this); } cElainAlkio::~cElainAlkio() { delete elain; if ( pElaimet && pElaimet->poista(this) == 0 ) { delete pElaimet; pElaimet = NULL; } } string kityhja("Ei eläintä"); //------------------------------------------------------------------------------ class cElaintarha { int lkm; int max_lkm; caElain **alkiot; public: cElaintarha(int ml) { max_lkm = ml; lkm = 0; alkiot = new caElain *[ml]; } virtual ~cElaintarha() { poista_kaikki(); delete [] alkiot; } int lisaa(caElain *uusi) { if ( lkm >= max_lkm ) return 1; alkiot[lkm] = uusi; lkm++; return 0; } void poista_kaikki(); void tulosta(ostream &os) const; void aantele(ostream &os) const; int lue(istream &f); int lue(const string &tiedoston_nimi) { ifstream f(tiedoston_nimi.c_str()); if ( !f ) return 1; return lue(f); } int talleta(ostream &os) const; int talleta(const string &tiedoston_nimi) { ofstream f(tiedoston_nimi.c_str()); if ( !f ) return 1; return talleta(f); } }; void cElaintarha::tulosta(ostream &os=cout) const { for (int i=0; igetAsString() << endl; } void cElaintarha::aantele(ostream &os=cout) const { for (int i=0; iaantelyAsString() << " "; os << endl; } int cElaintarha::lue(istream &f) { string s,luokka; while ( !f.eof() ) { if ( !getline(f,s) ) return 1; luokka = erota(s,':'); cElainAlkio *ea = cElainAlkio::etsi(luokka); if ( !ea ) continue; lisaa(ea->luo(s)); } return 0; } int cElaintarha::talleta(ostream &f) const { for (int i=0; igetTunnus() << ":" << alkiot[i]->getAsString() << endl; return 0; } void cElaintarha::poista_kaikki() { for (int i=0; i