Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Ääkköstä syöttäessä ohjelma kaatuu

punppis [06.07.2008 03:34:28]

#

Olen tässä nyt C++-ohjelmointia harjoitellu ja lukenut kaikenmaailman oppaita alusta alkaen, joten tein erittäin alkeellisen harjoituksen ihan muistin virkistämiseksi. Ohjelma ei näytäkään olevan niin alkeellinen (ainakaan minulle), koska se ei toimi oikein.

Ohjelma on siis tämä legendaarinen "Arvaa luku väliltä 1-10". Ohjelma toimii siis muuten moitteetta, mutta kun syötän ääkkösen (ä tai ö), niin ohjelma kaatuu. Erikoismerkit ei kyllä kaada ohjelmaa. Huomasin vielä, että myös esim. ctrl-c -yhdistelmän painaminen kaataa ohjelman (debugging-tilassa tulee virheilmoitus, ilman debuggingia ohjelma vain sammuu).

#include <iostream>		// Tulostus ja kirjoitus
#include <string>		// Merkkijonot
#include <stdlib.h>		// Satunnaislukuja varten
#include <time.h>		// Satunnaislukuja varten
#include <sstream>		// Tyyppimuunnoksia varten

using namespace std;

// Funktio satunnaisen luvun saamiseen tiettyjen lukujen välistä.
int random(int min, int max) {
	int tulos;
	for(int x=0; x<(rand() % (200 - 100) + 100); x++) {
		tulos = rand() % (max - min) + min;
	}
	return tulos;
}

bool onkoNumero(string nro) {
	// Jos syöte on enemmän kuin yhden merkin pituinen, niin tarkistetaan onko se negatiivinen.
	if(nro.length() > 1) {
		if(!isdigit(nro[0]) && nro[0] != '-') return false;
		for(unsigned int x=1; x < nro.length(); x++) {
			if(!isdigit(nro[x])) return false;
		}
		return true;
	}
	// Jos vain yhden merkin, niin miinusmerkkiä ei sallita.
	else if(nro.length() == 1 && isdigit(nro[0])) {
		return true;
	}
	// Tyhjä syöte ei kelpaa.
	else return false;
}

int main() {
	srand(time(0));
	int oikeaLuku = random(1, 10);
	int arvattuLuku;
	string syote;
	cout << "Arvaa oikea luku valilta 1-10:" << endl;
	// Loopataan kunnes arvaus on oikein.
	do {
		// Loopataan kunnes syötetään numeroita.
		do {
			cout << "Syota luku: ";
			cin >> syote;
			if(!onkoNumero(syote)) cout << "Syotteen pitaa olla luku (numero)!" << endl;
		}
		while(!onkoNumero(syote));

		// Muunnetaan stringistä intiksi.
		istringstream muunnos(syote);
		muunnos >> arvattuLuku;

		if(arvattuLuku == oikeaLuku) cout << "Oikein!";
		else if(arvattuLuku < 1 || arvattuLuku > 10) cout << "Luvun pitaa olla valilta 1-10!" << endl;
		else cout << "Vaarin, yrita uudestaan: " << endl;
	}
	while(arvattuLuku != oikeaLuku);

	// Ettei ohjelma vaan katoa, kun arvattu oikein.
	cout << endl;
	system("pause");
	return EXIT_SUCCESS;
}

Missä siis vika piilee? Kääntäjä on Microsoft Visual C++ 2008 Express Edition.

Koodista mielellään voi muutenkin kommentoida, jos ei ole taiteen sääntöjen mukaisesti jotain asiaa toteutettu.

Kuva virheilmoituksesta

FooBat [06.07.2008 07:08:47]

#

isdigit haluaa parametrinsa välillä 0-255 tai se heittää volttia. Stringin nro[0] kutsu puolestaan palauttaa -108 'ö':lle ja -124 'ä':lle. Joku fiksumpi saa kertoa minkä takia noi palautetaan signed tyyppisenä ja minkä takia isdigit haluaa arvot unsgined tyyppisenä.

Virheen saa pois castaamalla nro[0] (unsigned char) tyyppiseksi tai vaikka and:illa 0xff:n kanssa.

TsaTsaTsaa [06.07.2008 11:08:08]

#

Ctrl-c -yhdistelmän kuuluukin kaataa ohjelma.

Pekka Karjalainen [06.07.2008 11:50:49]

#

Tässä on ohjelma, joka vaatii kolme ctrl-c:n napautusta lopetukseen. Joku Unixin ja C:n paremmin tunteva saa korjata, jos olen rikkonut standardeja vastaan.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

static volatile sig_atomic_t naputettu = 0;

void ctrl_c (int sig) {
	++naputettu;
	signal (sig, ctrl_c);
}

int main (void) {
	short int i=0;
	signal (SIGINT, ctrl_c);
	while (naputettu < 3) {
		++i;
		if (i==0) putchar ('#');
	}
	printf ("\nOk, nyt riitti!");
	/* system ("pause");  /* windows-sakin riemuksi ja iloksi */
	return 0;
}

Tästä voisi tehdä koodivinkin, mutta en nyt uskalla luvata, osaanko tehdä oikeaoppisen. Näitä signaaleja ei tunnetusti ole pidetty aivan C-kielen helpoiten siirtyvänä ominaisuutena, joten Windows-maailmassa voi tapahtua kummia. Ainahan siellä :D

punppis [06.07.2008 17:37:09]

#

Kiitos vaan, tuolla unsigned charrilla sain toimimaan.

Vastaus

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

Tietoa sivustosta