Datentyp überprüfen



  • H

    • allo,
      ich beschäftige mich erst seit Kurzem mit C++ und kenne mich daher noch nicht so gut aus. Ich habe Folgendes Problem: ich habe in der main()-Funktion die Variable n mit Datentyp integer definiert. Über die Eingabe wird dann ein Wert für n eingegeben. Mein Ziel wäre es nun, dass das Programm mit return -1 beendet, falls für n ein falscher Datentyp eingegeben wird. Ich habe es daher mit diesem Code versucht:
      if (!cin){
      cout<<"Invalide Eingabe: Bitte starten Sie das Programm neu." ;
      return -1;
      }

      Dieser Code funktioniert einwandfrei, wenn für n ein Buchstabe oder ein anderes Zeichen eingegeben wird, aber bei Eingabe einer Gleitkommazahl, erscheint die Fehlermeldung verzögert, nachdem schon der nächste cout Befehl angezeigt wird.
      Ich habe es auch schon cin.good()||!cin funktioniert, aber hier akzeptiert es keinen Wert mehr für n. Gibt es eine andere Möglichkeit den Datentyp der cin Eingabe zu überprüfen?

    Danke



  • Zeig bitte mal ein kompilierbares kurzes Beispiel.

    Bei der Extraktion eines int aus einem Stream in dem eine Kommazahl steht schlägt die Extraktion nicht fehl weil der ganzzahlige Anteil der Kommazahl den Regeln für einen int entspricht. Erst das Kommazeichen lässt die Extraktion abbrechen. Der Stream geht jedoch nicht in einen Fehlerzustand. Erst beim nächsten Versuch einen int zu extrahieren wird >> auf das Komazeichen stoßen ohne vorher einen gültigen int lesen zu können ~> Stream geht in den Fehlerzustand.

    Du willst aber - wenn ich Dich richtig verstanden habe - einen Fehler melden, wenn außer dem zu extrahierendem Typ noch weitere Zeichen bis zu einem Newline im Stream stehen?



  • Ja, ich möchte eine Fehlermeldung.



  • Sowas?

    #include <limits>
    #include <cctype>
    #include <string>
    #include <iostream>
    
    template<typename T>
    std::istream& read_formatted(std::istream &is, T &value)
    {
    	if (!(is >> value))
    		return is;
    
    	auto ch{ is.peek() };
    	while (ch != EOF && std::isspace(ch) && ch != '\n') {
    		is.get();
    		ch = is.peek();
    	}
    	
    	if (ch == '\n')
    		is.get();
    	else is.setstate(std::ios::failbit);
    
    	return is;
    }
    
    void clear_and_ignore(std::istream &is)
    {
    	is.clear();
    	is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    
    int main()
    {
    	int n;
    	while (std::cout << "Bitte einen Ganzzahl: ",
    	       !read_formatted(std::cin, n))
    	{
    		std::cerr << "Fehler beim Lesen einer Ganzzahl :(\n\n";
    		clear_and_ignore(std::cin);
    	}
    	
    	double d;
    	while (std::cout << "Bitte einen Kommazahl: ",
    	       !read_formatted(std::cin, d))
    	{
    		std::cerr << "Fehler beim Lesen einer Kommazahl :(\n\n";
    		clear_and_ignore(std::cin);
    	}
    
    	std::string str;
    	while (std::cout << "Bitte ein Wort: ",
    	       !read_formatted(std::cin, str))
    	{
    		std::cerr << "Fehler beim Lesen eines Wortes :(\n\n";
    		clear_and_ignore(std::cin);
    	}
    
    	std::cout << "Ihre Eingaben:"
    	             "\n  Ganzzahl   " << n
    	          << "\n  Kommazahl  " << d
    	          << "\n  Wort       " << str << "\n\n";
    }
    


  • Du kannst auch einfach mit getline einen String einlesen und diesen dann mit stoi versuchen umzuwandeln (Achtung: 2. Parameter von stoi beachten!).

    Dann kannst du im Fehlerfall auch leicht den gesamten fehlerhaften String ausgeben und brauchst dich nicht mit den nervigen Streams rumschlagen.


Log in to reply