Zahleneingabe prüfen auf Komma



  • Hallo zusammen,
    ich möchte gerne überprüfen, ob die Zahleneingabe ein Komma bzw. Punkt enthält oder nicht. Falls möglich ohne besondere Funktion sondern raw.
    Die Eingabe wird in einer int Variable gespeichert. Ich weiß, dass int die Zahlen nach dem Komma "ignoriert", aber die Kommazahl wird trotzdem akzeptiert was ich nicht möchte. Prüfung mit !std::cin etc. lässt das Komma bzw. Punkt auch zu.

    #include<iostream>;
    
    int main() {
    
    	int eingabe = 0;
    	bool kontrolle = true;
    
    	do {
    		std::cout << "Bitte geben Sie die Stunde der aktuellen Uhrzeit ein: ? ";
    		std::cin >> eingabe;
    
    		if (eingabe < 0 || eingabe > 23 || !std::cin) {
    			std::cout << "Keine erlaubte Stundenangabe." << std::endl;
    			std::cin.clear();
    			std::cin.ignore();
    			kontrolle = false;
    		}
    		else {
    			kontrolle = true;
    		}
    	} while (!kontrolle);
    
    	std::cout << eingabe + eingabe << std::endl;
    
    	system("pause");
    	return 0;
    }
    


  • Das Problem ist, dass der Operator >> soweit einliest, wie gültige Zeichen im Stream kommen. Bei 12,34 ist 1 und 2 gültig, das Komma dann nicht. Daher stoppt das Einlesen dort - der Stream ist aber weiterhin gültig und bereit, das nächste Objekt einzulesen. Du kannst nun mit stream.peek() schauen, welches Zeichen folgt. Folgt ein Zeilenumbruch, hast du die gesamte Zeile umgewandelt.

    Ich finde es immer sehr praktisch, das schnell interaktiv mit cling bzw. root zu testen:

    root [0] int i;
    root [1] cin >> i;
    12,34
    root [2] cin.peek()
    (int) 44
    root [3] (char)cin.peek()
    (char) ','  <--- wie man sieht, ist das nächste Zeichen ein Komma
    root [4] string s;
    root [5] cin >> s;  <-- passiert ohne Benutzerinteraktion, da noch im Stream drin
    root [6] s
    (std::string &) ",34"
    root [7] cin >> i;   <-- nochmal einen int lesen, dieses mal geben wir 12 ein
    12
    root [8] (char)cin.peek()
    (char) '\n' <--- Zeichen ist jetzt der Zeilenumbruch
    

    Ich lese gerne in einen std::string ein und versuche diesen dann mit stoi oder ähnlich umzuwandeln. Macht es einfacher, dann auch eine gute Fehlermeldung zu geben wie "<12,34> ist kein gülter Ganzzahlwert". Andererseits ist der schönere Weg aber, direkt aus dem Stream zu lesen.

    Zum Code: je drei (3) Backticks vor und hinter dem Code einfügen. Backtick ist shift+die Taste zwischen ß und Backspace (und ggf. musst du danach <space> drücken, damit das Zeichen erscheint).



  • Diese Methode kommt mir als C++ Anfänger ziemlich kompliziert vor...
    Gibt es vielleicht eine einfachere Lösungsmöglichkeit z.B mit If-Statements ? 🙂

    Und danke für die Hilfe mit den Backticks 🙂


  • Mod

    Die Frage ist quasi identisch zu deiner anderen Frage neulich. Die Antwort ähnelt daher sehr der Antwort dort. Ich rate dir als Neuling dringend, nicht zu viel Zeit mit dieser ganzen Sache zu verschwenden. Dazu eine Erklärung, warum dieses Problem so eklig ist und wieso das verschwendete Mühe ist:

    Es gibt bei der Benutzereingabe zwei Ebenen:

    1. Der Teil, der direkt mit dem Benutzer spricht. Der fragt die Tastatur ab, zeigt eventuell etwas auf dem Bildschirm an, und ähnliches. Dies ist das Nutzerinterface, zu englisch user interface, oder UI. Da die meisten davon grafisch sind, oft auch GUI genannt. Bei deinen einfachen Testprogrammen hast du wahrscheinlich eine primitive Textkonsole als UI. Diese Textkonsole ist aber nicht dein Programm! Diese UI ist das, worin dein Programm läuft, also das Terminalprogramm selber, das mit deiner Entwicklungsumgebung oder mit deinem Betriebssystem gekommen ist.
    2. Den Teil, der die Eingaben logisch verarbeitet. Also der Teil, der eine Zeichenfolge wie "-5.245" ansieht, und dann entscheidet, dass dies ein double-Wert -5.245 sein soll. Das sind die C++-Streams in deinem Programm, hier cin.

    Jetzt versuchst du eine Eingabeschnittstelle zu bauen, mit den Mitteln, die eigentlich der logischen Interpretation einer bereits erfolgten Eingabe dienen. Das geht mit viel Mühe auch, aber das Ergebnis ist schlecht, und insgesamt ist es eher viel Gehacke, anstatt dass du gutes Programmieren lernst. Weil halt das falsche Mittel für den Zweck eingesetzt wird. Das Einschränken der möglichen Eingaben auf gewisse Zeichen wäre nämlich korrekterweise in dem Teil des Programms aufgehoben, der direkt mit dem Nutzer kommuniziert. Der könnte beispielsweise alle Tastatureingaben verwerfen, die nicht zu dem erwarteten logischen Format passen. Wenn die Eingaben logisch interpretiert werden, ist es dafür nämlich eigentlich schon zu spät, weil erwartet wird, dass die Eingabe korrekt war, bevor sie interpretiert wird.

    Die Textkonsole bietet dir als Anfänger, die schöne Möglichkeit, dass du dich gar nicht um die Details der direkten Kommunikation mit dem Nutzer kümmern musst, weil das externe Terminalprogramm für dich erledigt. Der Nachteil ist, dass du aber entsprechend wenig Kontrolle hast. Später, wenn du mehr Übung hast, und du solche Kontrolle haben willst, dann wirst du die UI auch direkter in dein Programm einbinden. Oft dann auch nicht mehr als Textterminal, sondern als GUI. Dann hast du die Kontrolle, die du dir hier wünscht. Vorerst würde ich an deiner Stelle einfach vom Anwender deiner Programme erwarten (der ja wahrscheinlich nur du selbst bist), dass er dein Programm auch korrekt bedient. Und wen nicht, dann ist er halt selber Schuld, wenn das Programm nicht funktioniert. Jedenfalls wirst du bei den Versuchen, solche Sachen wie von @wob gezeigt nachzumachen, sehr wenig nützliches lernen. Das sind weder nützliche Algorithmen, noch lernst du irgendetwas tiefgründiges über C++. Aber es verschwendet viel Zeit und Mühe, in der du nützlicheres hättest lernen können.



  • @seppj da hast du wahrscheinlich recht. Das werde ich mir zu Herzen nehmen, danke. 🙂


Log in to reply