/* kentta.h */ /*---------------------------------------------------------------------------- K E N T T A . H Tietueen yleinen kentt„ ja siit„ peritty joukko hy”dyllisi„ kentti„. Tekij„t: Vesa Lappalainen Ohjelmointikurssi 1996 Tehty: 07.01.1996/vl Muutettu: 14.01.1996/vl Mit„ muutettu: + help_aihe Julkiset metodit: ----------------- string jonoksi() const = 0; - muutetaan kentt„ merkkijonoksi cKenttavirhe sijoita(const char *s) cKenttavirhe sijoita(const string &st) cKenttavirhe sijoita(const cKentta &kentta); - sijoittaa merkkijonon tai kentan t„h„n kentt„„n. palauttaa joko KENTTA_OK tai sitten virheen josta selvi„„ vakavuus ja itse virhe tekstin„. cKenttavirhe ota_seuraava(istream &is, const char *erotin); - ottaa tietovirrasta is seuraavan "palasen" eli johonkin erotinmerkkkin asti olevan jonon. T„m„ ei voi ylitt„„ rivirajaa, eli jos rivin loppu tulee vastaan, niin se laitetaan takaisin tietovirtaan. Kent„st„ poistetaan ylim„„r„iset tyhj„t. int tyhjenna(istream &is) - kun kaikki kent„t rivilt„ luettu, pit„„ t„ll„ siirty„ "seuraavalle riville" ostream &operator<<(ostream &os,const cKentta &k); - tulostaa kent„n tietovirtaan muunnos_funktio muunnos() const - palauttaa muunnosfunktion osoitteen. Muunnosfunktiolla tehd„„n kentt„„n sen oikeellisuutta vastaava muunnos. Muunnosfunktiota on voitava k„ytt„„ jokaisen painetun merkin j„lkeen. Muunosfunktio voi esimerkiksi poistaa laittomat merkit jonosta. const char *help_aihe() const - paluttaa merkkijonon t„m„n kent„n "context sensitive" hakusanasta. esim. "t_nimi" (t = topic). Luokkahierarkia: help-aihe ---------------- class cKentta NULL class cJonoKentta : public cKentta t_ok class cJono1isoksiKentta : public cJonoKentta t_alku_isoksi class cJonoIsoksiKentta : public cJonoKentta t_1_isoksi class cIntKentta : public cKentta t_int class cDoubleKentta : public cKentta t_double class cHetuKentta : public cJonoKentta t_hetu class cHetu1Kentta : public cHetuKentta t_hetu_1 class cNimiKentta : public cJonoKentta t_nimi class cNimi1Kentta : public cNimiKentta t_nimi_1 class cPuhKentta : public cJonoKentta t_puh class cPostinumeroKentta : public cJonoKentta t_postinumero class cVirheKentta : public cJonoKentta t_virhe Kentt„„n voidaan sijoittaa esim. merkkijono metodilla sijoita("kissa") Metodi palauttaa cKenttavirhe -luokan, jossa on virheen vakavuus. Vakavuus kysyt„„n metodilla Taso(): KENTTA_OK, KENTTA_VAROITUS, // Kentt„ muutettu, riitt„„ ilmoitus n„ytt””n KENTTA_MUUTETTU_KYSY, // Kentt„ muutettu, kysy uudelleen KENTTA_UUDELLEEN, // Kentt„„ ei muutettu, kysytt„v„ uudelleen KENTTA_OK_ONKO_AINOA, // Syntaksi OK, yksik„sitteisyys tarkistettava KENTTA_OK_VAROITA_MUUT, // Syntaksi OK, ei-yksik„sitteisyys varmistettava KENTTA_TUNTEMATON_VIRHE Lis„ksi luokassa cKenttavirhe on virhett„ vastaava teksti C-merkkijonona, joka voidaan kysy„ metodilla Virhe(). Normaalien kenttien lis„ksi voi olla viel„ erikoiskentti„, mutta niit„ ei ole toteutettu viel„. Erikoiskentti„ olisivat esimerkiksi taulukkotyyppiset kent„t. (ks. eKenttatyyppi) Kent„lt„ voidaan my”s kysy„ metodilla muunnos() osoite muunnosfunktiolle, jolla kent„st„ poistetaan kentt„„n kuulumattomat merkit, muutetaan mahdollisesti kent„n kirjaimia isoiksi ja pieniksi jne. Kentt„ voidaan tarvittaessa muuttaa merkkijonoksi (string) metodilla jonoksi(). Kentt„ voidaan tulostaa tietovirtaan esim. cout << kentta Kentta voidaan ottaa tietovirrasta metodilla kentta.ota_seuraava(cin,"|,") miss„ "|," on erotinjoukko, eli erottimena joko | tai , ----------------------------------------------------------------------------*/ #ifndef __KENTTA_H #define __KENTTA_H #include #include using namespace std; #include "muunnos.h" #include "mjonot.h" #include "mjonotpp.h" int ota_seuraava(istream &is, char *s, int max_koko, const char *erotin); int tyhjenna(istream &is); //---------------------------------------------------------------------------- // Virhetasot: //---------------------------------------------------------------------------- typedef enum { KENTTA_OK, // Kentt„ kaikin puolin kunnossa KENTTA_VAROITUS, // Kentt„ muutettu, riitt„„ ilmoitus n„ytt””n KENTTA_MUUTETTU_KYSY, // Kentt„ muutettu, kysy uudelleen KENTTA_UUDELLEEN, // Kentt„„ ei muutettu, kysytt„v„ uudelleen KENTTA_OK_ONKO_AINOA, // Syntaksi OK, yksik„sitteisyys tarkistettava KENTTA_OK_VAROITA_MUUT, // Syntaksi OK, ei-yksik„sitteisyys varmistettava KENTTA_TUNTEMATON_VIRHE } eVirhetaso; //---------------------------------------------------------------------------- // Kentt„tyypit: //---------------------------------------------------------------------------- typedef enum { KENTTA_NORMAALI, // Tavallinen yhden alkion kentta KENTTA_LISTA, // Monesta alkiosta koostuva kentta KENTTA_TUNTEMATON } eKenttatyyppi; //---------------------------------------------------------------------------- // Luokka virheelle: //---------------------------------------------------------------------------- class cKenttavirhe { eVirhetaso taso; const char *virhe; void alusta(eVirhetaso t=KENTTA_OK, const char *v="") { virhe = v; taso = t; } public: cKenttavirhe(eVirhetaso t=KENTTA_OK,const char *v="") { alusta(t,v); } const char *Virhe() { return virhe; } eVirhetaso Taso() { return taso; } }; //---------------------------------------------------------------------------- // Pari makroa kirjoitusty”n pienent„miseksi: //---------------------------------------------------------------------------- #define VIRHE(t,v) cKenttavirhe((t),(v)) #define cKENTTA_OK cKenttavirhe(KENTTA_OK) //---------------------------------------------------------------------------- // // cKentta // ======= // // Abstrakti luokka yleiselle tietueen kent„lle // Jokaiseen kentt„„n on teht„v„ ainakin seuraavat metodit: // alusta(const char *) // - alustaa kent„n merkkijonolla ja palauttaa jonkin // kenttavirheen tai KENTTA_OK // string jonoksi() // - muuttaa kent„n merkkijonoksi // Lis„ksi jos katsotaan tarpeelliseksi, kannattaa tehd„ // muunnosfunktion osoitteen palauttava metodi: // muunnos_funktio muunnos() // - palauttaa funktion, jolla merkkijono muunnetaan vastaamaan // kentt„„n sallitua muotoa. Esimerkiksi jos kentt„„n sallitaan // vain numerot, voidaan palauttaa jono_numerot -funktion osoite // My”s sijoituksia voi tehd„: // =(string st) // =(int i) // =(long l) // =(double d) // =(const char *s) // ehk„ t„rkein sijoitus //---------------------------------------------------------------------------- class cKentta { protected: virtual cKenttavirhe alusta(const char *s) = 0; virtual int muunna_ja_vertaa(char *p, int maxp, const char *s, muunnos_funktio fun=NULL) const; public: // cKentta(const char *s="") { alusta(s); } virtual ~cKentta() {;} virtual string jonoksi() const = 0; virtual const char *help_aihe() const { return "NULL"; } cKenttavirhe sijoita(const char *s) { return alusta(s); } cKenttavirhe sijoita(const string &st) { return sijoita(st.c_str());} cKenttavirhe sijoita(const cKentta &kentta); //virtual const char *operator=(const char *s) { sijoita(s); return s; } //virtual void operator=(const cKentta &k) { sijoita(k); } //virtual const string &operator=(const string &st) { sijoita(st); return st;} //virtual long operator=(long ul); //virtual int operator=(int ui); //virtual double operator=(double ud); virtual cKenttavirhe ota_seuraava(istream &is, const char *erotin); friend ostream &operator<<(ostream &os,const cKentta &k); virtual muunnos_funktio muunnos() const { return NULL; } }; inline ostream &operator<<(ostream &os,const cKentta &k) { os << k.jonoksi(); return os; } inline cKenttavirhe cKentta::sijoita(const cKentta &kentta) { if ( this == &kentta ) return KENTTA_OK; return sijoita(kentta.jonoksi()); } inline cKenttavirhe cKentta::ota_seuraava(istream &is, const char *erotin) { char s[100]; int err = ::ota_seuraava(is,s,sizeof(s),erotin); if ( err ) { sijoita(""); return VIRHE(KENTTA_VAROITUS,"Stream virhe"); } return sijoita(s); } inline int cKentta::muunna_ja_vertaa(char *p,int maxp,const char *s, muunnos_funktio fun) const // Sijoitetaan s jonoon p. Muutetaan p muunnoksella ja tutkitaan // muuttuiko muunnoksessa. Jos muuttui, palautetaan 1, muutoin 0 // Muunnosfunktiota fun k„ytet„„n tutkimisen j„lkeen p:hen. // fun voi olla esim. poista_tyhjat tms. { if ( p == NULL ) return 0; kopioi_jono(p,maxp,s); if ( muunnos() ) muunnos()(p); int eri = onko_samat(p,s); if ( fun ) fun(p); return eri; } #if 0 // Turha kirjoitaa, koska eiv„t valitettavasti periydy C++:ssa! inline int cKentta::operator=(int ui) { char s[20]; sijoita(int_jonoksi(N_S(s),ui,"%d")); return ui; } inline long cKentta::operator=(long ul) { char s[20]; sijoita(double_jonoksi(N_S(s),ul,"%1.0lf")); return ul; } inline double cKentta::operator=(double ud) { char s[20]; sijoita(double_jonoksi(N_S(s),ud,"%4.2lf")); return ud; } #endif //---------------------------------------------------------------------------- // Tietueen kentt„ merkkijonona //---------------------------------------------------------------------------- class cJonoKentta : public cKentta { protected: string jono; virtual cKenttavirhe alusta(const char *s) { jono = s; return KENTTA_OK; } virtual int sijoita_muuttuuko(const char *s,muunnos_funktio fun = NULL); public: cJonoKentta(const char *s=NULL) : jono(s?s:"") {;} virtual string jonoksi() const { return jono; } virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual const char *help_aihe() const { return "t_ok"; } }; inline int cJonoKentta::sijoita_muuttuuko(const char *s,muunnos_funktio fun) // Muunnetaan s muunnoksella ja sijoitetaan se jonoon ja tutkitaan // muuttuiko muunnoksessa. Jos muuttui, palautetaan 1, muutoin 0 // Jos fun == NULL (oletus), poistetaan vertailun j„lkeen tyhjat { char apu[100]; if ( fun == NULL ) fun = poista_tyhjat; int eri = muunna_ja_vertaa(N_S(apu),s,fun); jono = apu; return eri; } //---------------------------------------------------------------------------- // Tietueen kentt„ merkkijonona jonka 1. merkki isoksi //---------------------------------------------------------------------------- class cJono1isoksiKentta : public cJonoKentta { protected: virtual cKenttavirhe alusta(const char *s) { sijoita_muuttuuko(s); return KENTTA_OK; } public: cJono1isoksiKentta(const char *s=NULL) : cJonoKentta(s) {;} virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual muunnos_funktio muunnos() const { return jono_1_isoksi; } virtual const char *help_aihe() const { return "t_1_isoksi"; } }; //---------------------------------------------------------------------------- // Tietueen kentt„ merkkijonona jonka kaikki merkit isoiksi //---------------------------------------------------------------------------- class cJonoIsoksiKentta : public cJonoKentta { protected: virtual cKenttavirhe alusta(const char *s) { sijoita_muuttuuko(s); return KENTTA_OK; } public: cJonoIsoksiKentta(const char *s=NULL) : cJonoKentta(s) {;} virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual muunnos_funktio muunnos() const { return jono_isoksi; } virtual const char *help_aihe() const { return "t_isoksi"; } }; //---------------------------------------------------------------------------- // Tietueen kentt„ kokonaislukuna //---------------------------------------------------------------------------- class cIntKentta : public cKentta { protected: int i; virtual cKenttavirhe alusta(const char *s); public: cIntKentta(int ui = TYHJA_ARVO) { i = ui; } virtual string jonoksi() const { char s[20]; int_jonoksi(N_S(s),i,"%d"); return string(s); } virtual int operator=(int ui) { i = ui; return ui; } virtual operator int() const { return i; } virtual muunnos_funktio muunnos() const { return int_muunnos; } virtual const char *help_aihe() const { return "t_int"; } }; inline cKenttavirhe cIntKentta::alusta(const char *s) { char p[30]; int ero = muunna_ja_vertaa(N_S(p),s); i = jono_intiksi(p,"%d"); return ero ? VIRHE(KENTTA_MUUTETTU_KYSY,"Laittomia merkkej„!") : cKENTTA_OK; } //---------------------------------------------------------------------------- // Tietueen kentt„ reaalilukuna //---------------------------------------------------------------------------- class cDoubleKentta : public cKentta { protected: double d; virtual cKenttavirhe alusta(const char *s); public: cDoubleKentta(int ud = TYHJA_ARVO) { d = ud; } virtual string jonoksi() const { char s[20]; double_jonoksi(N_S(s),d,"%4.2lf"); return string(s); } virtual double operator=(double ud) { d = ud; return ud; } virtual muunnos_funktio muunnos() const { return double_muunnos; } virtual const char *help_aihe() const { return "t_double"; } }; inline cKenttavirhe cDoubleKentta::alusta(const char *s) { char p[30]; int ero = muunna_ja_vertaa(N_S(p),s); d = jono_doubleksi(p,"%lf"); return ero ? VIRHE(KENTTA_MUUTETTU_KYSY,"Laittomia merkkej„!") : cKENTTA_OK; } //---------------------------------------------------------------------------- // Tietueen kentt„ henkil”tunnuksena //---------------------------------------------------------------------------- cKenttavirhe hetu_tarkistus(string &jono,const char *sa,int yks); //---------------------------------------------------------------------------- class cHetuKentta : public cJonoKentta { protected: virtual cKenttavirhe alusta(const char *s) { return hetu_tarkistus(jono,s,0); } public: virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual muunnos_funktio muunnos() const { return hetu_muunnos; } virtual const char *help_aihe() const { return "t_hetu"; } }; //---------------------------------------------------------------------------- // Tietueen kentt„ henkil”tunnuksena joita saa olla vain yksi kpl //---------------------------------------------------------------------------- class cHetu1Kentta : public cHetuKentta { protected: virtual cKenttavirhe alusta(const char *s) { return hetu_tarkistus(jono,s,1); } public: virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual const char *help_aihe() const { return "t_hetu_1"; } }; //---------------------------------------------------------------------------- // Tietueen kentt„ nimen„ //---------------------------------------------------------------------------- class cNimiKentta : public cJonoKentta { protected: virtual cKenttavirhe alusta(const char *s) { sijoita_muuttuuko(s); return KENTTA_OK; } public: virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual muunnos_funktio muunnos() const { return jono_alku_isoksi;} virtual const char *help_aihe() const { return "t_nimi"; } }; //---------------------------------------------------------------------------- // Tietueen kentt„ nimen„ joita mahdollisesti saa olla vain 1 kpl //---------------------------------------------------------------------------- class cNimi1Kentta : public cNimiKentta { protected: virtual cKenttavirhe alusta(const char *s) { sijoita_muuttuuko(s); return KENTTA_OK_VAROITA_MUUT; } public: virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual const char *help_aihe() const { return "t_nimi_1"; } }; //---------------------------------------------------------------------------- // Tietueen kentt„ puhelinnumerona //---------------------------------------------------------------------------- class cPuhKentta : public cJonoKentta { protected: virtual cKenttavirhe alusta(const char *s); public: virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual muunnos_funktio muunnos() const { return puh_muunnos; } virtual const char *help_aihe() const { return "t_puh"; } }; inline cKenttavirhe cPuhKentta::alusta(const char *s) { if ( sijoita_muuttuuko(s) ) return VIRHE(KENTTA_MUUTETTU_KYSY,"V„„ri„ merkkej„!"); return KENTTA_OK; } //---------------------------------------------------------------------------- // Tietueen kentt„ postinumerona //---------------------------------------------------------------------------- class cPostinumeroKentta : public cJonoKentta { protected: virtual cKenttavirhe alusta(const char *s); public: virtual const char *operator=(const char *s) { sijoita(s); return s; } virtual muunnos_funktio muunnos() const { return numerot_muunnos;} virtual const char *help_aihe() const { return "t_postinumero";} }; inline cKenttavirhe cPostinumeroKentta::alusta(const char *s) { if ( sijoita_muuttuuko(s) ) return VIRHE(KENTTA_MUUTETTU_KYSY,"V„„ri„ merkkej„!"); int len = jono.length(); if ( len != 5 && len != 0 ) return VIRHE(KENTTA_MUUTETTU_KYSY,"Postinumerossa t„ytyy olla 5 numeroa!"); return KENTTA_OK; } //---------------------------------------------------------------------------- // Tietueen kentt„ virheen„ //---------------------------------------------------------------------------- class cVirheKentta : public cJonoKentta { protected: virtual cKenttavirhe alusta(const char *s); public: cVirheKentta(const char *s): cJonoKentta(s) {;} virtual const char *help_aihe() const { return "t_virhe"; } }; inline cKenttavirhe cVirheKentta::alusta(const char *s) { cJonoKentta::alusta(s); return VIRHE(KENTTA_VAROITUS,"Kentt„virhe"); } #undef cKENTTA_OK #undef VIRHE #endif