// OHJ-1151 Palautus 1 2/2008 // Komentotulkki #include #include #include #include #include #include //------------ // Tietotyypit enum Toiminto {VIRHE, SIIRTO, TULOSTUS, LOPETUS}; struct Komentosana { std::string komento; Toiminto toiminto; int x_muutos; // Vain siirroille int y_muutos; }; // Eri komennot ja niiden toiminnot const Komentosana KOMENNOT[] = { {"POHJOISEEN", SIIRTO, 0, 1}, {"ETELAAN", SIIRTO, 0, -1}, {"ITAAN", SIIRTO, 1, 0}, {"LANTEEN", SIIRTO, -1, 0}, {"KOILLISEEN", SIIRTO, 1, 1}, {"KAAKKOON", SIIRTO, 1, -1}, {"LOUNAASEEN", SIIRTO, -1, -1}, {"LUOTEESEEN", SIIRTO, -1, 1}, {"ETEEN", SIIRTO, 0, 1}, {"TAAKSE", SIIRTO, 0, -1}, {"VASEMMALLE", SIIRTO, -1, 0}, {"OIKEALLE", SIIRTO, 1, 0}, {"SUORAAN", SIIRTO, 0, 1}, {"PERUUTA", SIIRTO, 0, -1}, {"YLOS", SIIRTO, 0, 1}, {"ALAS", SIIRTO, 0, -1}, {"TULOSTA", TULOSTUS, 0, 0}, {"LOPETA", LOPETUS, 0, 0}, {"QUIT", LOPETUS, 0, 0}, {"POIS", LOPETUS, 0, 0}, {"EXIT", LOPETUS, 0, 0}, {"SOMMORO", LOPETUS, 0, 0} }; // Komentotaulukon koko const int KOMENNOT_SIZE = sizeof(KOMENNOT) / sizeof(Komentosana); struct Koordinaatit { int x; int y; }; //--------- // Funktiot // Vertaa komentoa, pienistä ja isoista kirjaimista välittämättä. // True, jos annettu on kokonaisen alku. bool vertaa_komento(std::string annettu, std::string kokonainen) { unsigned int kohta = 0; if (annettu.size() > kokonainen.size()) { // Annettu kokonaista pidempi => ei vastaa return false; } for (kohta = 0; kohta < annettu.size(); kohta++) { if (std::tolower(annettu.at(kohta)) != std::tolower(kokonainen.at(kohta))) { // Eroavaisuus return false; } } // Ei löytynyt eroja return true; } // Etsii annettua komentoa vastaavan toiminnon. // Osittaiset komennot käyvät, kunhan vastaavuuksia ei ole useita. Komentosana tulkitse_komento(std::string annettu) { Komentosana tulos = {"", VIRHE, 0, 0}; int sopivia = 0; int i = 0; for (i = 0; i < KOMENNOT_SIZE; i++) { if (vertaa_komento(annettu, KOMENNOT[i].komento)) { sopivia += 1; tulos = KOMENNOT[i]; } } if (sopivia == 1) { return tulos; } else { // Ei vastaavuuksia tai useita vastaavuuksia tulos.toiminto = VIRHE; return tulos; } } // Tulostaa koordinaatit näytölle void tulosta_koordinaatit(const Koordinaatit &koordinaatit) { std::cout << "Koordinaatit: " << koordinaatit.x; std::cout << ", " << koordinaatit.y << std::endl; } // Toteuttaa rivin tai tulostaa virheen. // Palauttaa false jos käyttäjä tahtoo lopettaa. bool toteuta_rivi(std::string rivi, Koordinaatit &koordinaatit) { std::istringstream virta(rivi); std::string komento; std::string parametrit; // Yritetään lukea virrasta komento ja ensimmäinen parametri. // Jos ei mitään luettavaa, arvot jäävät tyhjiksi. virta >> komento >> parametrit; if (komento == "") { // Tyhjä komento -> uusi kehote return true; } // Haetaan komentoa vastaavat tiedot vakiotaulukosta Komentosana tulos = tulkitse_komento(komento); if (tulos.toiminto == VIRHE) { std::cout << "Virheellinen komento!" << std::endl; return true; } // Tutkitaan vasta nyt -> ilmoitetaan virheellisestä komennosta // jos olemattomalle komennolle annetaan parametreja. if (parametrit != "") { std::cout << "Virheelliset parametrit!" << std::endl; return true; } switch (tulos.toiminto) { case SIIRTO: koordinaatit.x += tulos.x_muutos; koordinaatit.y += tulos.y_muutos; tulosta_koordinaatit(koordinaatit); break; case TULOSTUS: tulosta_koordinaatit(koordinaatit); break; case LOPETUS: // False -> pääohjelma lopettaa return false; break; default: // Virheet on jo käsitelty -> ei pitäisi päätyä tänne std::cout << "Sisainen virhe!" << std::endl; break; } return true; } // Pääohjelma lukee loopissa rivejä käyttäjältä ja toteuttaa niitä. int main() { std::cout << "### OHJ-1151 Ohjelmointi IIe" << std::endl; std::cout << "### Petteri Aimonen, 205441, aimonen" << std::endl; Koordinaatit koordinaatit = {0, 0}; tulosta_koordinaatit(koordinaatit); std::string rivi; while (std::cin.good()) { // Luetaan rivi käyttäjältä std::cout << "> "; std::getline(std::cin, rivi); // Yritetään toteuttaa if (!toteuta_rivi(rivi, koordinaatit)) { // Lopetus break; } } return EXIT_SUCCESS; }