/* jasenet.cpp */ /****************************************************************************/ /* ** J A S E N E T . C P P ** ** J„senet-luokan toteutus ** ** Tekij„t: Vesa Lappalainen ** Ohjelmointikurssi 1991 ** Tehty: 20.12.1991 ** Muutettu: 09.12.1995 ** Mit„ muutettu: Muutettu C++ luokaksi ** Muutettu: 10.12.1995 ** Mit„ muutettu: + Laitettu tiedoston lukeminen ja kirjoittaminen ** toimivaksi (ks. metodit lue_tiedostosta ja talleta) ** + J„senen lis„ys kasvattaa taulukon kokoa, mik„li ** tila loppuu (ks. lisaa) ** Muutettu: 20.01.1997 ** Mit„ muutettu: + Otettu kerhosta j„senist”n osuus ** ** Public-metodeja: ** ================ ** ** Metodit palauttavat yleens„ virheen merkkijonona, joka voidaan ** suoraan tulostaa. Jos virhett„ ei tapahdu, palautetaan NULL. ** ** cJasenet(int koko=0) ** - j„senit”n luominen, jos koko = 0, ei luoda j„sentaulukkoa ** ** ~cJasenet() ** - j„senist„n h„vitt„minen, jos j„senist”„ ei ole talletettu, talletetaan ** viimeist„„n nyt (mahd. virheilmoitus harakoille) ** ** string lisaa(const cJasen &jasen); ** - lis„t„„n uusi j„sen. J„senest„ tehd„„n kopio. Jos tila loppuu, ** yritet„„n kasvattaa tilaa. ** ** const cJasen &anna(int i) const ** - otetaan kerhosta i:s j„sen. Jos i v„„rin, otetaan 0:s j„sen. ** Kerholaisia voidaan muuttaa, kun otetaan j„senest„ kopio ** anna-metodilla, muutetaan kopion tietoja ja laitetaan takaisin ** korvaa-metodilla: ** cJasen jasen(kerho.anna(i)); ** - muuta jasenta ** kerho.korvaa(i,jasen); ** ** string luo(const string &tied,const string &nimi, ** - luo j„senist”n uutta kerhoa varten, mahd. vanha talletetaan ** ** string lue(const string &tied); ** - luetaan uusi j„senist”, mahd. vanha talletetaan ** ** string talleta(const string &tied=""); ** - talletetaan j„sensist„. Jos tied=="", k„ytet„„n luettaessa ** annettua nimi„. ** ** const string &Koko_nimi() const ** - palauttaa tiedoston koko nimen. ** ** int Lkm() const ** - palauttaa j„senm„„r„n ** ** const string &Tiedoston_nimi() const ** - paluttaa viimeksi k„ytetyn tiedoston nimen ** ** int Muutettu() const ** - palauttaa 1, mik„li j„senist”„ on muutettu talletusten j„lkeen ja ** 0 muuten. ** ** int cJasenet::TeeBak(const string &bak_tark) ** - palauttaa 0, mik„li tiedoston muuttaminen bak-tiedostoksi onnistuu ** 1 muuten. ** --------------------------------------------------------------------------- ** ** Tietorakenne on seuraava: ** ========================= ** ** ** cJasenet cJasen ** ------ ** | | ------ ** | | | | ** | 7 | max |---->| | ** | 3 | alkiot | | | ------ ** | o--+------>|-----| | ------ | | ** ------ | o--+-----| | | ** |-----| |----->| | ** | o--+------------| ------ ------ ** |-----| | | ** | o--+--------------------------->| | ** |-----| | | ** | o--+--? ------ ** |-----| ** | o--+--? ** |-----| ** | o--+--? ** |-----| ** | o--+--? ** |-----| ** ** ** J„senet ei tied„ j„seniens„ ominaisuuksia. ** J„senist” pit„„ huolta siit„, onko j„senet muuttunut, eli tarvitseeko se ** talletusta vaiko ei. ** Tiedoston muoto, ks. lue_tiedostosta - metodi ** */ #include #include #include #include "mjonotpp.h" #include "jasenet.h" //============================================================================ // Makrot: //============================================================================ //---------------------------------------------------------------------------- // Makro, jolla tutkitaan palauttiko kutsu v virheen vai ei ja jos // palautti, niin poistutaan aliohjelmasta palauttaen sama virhe. #define IF_ERR_RETURN(v) { string virhe=(v); if ( virhe != "" ) return virhe; } //============================================================================ // Virheilmoitukset: //============================================================================ static const char *EI_VOI_LUODA = "Taulukolle ei saada varattua tilaa muistista!"; static const char *LIIKAA_ALKIOITA = "Liikaa alkioita, ei voi lis„t„!"; static const char *EI_SAA_ALKIOTA = "Ei saada tilaa uudelle alkiolle muistista!"; static const char *EI_NIMEA = "Ei koko nime„ tiedostossa!"; static const char *EI_MAXKOKOA = "Ei maksimikokoa tiedoston alussa!"; static const char *TIED_EI_AUKEA = "Tiedosto ei aukea!"; static const char *OTS_EI_KIRJ = "Otsikkotietoja ei voi kirjoittaa!"; static const char *ALKIO_EI_KIRJ = "Alkiota ei voi kirjoittaa!"; //============================================================================ // Private -metodeja: //============================================================================ //---------------------------------------------------------------------------- void cJasenet::poista_taulukko() { if ( max_lkm > 0 ) free(alkiot); max_lkm = 0; } //---------------------------------------------------------------------------- void cJasenet::poista_alkiot() { for (int i=0; i= max_lkm ) IF_ERR_RETURN(kasvata_kokoa()); cJasen *uusi = new cJasen(jasen); if ( uusi == NULL ) return EI_SAA_ALKIOTA; alkiot[lkm] = uusi; lkm++; muutettu = 1; return ""; } //---------------------------------------------------------------------------- string cJasenet::luo_taulukko(int koko) /* ** Luodaan j„sentaulukko valitun kokoiseksi. Jos j„sentaulukko on ennest„„n ** on siell„ on se parasta poistaa. ** Luomisessa k„ytet„„n malloc-funktiota, jotta koon muuttaminen on ** jatkossa helpompaa realloc-funktiolla. (ks. lisaa-metodi). ----------------------------------------------------------------------------*/ { poista_kaikki(); if ( koko <= 0 ) return ""; alkiot = (cJasen **)malloc( koko * (sizeof(cJasen *)) ); lkm = 0; max_lkm = 0; if ( alkiot == NULL ) return EI_VOI_LUODA; max_lkm = koko; return ""; } //---------------------------------------------------------------------------- string cJasenet::luo(const string &tied,const string &nimi,int max_koko) /* ** Luodaan uusi j„senist” valitulla tiedoston nimell„ ja j„senist”n nimell„. ** Taulukon yl„rajaksi luodaan max_jas. ----------------------------------------------------------------------------*/ { IF_ERR_RETURN(luo_taulukko(max_koko)); tiedoston_nimi = tied; koko_nimi = nimi; muutettu = 1; return ""; } //---------------------------------------------------------------------------- string cJasenet::lue_tiedostosta(const string &tied) /* ** Luetaan tiedostosta j„senist”n tiedot. ** ** Metodit olettavat tiedoston olevan seuraavaa muotoa: ** **Kelmien kerho ry **50 **; Kenttien j„rjestys tiedostossa on seuraava: **id|sukunimi etunimi |sotu |katuosoite |postinumero|postiosoite|koti... **1|Ankka Aku |010245-123U|Ankkakuja 6 |12345 |ANKKALINNA |12-1... **2|Susi Sepe |020347-123T| |12555 |Per„mets„ | ... **3|Ponteva Veli |030455-3333| |12555 |Per„mets„ | ... ** ** ** Tiedoston 3. rivilt„ alkaen olevat kommenttirivit (merkitty ;) unohdetaan. ** ** Taulukon yl„rajaksi luodaan tiedosta 2. rivilt„ luettu max_koko. ----------------------------------------------------------------------------*/ { ifstream f(tied.c_str()); if ( !f ) return TIED_EI_AUKEA; string nimi; lue_rivi(f,nimi); if ( !f ) return EI_NIMEA; int max_koko; lue_rivi(f,max_koko); if ( !f ) return EI_MAXKOKOA; IF_ERR_RETURN(luo_taulukko(max_koko)); tiedoston_nimi = tied; koko_nimi = nimi; string rivi; cJasen uusi; while ( getline(f,rivi) ) { if ( rivi == "" || rivi[0] == ';' ) continue; uusi.setAsString(rivi); // f >> uusi; // vaatisi kunkin rivin olemisen t„ydellisen„, muuten OK! IF_ERR_RETURN(lisaa(uusi)); } muutettu = 0; return ""; } //---------------------------------------------------------------------------- string cJasenet::talleta(const string &tied) { if ( !muutettu ) return ""; string tiedosto(tied); if ( tied == "" ) tiedosto = tiedoston_nimi; ofstream f(tiedosto.c_str()); if ( !f ) return TIED_EI_AUKEA; f << koko_nimi << endl; f << max_lkm << endl; if ( !f ) return OTS_EI_KIRJ; for (int i=0; ikentta_jonoksi(KENTTA); string sb = pjb->kentta_jonoksi(KENTTA); return sa.compare(sb); } #include class cVertaa { int kentta; public: cVertaa(int k) : kentta(k) { } bool operator() (const cJasen *a,const cJasen *b) const { // a < b string sa = a->kentta_jonoksi(kentta); string sb = b->kentta_jonoksi(kentta); return sa < sb; } }; void cJasenet::lajittele(int k) { // 1. STL sort // n. tehdään lajittelu itse O(n2) // KENTTA = k; // qsort(alkiot,lkm,sizeof(alkiot[0]),vertaa); // sort(alkiot,alkiot+lkm); // sort(alkiot,alkiot+lkm,greater()); sort(alkiot,alkiot+lkm,cVertaa(k)); // sort(alkiot,alkiot+lkm); } class cVertaa2 { int kentta; const cJasenet *jasenet; public: cVertaa2(int k, const cJasenet *ijasenet) : kentta(k), jasenet(ijasenet) { } bool operator() (int a,int b) const { // a < b // string sa = jasenet->anna(a).kentta_avaimeksi(kentta); string sa = jasenet->anna(a).kentta_jonoksi(kentta); string sb = jasenet->anna(b).kentta_jonoksi(kentta); return sa < sb; } }; void cJasenet::etsi(vector &loytyneet,int k,const string &jono) { for (int i=0; i