Stromeingabe überprüfen.



  • Hallo zusammen,
    ich versuche eine Methode zu entwickeln, welches überprüft, ob die Eingabe korrekt ist. Also keine Buchstaben bei Zahlen oder so.

    Gedacht habe ich mir sowas wie:

    if(!cin{
       //Fehler
    }
    

    Das hat immer funktioniert, wenn bei unsigned int eine negative Zahl eingegeben wurde, oder ein Buchstabe oder umgekehrt. War ganz zuverlässig.
    Aber da ich es an vielen Stellen brauche, wollte ich das in eine Methode verpacken:

    checkInput(std::istream in){
    
     if(!cin{
       //Fehler
     }
    }
    

    "istream" macht komischeweise keinen Unterschied mehr zwischen unsigned und signed typen.
    Dann möchte ich auch prüfen, ob irgendwelche zahlen vorkommen mit std::isdigit
    dafür schreibe (auch in dieser Methode)

    string wert;
    stringstream ss;
    ss << in;
    ss >> wert;
    isDigit(wert[0)
    

    Aber der stringstream erhält von dem istream auch irgendein blödsinn.
    Hat da jemand einen guten Ansatz wo ich einfach beim Aufruf schreiben kann sowas wie :

    cin >> eingabe;
    checkInput(cin);
    

    Danke für jeden Tipp.



  • Korrigiere mal Deine Tippfehler. Sonst wird es schwierig vernünftig zu antworten.



  • Tambler schrieb:

    Das hat immer funktioniert, wenn bei unsigned int eine negative Zahl eingegeben wurde, oder ein Buchstabe oder umgekehrt. War ganz zuverlässig.

    Glaub ich nicht.

    Tambler schrieb:

    Aber da ich es an vielen Stellen brauche, wollte ich das in eine Methode verpacken:

    unsigned read_unsigend(std::istream& in=std::cin) {
      long long n;
      if (!(in >> n) || n<0 || n>std::numeric_limits<unsigned>::max())
        // Fehler
      return n;
    }
    


  • Tambler schrieb:

    Hallo zusammen,
    ich versuche eine Methode zu entwickeln, welches überprüft, ob die Eingabe korrekt ist. Also keine Buchstaben bei Zahlen oder so.

    Gedacht habe ich mir sowas wie:

    if(!cin{
       //Fehler
    }
    

    Das hat immer funktioniert, wenn bei unsigned int eine negative Zahl eingegeben wurde, oder ein Buchstabe oder umgekehrt.

    Aus der Sicht des Streams sind negative Zahlen keine Fehler, deine if funktiniert also nicht. unsigend Unter- und Überläufe sind wohldefiniert. Bei signed Unter- und Überläufe kommt hoffentlich einfach nur Schrott raus, weil sie nicht wohldefiniert sind.

    Wenn du allerdings einen Buchstaben in den Stream stopfst anstatt eine Zahl (wenn ein int erwartet wird), sollte deine if korrekt funktionieren.

    Wenn ein Buchstabe erwartet wird und du dem Stream eine Zahl gibst, funktioniert deine if nicht, weil du eigentlich keine Zahl (z.B. 9) eigegeben hast, sondern ein char ('9').

    Tambler schrieb:

    checkInput(std::istream in){ // call-by-reference nicht vergessen, du willst ja den originalen Stream.
    
     if(!cin{
       //Fehler
     }
    }
    

    Es gibt ja verschiedene Möglichkeiten, wieso es zu einem Fehler kam. Wenn du das in eine Funktion auslagerst, würdest du ja alle Fehler gleich behandeln. Außerdem erwarte ich bei einer "check" Funktion einen Rückgabewert... Diesen müsstest du dann in der aufrufenden Funktion logischerweise testen, hast also wieder eine if. Was hast du durch die Funktion dann gewonnen?

    Tambler schrieb:

    Dann möchte ich auch prüfen, ob irgendwelche zahlen vorkommen mit std::isdigit
    dafür schreibe (auch in dieser Methode)

    string wert;
    stringstream ss;
    ss << in;
    ss >> wert;
    isDigit(wert[0)
    

    Aber der stringstream erhält von dem istream auch irgendein blödsinn.
    Hat da jemand einen guten Ansatz wo ich einfach beim Aufruf schreiben kann sowas wie :

    cin >> eingabe;
    checkInput(cin);
    

    Wenn du den Inhalt eines Stream kopieren willst, nimmst du istream::rdbuf(). ➡ oss << in.rdbuf(). ➡ Außerdem nimmst du ostringstream und nicht stringstream.



  • Vielen Dank.
    Habe noch mal das ganze getestet und das deckt sich mit euren Aussagen.

    Der Code:

    unsigned read_unsigend(std::istream& in=std::cin) { 
      long long n; 
      if (!(in >> n) || n<0 || n>std::numeric_limits<unsigned>::max()) 
        // Fehler 
      return n; 
    }
    

    Behebt mein Problem nicht.
    Ich gebe bereits von Außen einen Wert ein.
    Bei der ersten Bedienung in der if muss ich aber erneut was eingeben....
    Was sich kein Problem ist, man könnte das ja auch rausnehmen.

    Das Problem ist, ich kriege aus dem Arguement "in" keinen vernünftigen Wert heraus, welches ich dann checken kann. Stringstream, oder std::getline funktionieren nicht



  • Du willst also eine Funktion, die überprüft, ob eine beliebige Input Operation erfolgreich war (also einen brauchbaren Wert liefert)? Vielleicht können die Templatekünstler da was basteln ...



  • ja ich habe mir eben noch ne template-funktion gebastelt:

    bool checkType(T obj, string condition) {
    
        bool check(false);
        if (typeid (obj).name() == condition) {
            check = true;
        }
    
        check;
    }
    

    Aber irgendwie sehe ich bis jetzt keinen Sinn darin, denn wenn ich sie aufrufe:

    int name;
    cin >> name
    checkType(name, "int");
    

    Schauet er sich dann den type an, welche dann ein int ist und sagt: "ja es ist int" aber dass im Inhalt Buchstaben vorkommen, bleibt dabei ungeprüft...



  • Natürlich, dein Code ist Schwachsinn. Er prüft ob der Typ von int int ist*.
    Was genau spricht gegen:

    int i;
    in >> i;
    if (!in) // Buchstabe wurde eingegeben
     ups();
    

    *Technisch gesehen nur, ob das implementation-defined Ergebnis von std::type_info::name() gleich einem String ist. Das ist sowas von nicht portabel. Und da fehlt ein return in der Funktion.



  • Tambler schrieb:

    Aber irgendwie sehe ich bis jetzt keinen Sinn

    Macht auch überhaupt keinen Sinn, was du gemacht hast.



  • Das Probem ist, dass das Argument std::istream, den ich in meiner Methode verwende.
    Die Vorgehensweise:

    std::istream in;
    if(!in)
    {
    
    }
    

    funktioniert nicht in allen Fällen.
    Deswegen benötige ich den exakten Wert vom "std::istream" um ihn auf weitere Fehler zu prüfen.
    Seltsameweise kann ich weder mit stringsteam oder mit std::getline keinen brauchbaren Werten aus dem Argument std::istream herauslesen.
    Das ist das Problem 🙂


  • Mod

    Wenn du eigene, ganz spezielle Anforderungen an die Extraktionsfunktionen hast, dann schreib eine eigene, spezielle Extraktionsfunktion, anstatt zu versuchen, das Verhalten der Standardfunktionen irgendwie zu korrigieren.



  • In was für Fällen gehts denn nicht?


  • Mod

    Nathan schrieb:

    In was für Fällen gehts denn nicht?

    Er will halt, dass

    uint32_t u;
    cin >> u;
    

    für Eingaben der folgenden Art einen Fehler auslöst:

    -1
    1a
    999999999999999
    

Log in to reply