/* ********************************************************* HENKTIE2.CPP Harjoitellaan sisäkkäisten tietueiden käyttöä. Lukee näppäimistöltä henkilötiedot ja tulostaa ne sitten näytölle. Muutettu: 27.6.2002 / Miika Nurminen Tarkoitus: sukupuoli luetelluksi tyypiksi (enum). syöttö ja tulostus 'rakenteiseksi' käyttäen uusia syöttö- ja tulostusfunktioita. Päivämäärän syöttöön lisätty tarkistus sscanf:ia käyttäen. Sukupuolen tarkistus merkkipohjaisena. Lisätty päivämäärän järkevyyden tarkastusfunktio. Muutettu: 2.7.2002 / MN Tarkoitus: Lisätty funktiot tiedoston käsittelyä varten ********************************************************* */ #include #include #include #include using namespace std; // Tietotyyppinen määritykset ------------------------------------------------- struct paivamaara { int pp, kk, vvvv; }; struct nimet { string etunimi, sukunimi; }; // lueteltu tyyppi sukupuolen esittämiseen enum sukupuoli { M,N }; struct henkilotiedot { nimet nimi; paivamaara synt_aika; sukupuoli sp; }; // Yleisiä apufunktioita ------------------------------------------------------ void tyhjenna_puskuri() { int tyhjat = cin.rdbuf()->in_avail(); // montako merkkiä puskurissa? cin.ignore(tyhjat,'\n'); // tyhjennetään puskuri } // yleinen virhetilanteen tulostusfunktio void virhe() { cout << "Virheellinen syöte!" << endl; } // palauttaa 0, jos päivämäärä kunnossa, muuten 1. int tarkasta(const paivamaara& pvm) { if (pvm.pp<1 || pvm.pp>31) return 1; // tähän voisi lisätä tarkistuksen joka kuukaudelle erikseen + karkausvuodet if (pvm.kk<1 || pvm.kk>12) return 1; if (pvm.vvvv<-9999 || pvm.vvvv>9999) return 1; // keinotekoinen raja return 0; } // muuntaa kokonaisluvun string-merkkijonoksi string int2str(int i) { char c[34]=""; // luodaan tilapäinen c-merkkijono // muunnosfunktion kutsumista varten itoa(i,c,10); // muunnetaan 10-järjestelmässä return string(c); } // Tietotyyppien syöttöfunktiot ----------------------------------------------- void lue_tiedot(nimet& nimi) { cout << "Anna etunimesi > "; getline(cin, nimi.etunimi); cout << "Anna sukunimesi > "; getline(cin, nimi.sukunimi); } void lue_tiedot(paivamaara& pvm) { string s; while(1) { // toistetaan, kunnes tiedot on syötetty oikein. cout << "Anna syntymäpäiväsi muodossa pp.kk.vvvv > "; getline(cin,s); sscanf(s.c_str(),"%d.%d.%d",&(pvm.pp),&(pvm.kk),&(pvm.vvvv)); // tarkistetaan päivämäärän oikeellisuus if (tarkasta(pvm)) virhe(); else return; } } void lue_tiedot(sukupuoli& sp) { char c; while(1) { // toistetaan, kunnes tiedot on syötetty oikein. cout << "Anna sukupuolesi (n=nainen, m=mies) > "; cin >> c; tyhjenna_puskuri(); // tyhjennetään varmuuden vuoksi syöttöpuskuri switch(c) { case 'm': case 'M': sp=M; return; // break jätetty tarkoituksella pois; return poistuu koko funktiosta case 'n': case 'N': sp=N; return; // break jätetty tarkoituksella pois; return poistuu koko funktiosta default: virhe(); } } } void lue_tiedot(henkilotiedot& henkilo) { cout << "\n\n"; lue_tiedot(henkilo.nimi); lue_tiedot(henkilo.synt_aika); lue_tiedot(henkilo.sp); } /* oletetaan, että tiedoston rivit ovat muodossa etunimi sukunimi pv|kk|vv|sukupuoli */ void muodosta_tiedostosta(henkilotiedot& h, istream& i) { getline(i,h.nimi.etunimi); getline(i,h.nimi.sukunimi); string s; getline(i,s); char c; // tilapäismuuttuja sukupuolta varten sscanf(s.c_str(),"%d|%d|%d|%c",&(h.synt_aika.pp),&(h.synt_aika.kk),&(h.synt_aika.vvvv),&c); switch(c) { case 'M': h.sp = M; break; case 'N': h.sp = N; break; default: virhe(); } } // Tietotyyppien tulostusfunktiot --------------------------------------------- void tulosta(const string& otsikko, const sukupuoli& sp) { cout << otsikko; switch (sp) { case M: cout << "mies"; break; case N: cout << "nainen"; break; default: cout << "tuntematon"; break; } cout << endl; } void tulosta(const string& otsikko, const paivamaara& pvm) { cout << otsikko << pvm.pp << "." << pvm.kk << "." << pvm.vvvv << endl; } void tulosta(const string& otsikko, const nimet& n) { cout << otsikko << n.etunimi << " " << n.sukunimi << endl; } void tulosta(const henkilotiedot& henkilo) { cout << "\n\n"; cout << "Henkilötietosi:\n"; tulosta(" Nimi: ",henkilo.nimi); tulosta(" Syntymäpäivä: ",henkilo.synt_aika); tulosta(" Sukupuoli: ",henkilo.sp); } ostream& tiedostoon(const henkilotiedot& h,ostream& os) { os << h.nimi.etunimi << endl; os << h.nimi.sukunimi << endl; os << int2str(h.synt_aika.pp) <<"|"<< int2str(h.synt_aika.kk) <<"|"<< int2str(h.synt_aika.vvvv) <<"|"; switch (h.sp) { case M: os << "M"; break; case N: os << "N"; break; default: break; } return os; } // Pääohjelma ----------------------------------------------------------------- int main(void) { henkilotiedot mina; /* ifstream i("henkilo.txt"); string s; muodosta_tiedostosta(mina,i); tulosta(mina); */ lue_tiedot(mina); tulosta(mina); ofstream o("henkilo.txt"); tiedostoon(mina,o); return 0; }