# Eingabefehler abfangen (Buchstaben)



## Pixtar (20. September 2006)

Moin Leutz,

sollen für die Schule mal wieder was über stumpfsinniger proggen, naja das Programm steht soweit - möchte es nur Idiotensicher gestalten, dafür fehlt mir eine bestimmte Funktion:

"Wie kann ich eine Eingabe (cin >> a <- definiert durch double, nicht int) so gestallten, das wirklich nur Zahlen eingegeben werden?"

Ich habe es schon nachlesen können, das man dafür isalpha() nehmen soll, Problem bei der Sache ist aber, das isalpha() nur mit int-Definitionen arbeitet und nicht mit double ...


```
#include <iostream.h>
#include <ctype.h>

int main()
{
	//Variablendeklaration
	long double A=0;
	long double PI=3.1415926535897932384626433832795028841972;

	//Programmeinführung
	cout << "\t\t\tKreisflaechenberechnung\n";
	cout << "\t\t\t Alle Angaben in 'cm' \n\n";

	//Wiedereinstieg nach Eingabefehler
Fehler:

	//Frage nach der einer Kreisvariablen
	cout << "Welchen Radius besitzt der Kreis?\n";

	//Eingabe der Kreisvariablen
	cout << ">> ";
	double radius = 0;
	cin >> radius;

	//Eingabefehler abfangen
	if ( radius==0 || radius<0)
	{
		cout << "\nBitte nur Zahlen (positive) verwenden bzw. keine Null!\n\n";
		goto Fehler;
	}
	else
	{
		cout << "";
	}

	//Berechnung
	A=2*radius*PI;

	//Ausgabe
	cout << "\nDie Kreisinnenflaeche betraegt:\n";
	cout << ">> " << A << " cm" << "\n\n\n\n\n\n\n\n\n\n";

	return 0;

}
```

Wie ihr vielleicht seht, hab ich nur einen Abfang für negative Zahlen, sowie Null hinbekommen ... ne Idee?

Mfg Pixtar ;-]


----------



## deepthroat (20. September 2006)

Hi.

Das Ganze ist einfacher als du denkst. 
	
	
	



```
if (cin >> radius && radius > 0) {
  // Eingabe OK
  ...
} else {
  // Eingabe war kein double oder es trat EOF auf, oder der eingelesene Wert war nicht größer 0.
  cerr << "Sie müssen eine gültige positive rationale Zahl eingeben!" << endl;
  cin.clear ();
}
```
Zur Erklärung: Du solltest *immer* gleich beim Einlesen überprüfen ob das Einlesen erfolgreich war. Dazu ist es meist günstig das Einlesen selbst gleich in einer Bedingung zu machen. 

So wie du es vorher gemacht hast, ist es problematisch weil du da nicht kontrollierst ob überhaupt etwas eingelesen wurde oder nicht - und somit rechnest du einfach mit einem alten Wert von radius weiter.

Gruß


----------



## Pixtar (20. September 2006)

Das mit der "leeren" Eingabe ist ja klaro, das hatte ich nun garnicht bedacht, auch das die Variable nach einer falschen Eingabe wieder geleert wird ( cin.clear () ) 
ABER
was beinhaltet dieser Teil des Quellcodes

if (cin >> radius && radius > 0)

 das Buchstaben, negative Zahlen und eine leere Eingabe ausgeschlossen werden bzw. als falsch gewertet werden

Mfg Pixtar

PS: Das "cerr" wird dann wahrschnlich mit dem "cin" gekoppelt sein, das wenn ein Fehler auftritt, der Text ausgegeben wird, right?


----------



## GeHo (21. September 2006)

Man kann auch (vielleicht übersichtlicher) schreiben:
	
	
	



```
cin >> radius;
if (cin.fail() == false) {
  /* Zahl richtig eingelesen*/
}
```
oder verkürzt:
	
	
	



```
cin >> radius;
if (!cin.fail()) {
  /* Zahl richtig eingelesen*/
}
```
oder noch mehr verkürzt:
	
	
	



```
if (cin >> radius) {
  /* Zahl richtig eingelesen*/
}
```



> PS: Das "cerr" wird dann wahrschnlich mit dem "cin" gekoppelt sein, das wenn ein Fehler auftritt, der Text ausgegeben wird, right?


Nee, 'cerr' hat nichts direkt mit 'cin' zu tun. 'cerr' kannst du wie 'cout' überall im Quelcode verwenden. Wie der Name schon sagt, ist 'cerr' für die Fehlerausgabe gedacht. Der Vorteil von 'cerr' gegenüber zu 'cout' ist, dass die Ausgabe ungepuffert ist und dass die Ausgabe immer auf den Bildschirm erscheint, auch wenn der stdout umgeleitet wurde (also sowas wie test.exe > ausgabe.txt im shell).


----------



## deepthroat (21. September 2006)

Pixtar hat gesagt.:
			
		

> Das mit der "leeren" Eingabe ist ja klaro, das hatte ich nun garnicht bedacht, auch das die Variable nach einer falschen Eingabe wieder geleert wird ( cin.clear () )


Das cin.clear() bedeutet nur, das der Streamzustand wieder zurückgesetzt wird , wobei es eine gute Idee wäre, das nur zu tun wenn cin noch nicht am EOF ist und danach von der Eingabe eine komplette Zeile zu lesen (um den Eingabepuffer zu leeren). 

Wenn der Stream cin in einem Fehlerzustand ist (egal warum), dann kann von dem Stream nichts mehr gelesen werden. Daher muß man den Zustand wieder zurücksetzen damit man vom Benutzer nochmal etwas abfragen kann. Allerdings wenn die Eingabe fehlgeschlagen ist, dann wurden auch keine Zeichen aus dem Eingabepuffer des Streams entfernt, d.h. was immer der Benutzer eingegeben hat ist immer noch da und wird beim nächsten Einlesen wiederverwendet.


			
				Pixtar hat gesagt.:
			
		

> ABER
> was beinhaltet dieser Teil des Quellcodes
> 
> if (cin >> radius && radius > 0)
> ...


Ja. Wenn radius ein double ist, dann schlägt die Eingabe fehl, sobald der eingegebene Wert kein korrekter double-Wert ist. Sollte die Eingabe klappen wird dann auch noch überprüft ob radius > 0 ist.

Gruß


----------

