#include #include #include #include #include using namespace std; const string OLETUS_TIEDOSTO = "yhtalot.txt"; const string KYSY_TIEDOSTO = "Anna asetustiedoston nimi (oletuksena "+OLETUS_TIEDOSTO+"): "; const string KYSY_DERIVOI = "Derivoidaanko? (k/e) "; // tietue piirtoalueen tietojen tallentamista varten struct piirtoalue { char tm; // taustamerkki int leveys, korkeus; int alkux, alkuy; // x ja y akselin alkuarvot vector merkit; }; // tietue termien tallentamista varten struct termi { double kerroin, potenssi; }; int pyorista(double tulos) { if (tulos < 0) return static_cast(tulos-0.5); else return static_cast(tulos+0.5); } // kysyy käyttäjältä käytettävän tiedoston nimen string kysyTiedosto() { string tiedosto = ""; cout << KYSY_TIEDOSTO; getline(cin, tiedosto); if (tiedosto == "") tiedosto = OLETUS_TIEDOSTO; return tiedosto; } // kysyy haluaako käyttäjä derivoida, palauttaa true // arvon jos käyttäjä vastaan k, false jos käyttäjä // vastaa e, muussa tapauksessa kysyy uudestaan bool kysyDerivoi() { string derivointi; for (;;) { cout << KYSY_DERIVOI; getline(cin, derivointi); if (derivointi == "k") return true; else if (derivointi == "e") return false; } } // lue piirtoalueen tiedot tiedostosta piirtoalue luePiirtoalue(ifstream &tsisaan) { // luo uusi piirtoalue tietue piirtoalue piirto; piirto.tm = tsisaan.get(); tsisaan >> piirto.leveys >> piirto.korkeus; // kasvata merkit rakenne vastaamaan alueen kokoa for (int i = 0; i < piirto.korkeus; ++i) piirto.merkit.push_back(string(piirto.leveys, piirto.tm)); piirto.alkux = -(piirto.leveys / 2); piirto.alkuy = piirto.korkeus / 2; // piirrä koordinaatisto akselit for (int i = 0; i < piirto.korkeus; ++i) for (int j = 0; j < piirto.leveys; ++j) { if (piirto.alkux + j == 0 && piirto.alkuy - i == 0) piirto.merkit.at(i).at(j) = '+'; else if (piirto.alkux + j == 0) piirto.merkit.at(i).at(j) = '|'; else if (piirto.alkuy - i == 0) piirto.merkit.at(i).at(j) = '-'; } return piirto; } // derivoi merkkien määrittämä yhtälö ja kirjoita se tderivaatat virtaan. // oletus, että vakiotermi on viimeisenä. void derivoi(vector &termit, const string &merkit, ofstream &tderivaatat) { for (int i = 0; i < termit.size(); ++i) { // jos termin potenssi on 0 on kyseessä vakiotermi ja se poistetaan if (static_cast(termit.at(i).potenssi) == 0) { termit.erase(termit.begin()+i); break; } // laske termien uusi arvo termit.at(i).kerroin = termit.at(i).kerroin * termit.at(i).potenssi; termit.at(i).potenssi = termit.at(i).potenssi - 1; } // kirjoita käytettävät merkit ja termien uusi lukumäärä tderivaatat << merkit << " " << termit.size(); for (int i = 0; i < termit.size(); ++i) tderivaatat << " " << termit.at(i).kerroin << " " << termit.at(i).potenssi; tderivaatat << endl; } // piirrä termien määrittelemä yhtälö käyttäen merkit merkkijonon merkkejä void piirra(piirtoalue &piirto, const vector &termit, const string &merkit) { // monesMerkki on indeksi merkit merkkijonoon, jota käytetään pitämään kirjaa kulloinkin tulostettavasta merkistä. unsigned int monesMerkki = 0; for (int x = piirto.alkux; x < piirto.alkux + piirto.leveys; ++x) { double tulos = 0; for (int i = 0; i < termit.size(); ++i) tulos += termit.at(i).kerroin * pow(x, termit.at(i).potenssi); int y = piirto.alkuy - pyorista(tulos); if (y >= 0 && y < piirto.korkeus) piirto.merkit.at(y).at(x - piirto.alkux) = merkit[monesMerkki]; if (++monesMerkki == merkit.length()) monesMerkki = 0; } } void tulosta(piirtoalue &piirto) { // rivi ja sarake piirtävät x- ja y-akselin numerot. Haluttu numero saa- // daan jakamalla oikea arvo kymmenellä ja ottamalla siitä jakojäännös. cout << endl; for (int i = 0; i < piirto.korkeus; ++i) { int rivi = piirto.alkuy - i; if ( rivi < 0 ) rivi = -rivi % 10; else rivi = rivi % 10; // tulosta nykyinen rivi cout << rivi << piirto.merkit.at(i) << endl; } cout << " "; for (int i = 0; i < piirto.leveys; ++i) { int sarake = piirto.alkux + i; if (sarake < 0) sarake = -sarake % 10; else sarake = sarake % 10; cout << sarake; } cout << endl; } int main() { cout << "### OHJ-1101 Ohjelmointi Ie - Harjoitustyö - kako" << endl; cout << "### Henri Lipsanen, lipsaneh" << endl; cout << "### 199051, Tietojohtaminen" << endl; // kysy käyttäjältä käytettävä tiedosto ja avaa se tsisaan virtana // tai tulosta virhe ja poistu ohjelmasta jos tiedostoa ei voitu avata. string tiedosto = kysyTiedosto(); ifstream tsisaan(tiedosto.c_str()); if ( !tsisaan ) { cout << "Virhe: Tiedostoa " << tiedosto << " ei voida lukea." << endl; return EXIT_FAILURE; } // kysy haluaako käyttäjä derivoida. bool derivointi = kysyDerivoi(); // luo uusi piirtoalue tiedostossa olevien tietojen mukaan. piirtoalue piirto = luePiirtoalue(tsisaan); ofstream tderivaatat; if (derivointi) { tderivaatat.open((tiedosto + ".derivaatat").c_str()); tderivaatat << piirto.tm << " " << piirto.leveys << " " << piirto.korkeus << endl; } // jatka niin kauan kuin tiedostosta pystyy lukemaan while (tsisaan) { string merkit; tsisaan >> merkit; if (!tsisaan) break; vector termit; int termeja, i = 0; tsisaan >> termeja; // lue tarvittavat termit tiedostosta for (i = 0; i < termeja; ++i) { termi tmp; tsisaan >> tmp.kerroin >> tmp.potenssi; termit.push_back(tmp); } if (derivointi) derivoi(termit, merkit, tderivaatat); piirra(piirto, termit, merkit); } tulosta(piirto); return EXIT_SUCCESS; }