Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: char int:n paikalla

Brebl [11.07.2018 20:07:33]

#

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...

groovyb [11.07.2018 20:12:58]

#

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.

Brebl [11.07.2018 20:34:19]

#

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;
}

Metabolix [11.07.2018 21:49:24]

#

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.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta