/* kerho.cpp */ /****************************************************************************/ /* ** K E R H O . C P P ** ** Kerho-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: 11.01.1996 ** Mit„ muutettu: + Lis„tt„v„n j„senen rekister”inti ** + laske montako muuta ** + tiedoston lukemisessa tyhj„t rivit eiv„t en„„ ** haittaa ** ** Public-metodeja: ** ================ ** ** Metodit palauttavat yleens„ virheen merkkijonona, joka voidaan ** suoraan tulostaa. Jos virhett„ ei tapahdu, palautetaan NULL. ** ** cKerho(int koko=0) ** - kerhon luominen, jos koko = 0, ei luoda j„sentaulukkoa ** ** ~cKerho() ** - kerhon h„vitt„minen, jos kerhoa ei ole talletettu, talletetaan ** viimeist„„n nyt (mahd. virheilmoitus harakoille) ** ** const char *lisaa(const cJasen &jasen); ** - lis„t„„n uusi j„sen. J„senest„ tehd„„n kopio. Jos tila loppuu, ** yritet„„n kasvattaa tilaa. ** ** const char *korvaa(int i,const cJasen &jasen); ** - korvataan i:s j„sen uudella. Jos i v„„rin, ei tehd„ mit„„n (pal 1). ** ** const cJasen &anna(int i) const ** - otetaan kerhosta i:s j„sen. Jos i v„„rin, otetaan viim. j„sen. ** Jollei ole viimeist„k„„n, palautetaan virhej„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); ** ** const char *luo(const string &tied,const string &nimi, ** - luo j„senist”n uutta kerhoa varten, mahd. vanha talletetaan ** ** const char *lue(const string &tied); ** - luetaan uusi j„senist”, mahd. vanha talletetaan ** ** const char *talleta(const string &tied=""); ** - talletetaan j„sensist„. Jos tied=="", k„ytet„„n luettaessa ** annettua nimi„. ** ** const string &Kerhon_nimi() const ** - palauttaa kerhon koko nimen. ** ** int jasenlkm() const ** - palauttaa kerhon j„senm„„r„n ** ** const string &Tiedoston_nimi() const ** - paluttaa viimeksi k„ytetyn tiedoston nimen ** ** int Muutettu() const ** - palauttaa 1, mik„li kerhoa on muutettu talletusten j„lkeen ja ** 0 muuten. ** ** int laske_montako_muuta(const cJasen &jasen, int k,int &kuka) ** - laskee monellako j„senell„ on kent„ss„ k samat tiedot ** kuin jasenella. Palautetaan my”s viimeinen ko. j„sen. ** --------------------------------------------------------------------------- ** ** Tietorakenne on seuraava: ** ========================= ** ** ** cKerho cJasen ** ------ ** | | ------ ** | | | 1 | ** | 7 | max |---->| | ** | 3 | jasenet | | | ------ ** | o--+------>|-----| | ------ | 2 | ** ------ | o--+-----| | | ** |-----| |----->| | ** | o--+------------| ------ ------ ** |-----| | 3 | ** | o--+--------------------------->| | ** |-----| | | ** | o--+--? ------ ** |-----| ** | o--+--? ** |-----| ** | o--+--? ** |-----| ** | o--+--? ** |-----| ** ** ** Kerho ei tied„ j„seniens„ ominaisuuksia. ** Kerho pit„„ huolta siit„, onko kerho muuttunut, eli tarvitseeko se ** talletusta vaiko ei. ** Tiedoston muoto, ks. lue_tiedostosta - metodi ** */ #include #include #include "mjonotpp.h" #include "kerho.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) { const char *virhe=(v); if ( virhe ) return virhe; } //============================================================================ // Virheilmoitukset: //============================================================================ static const char *EI_VOI_LUODA = "J„senist”lle ei saada varattua tilaa" " muistista!"; static const char *LIIKAA_JASENIA = "Liikaa j„seni„, ei voi lis„t„!"; static const char *EI_SAA_JASENTA = "Ei saada tilaa uudelle j„senelle!"; static const char *EI_NIMEA = "Ei kerhon 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 *JASEN_EI_KIRJ = "J„sent„ ei voi kirjoittaa!"; static const char *LAITON_INDEKSI = "Laiton indeksi!"; static const char *EI_REKISTEROITY= "J„sent„ ei ole rekister”ity!"; //============================================================================ // Private -metodeja: //============================================================================ //---------------------------------------------------------------------------- void cKerho::poista_jasentaulukko() { if ( max_jasenia > 0 ) free(jasenet); max_jasenia = 0; } //---------------------------------------------------------------------------- void cKerho::poista_jasenet() { for (int i=0; i= max_jasenia ) IF_ERR_RETURN(kasvata_kokoa()); cJasen *uusi_jasen = new cJasen(jasen); if ( uusi_jasen == NULL ) return EI_SAA_JASENTA; uusi_jasen->rekisteroi(); jasenet[jasenia] = uusi_jasen; jasenia++; muutettu = 1; return NULL; } //---------------------------------------------------------------------------- const char *cKerho::korvaa(int i,const cJasen &jasen) /* ** Korvataan paikassa i oleva j„sen uudella j„senell„. ** Vain rekister”ityneet j„senet hyv„ksyt„„n. ** Jos samat tiedot kuin vanhalla j„senell„, ei korvata. ----------------------------------------------------------------------------*/ { if ( ulkona(i) ) return LAITON_INDEKSI; if ( jasenet[i]->sama_rekisteri(jasen) == 0 ) return EI_REKISTEROITY; if ( *(jasenet[i]) == jasen ) return 0; muutettu = 1; *(jasenet[i]) = jasen; return NULL; } //---------------------------------------------------------------------------- const char *cKerho::luo_jasentaulukko(int koko) /* ** Luodaan j„sentaulukko valitun kokoiseksi. Jos j„sentaulukko on ** ennest„„n siell„ on se parasta poistaa. ** Luomisessa k„ytet„„n malloc-funktiota, jotta koon muuttaminen on ** jatkossa helpompaa realloc-funktiolla. (ks. lisaa-metodi). ----------------------------------------------------------------------------*/ { poista_jasenisto(); if ( koko <= 0 ) return NULL; jasenet = (cJasen **)malloc( koko * (sizeof(cJasen *)) ); jasenia = 0; max_jasenia = 0; if ( jasenet == NULL ) return EI_VOI_LUODA; max_jasenia = koko; return NULL; } //---------------------------------------------------------------------------- const char *cKerho::luo(const string &tied,const string &nimi,int max_jas) /* ** Luodaan uusi kerho valitulla tiedoston nimell„ ja kerhon nimell„. ** Taulukon yl„rajaksi luodaan max_jas. ----------------------------------------------------------------------------*/ { IF_ERR_RETURN(luo_jasentaulukko(max_jas)); tiedoston_nimi = tied; kerhon_nimi = nimi; muutettu = 1; return NULL; } //---------------------------------------------------------------------------- const char *cKerho::lue_tiedostosta(const string &tied) { /* ** Luetaan tiedostosta kerhon tiedot. ** ** Metodit olettavat tiedoston olevan seuraavaa muotoa: ** **Kelmien kerho ry **50 **; Kenttien j„rjestys tiedostossa on seuraava: **; sukunimi etunimet|sotu |katuosoite |postinumero|postiosoite|koh... **Ankka Aku |010245-123U|Ankkakuja 6 |12345 |ANKKALINNA |123... **Susi Sepe |020347-123T| |12555 |Per„mets„ | ... **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_jasentaulukko(max_koko)); tiedoston_nimi = tied; kerhon_nimi = nimi; int tunniste; cJasen jasen; IF_ERR_RETURN(jasen.lue_lisatiedot(f,tiedoston_nimi)); while ( f ) { tunniste = f.get(); if ( tunniste == 0 || tunniste == ';' || tunniste == '\n' ) continue; if ( tunniste == EOF ) break; // Ei kai ole mahdollista??? f.putback(tunniste); f >> jasen; // vaatii kunkin rivin k„sittelemisen t„ydellisen„, muuten OK! if ( !jasen.tyhja() ) IF_ERR_RETURN(lisaa(jasen)); } muutettu = 0; return NULL; } //---------------------------------------------------------------------------- const char *cKerho::talleta(const string &tied) { if ( !muutettu ) return NULL; string tiedosto(tied); if ( tied == "" ) tiedosto = tiedoston_nimi; ofstream f(tiedosto.c_str()); if ( !f ) return TIED_EI_AUKEA; f << kerhon_nimi << endl; f << max_jasenia << endl; if ( !f ) return OTS_EI_KIRJ; cJasen jasen; IF_ERR_RETURN(jasen.kirjoita_lisatiedot(f,tiedoston_nimi)); for (int i=0; ikentta_jonoksi(k) == kentta && jasenet[i]->sama_rekisteri(jasen) == 0 ) { lkm++; kuka = i; } } return lkm; }