/* tarkkell.cpp */ /* Ohjelmalla testataan tarkista_kello-aliohjelman toiminta / vl-2000 */ /* Ohjelma on samalla malli automaattisesta testaamisesta, jollaista */ /* tulee käyttää, mikäli vaihtoehtoja on paljon ja yhden toiminnon */ /* muuttaminen saattaa pilata olemassa olevat toiminnot. */ /* Projektiin tarkkell.cpp, mjonotpp.cpp, mjonot.c (vstring.cpp) */ /* Guru-tehtävä: Muuta käyttämään try-catchia */ #include #include #include #include #include #include "mjonotpp.h" struct tRaja { /* Tyyppi tarkistuksen rajoille */ double ala; /* Pienin luku */ double yla; /* Suurin luku */ const char *yks; /* "Yksikkö", eli esim. "tunnit" */ const char *erotin; /* Millä erotettu seuraavasta osasta */ int des; /* Käsitelläänkö "desimaalisena" ja /mitä */ }; static tRaja KELLORAJAT[] = { { 0,23,"tunnit" ,":" ,0}, { 0,59,"minuutit" ,":" ,0}, { 0,59,"sekunnit" ,"." ,0}, { 0,99,"sadasosat","" ,100}, { 0, 0,NULL ,NULL,0} }; //======================================================================== class cLukuVirhe { string ilmoitus; int paikka; public: cLukuVirhe() : ilmoitus(""), paikka(-1) {} cLukuVirhe(const string &s,int p) : ilmoitus(s), paikka(p) { } operator int() const { return paikka != -1; } string getIlmoitus() const { return ilmoitus; } int getPaikka() const { return paikka; } cLukuVirhe &operator+=(int i) { paikka += i; return *this; } }; ostream &operator<<(ostream &os, const cLukuVirhe &v) { os << v.getIlmoitus(); return os; } const string NUMEROT = "0123456789"; //======================================================================== cLukuVirhe tarkista_luku(const string &s,const tRaja &r) // Funktio palauttaa tyhjän jonon, jos luku on virheetön. Silloin // myös paikka = -1. Muuten palautetaan virhettä vastaava jono // ja virheen alkamispaikka jonossa. { double d; char paluu[80]; int n; if ( r.yks == NULL ) { /* Tässä tämä ei toteudu koskaan, miksi? */ return cLukuVirhe("Liikaa merkkejä!",0); } if ( s == "" ) { /* Tyhjä jono */ return cLukuVirhe(string("Jono katkeaa kesken, puuttuu ") + r.yks,0); } if ( ( n = sallituissa(s,NUMEROT) ) >= 0 ) { /* Vain numeroita? */ return cLukuVirhe(string("Merkki '") + s[n] + "' väärin!",n); } if ( sscanf(s.c_str(),"%lf",&d) == 0 ) { return cLukuVirhe(s + " ei kelpaa luvuksi",0); } if ( r.des ) { /* Jos halutaan "desimaalimuodossa */ d *= r.des; /* eli etunollat tarpeellisia! */ d /= pow(10,s.length()); /* 12:30:5.2 => 20 */ } /* 12:30:5.02 => 2 */ if ( d < r.ala ) { /* Liian pieni luku*/ sprintf(paluu,"Liian pienet %s: %lg!",r.yks,d); return cLukuVirhe(paluu,0); } if ( d > r.yla ) { /* Liian iso luku */ sprintf(paluu,"Liian isot %s: %lg!",r.yks,d); return cLukuVirhe(paluu,0); } return cLukuVirhe("",-1); } //======================================================================== cLukuVirhe tarkista_kello(const string &jono) // Funktio palauttaa tyhjän jonon, jos aika on virheetön. Silloin // myös paikka = -1. Muuten palautetaan virhettä vastaava jono // ja virheen alkamispaikka jonossa. { string s(jono),pala,vanha_s; cLukuVirhe virhe; int virhe_paikka=0,ir = 0; do { /* Käydään läpi kellonajan osia kunnes virhe tai jono loppu */ vanha_s = s; pala = erota(s,KELLORAJAT[ir].erotin); virhe = tarkista_luku(pala,KELLORAJAT[ir]); if ( virhe ) return virhe += virhe_paikka; ir++; virhe_paikka += pala.length() + 1; } while ( vanha_s != pala ); return cLukuVirhe(); } //======================================================================== int main(void) { struct tTesti { const char *jono; int paikka; }; tTesti testi[] = { { "12:23:00.05" , -1} , /* ok */ { "kissa" , 0} , /* vääriä merkkejä */ { "12:23:" , 6} , /* katkeaa kesken */ { "12 23" , 2} , /* ??? */ { "12k23" , 2} , /* vääriä merkkejä */ { "12:30" , -1} , /* ok */ { "25:30" , 0} , /* liian isot tunnit */ { "12:65" , 3} , /* liian isot minuutit */ { "12:59:78" , 6} , /* liian isot sekunnit */ { "12:23:00.0.0" , 10}, /* liian paljon merkkejä */ { "12:59:10.1000", 9}, /* liian isot sadasosat */ { "12" , -1}, /* ok */ { "" , 0}, /* tyhjä jono */ { "" , -2} /* tyhjä jono */ }; int virheita=0; cLukuVirhe virhe; cout << "------------------------------------------------\n"; cout.setf(ios::left); for (int i=0; testi[i].paikka != -2 ; i++) { cout << "Kello " << setw(20) << testi[i].jono; virhe = tarkista_kello(testi[i].jono); if ( virhe ) { cout << " => " << virhe << "\n"; cout << setw(6+virhe.getPaikka()) << " " << "^"; } if ( virhe.getPaikka() != testi[i].paikka ) { cout << " TESTI VÄÄRIN"; virheita++; } cout << "\n"; } cout << "------------------------------------------------\n"; if ( virheita ) cout << "Testi ei mennyt virheettä läpi!\n"; return 0; }