Mikäs on kätevin konsti estää kirjainten syöttäminen kun kysytään lukua?
#include <iostream> int main() { int luku = 0; while (luku < 10) { std::cout << "Anna luku "; std::cin >> luku; } return 0; }
Tulee ikuinen silmukka kun laittaa kirjaimen...
tarkistamalla ylipäätään onko kyseessä luku. tuo ei toimi muutenkaan, koska otat konsolisyötteestä merkkijonon muuttujaan joka on alustettu kokonaisluvuksi. konvertoi syöte ensi kokonaisluvuksi luku -muuttujaan, jos tämä epäonnistuu, tulosta validointivirhe ja pyydä luku uudestaan. jos muunto onnistuu, jatka.
Jaa että näinkö?
#include <iostream> #include <cstdlib> #include <cctype> int main() { int luku = 0; char merkki[5]; while (luku < 10) { std::cout << "Anna luku "; std::cin >> merkki; if (isalpha(merkki[0])) std::cout << "Anna luku!\a\n"; luku = atoi(merkki); } return 0; }
Kun yritetään lukea tekstiä lukumuuttujaan, virta (cin) menee virhetilaan ja mikään lukeminen ei enää onnistu ennen virheen käsittelyä.
Pitää tarkastaa, onnistuiko lukeminen, ja tarvittaessa ohittaa viallinen rivi.
#include <iostream> #include <limits> int main() { int luku = 0; while (luku < 10) { while (true) { std::cout << "Anna luku: "; // Jos ei tule virhettä, lopetetaan silmukka. if (std::cin >> luku) { break; } // Poistetaan virhemerkintä. std::cin.clear(); // Ohitetaan rivi. std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Ilmoitetaan virheestä ja toistetaan silmukkaa. std::cout << "Syöte ei kelpaa!\n"; } // Luku on luettu, tarkastetaan se. if (luku < 10) { std::cout << "Luku on liian pieni!" << std::endl; } } }
Jos tekstin alussa on luku ja sitten muita merkkejä, luvun lukeminen onnistuu ja merkit jäävät seuraavalle lukukerralle.
Toinen vaihtoehto on lukea rivi tekstinä ja koettaa muuttaa luvuksi.
#include <iostream> #include <string> #include <stdexcept> int main() { int luku = 0; while (luku < 10) { while (true) { std::string teksti; std::cout << "Anna luku: "; // Luetaan rivi. std::getline(std::cin, teksti); // Yritetään muuttaa luvuksi, käsitellään virheet. try { luku = std::stoi(teksti); break; } catch (std::invalid_argument& e) { std::cout << "Syöttämäsi teksti \"" << teksti << "\" ei ole luku." << std::endl; } catch (std::out_of_range& e) { std::cout << "Syöttämäsi luku " << teksti << " on liian suuri." << std::endl; } } // Luku on luettu, tarkastetaan se. if (luku < 10) { std::cout << "Luku on liian pieni!" << std::endl; } } }
Tämä toimii hyvin, mutta nyt myös "7 kääpiötä" muuttuu luvuksi 7. Tähän voi tarvittaessa lisätä tarkastuksen, onko tekstissä muuta kuin numeroita.
if (teksti.find_first_not_of("0123456789") != std::string::npos) { // tekstissä on muuta kuin numeroita. }
Koodia voisi kehittää vielä niin, että syötteen lopettaminen (Linuxissa Ctrl+D, Windowsissa Ctrl+Z) myös käsiteltäisiin ilman ohjelman jumiutumista.
Aihe on jo aika vanha, joten et voi enää vastata siihen.