/* VaihdaTabt3.cpp - vaihtaa tabulaattorit välilyönnekisi Alkuperäinen versio ilman metodien toteutusta ohjelmointikurssin 2002 välikokeen liite. Vesa Lappalainen 17.3.2002 Mallivastaukseksi tehtävään 3 metodit täydentänyt Jani Korhonen 25.3.2002 Täydennykset on kommentoitu koodiin. */ #include #include #include #include #include "mjonotpp.h" #include "streampre.h" #include "dosout.h" using std::ostream; using std::ifstream; using std::string; using std::setw; using std::ios; using std::endl; // lisätty, koska tarvitaan rivinvaihtoa tulostuksessa using std::left; // lisätty, koska halutaan varmistaa tasauksen olevan "left" const MAX_TABS = 50; class cTabs { unsigned int tabs[ MAX_TABS ]; public: cTabs( int deftab = 0 ) { for ( int i = 0; i < MAX_TABS; i++ ) // silmukassa MAX_TABS kertaa tabs[i] = deftab; // sijoitetaan oletusarvo kuhunkin taulukon alkioon } void lisaa( int i, const string &sana ) { if ( i < 0 ) return; // varmistetaan, että indeksi on if ( i > MAX_TABS - 1 ) return; // rajoissa unsigned int pituus = sana.length(); // otetaan sanan pituus talteen if ( pituus > tabs[i] ) // jos pituus on suurempi kuin taulukon vanha arvo tabs[i] = pituus; // niin sijoitetaan se entisen arvon tilalle } unsigned int tab( int i ) { if ( i < 0 ) return 0; // varmistetaan, että indeksi on if ( i > MAX_TABS - 1 ) return 0; // rajoissa return tabs[i]; // ja palautetaan taulukon alkio } }; class cVaihda { cTabs tabs; char erotin; string tiedosto; void tutki_rivi( const string &rivi ); void tulosta_rivi( ostream &os, const string &rivi ) const; public: cVaihda( char iErotin, int minLev ) : tabs( minLev ), erotin( iErotin ) { } void tutki( const string &tied_nimi ); void tulosta( ostream &os ) const; }; void cVaihda::tutki_rivi( const string &s ) { int i = 0; // rivin "sanojen" laskuri string pala; // rivin "sana" = erotin-merkillä erotettu osa riviä string rivi = s; // lokaali kopio parametrista, koska erota-funktio ei // hyväksy const-merkkijonoa while ( rivi != "" ) { // jatketaan niin kauan, kun rivi:ssä on tavaraa pala = erota( rivi, erotin ); // erotetaan pala tabs.lisaa( i, pala ); // lisätään tarvittaessa palan pituus tabs:iin i++; // siirrytään seuraavaan palaan -> indeksi kasvaa } } void cVaihda::tutki( const string &tied_nimi ) { string rivi; // tiedoston rivi tiedosto = tied_nimi; // asetetaan tiedoston nimi attribuuttiin ifstream f( tiedosto.c_str() ); // avataan tiedosto. Huom! ifstreamin // konstruktori haluaa C-merkkijonon if ( !f ) { // tarkistetaan onnistuiko tiedoston avaus cout << "Tiedosto ei aukea!" << endl; return; } while ( getline( f, rivi ) ) // luetaan tiedostoa kunnes rivit loppuvat tutki_rivi( rivi ); // tutkitaan rivin "sanojen" pituudet f.close(); // Suljetaan tiedosto. Tässä tarpeeton, sillä f olio // sulkee tiedoston destruktorissaan. } void cVaihda::tulosta_rivi( ostream &os, const string &s ) const { int i = 0; // rivin "sanojen" laskuri string pala; // rivin "sana" = erotin-merkillä erotettu osa riviä string rivi = s; // lokaali kopio parametrista, koska erota-funktio ei // hyväksy const-merkkijonoa while ( rivi != "" ) { // jatketaan niin kauan, kun rivi:ssä erotettavaa pala = erota( rivi, erotin ); // erotetaan pala os << setw( tabs.tab( i ) ) << pala << " "; // tulostus os:iin i++; // siirrytään seuraavaan palaan -> indeksi kasvaa } } void cVaihda::tulosta( ostream &os ) const { string rivi; // tiedoston rivi ifstream f( tiedosto.c_str() ); // avataan tiedosto. Huom! ifstreamin // konstruktori haluaa C-merkkijonon if ( !f ) { // tarkistetaan onnistuiko tiedoston avaus cout << "Tiedosto ei aukea!" << endl; return; } os << left; // varmistetaan tasaus vasempaan laitaan (kuten yleensä oletus) while ( getline( f, rivi ) ) { // luetaan tiedostoa kunnes rivit loppuvat tulosta_rivi( os, rivi ); // tulostetaan rivi os << endl; // lisätään vielä rivinvaihto } f.close(); // Suljetaan tiedosto. } int main( void ) { cVaihda vaihda( '|', 3 ); vaihda.tutki( "rivit.txt" ); vaihda.tulosta( cout ); return 0; }