Abfangen von Eingabefehlern



  • Hi,

    ich wollte wissen ob man den Inhalt einer Variable darauf abfragen kann ob er nummerisch ist oder nicht?

    Ich hatte die idee eingabefehler ungefähr so abzufangen:

    char input;
    
    while(input == "nummerisch")
    {
      std::cin >> input;
    }
    


  • isNumeric() ?



  • Header: <locale>
    Function: isalpha(..)
    (C++ Runtime Library)

    --------------------------------------------------------------------------------------------------------
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-200516-and-start-is-10.html
    Ah, ja?



  • Naja kommt darauf an ob du das wirklich in dem Fall brauchst. Wenn du es einfach als falsche Eingabe behandelt haben willst, wenn keine Zahl eingegeben wird, dann guck mal in deinen anderen Thread dir die Funktion type und clear_stream an. Wenn es bei einem Eingabestream nicht möglich ist etwas einzulesen (in den entsprechenden Typ), wird ein failbit gesetzt. Das kannst du abfragen (fail() oder operator!, !good(), operator void* usw.). Wenn es gesetzt ist musst du den Stream aufräumen und das failbit wieder löschen. Dann kannst du es erneut versuchen. Bis die Eingabe korrekt ist 🙂



  • Ich habe versucht einen eingabefehler abzufangen:

    unsigned int basis;
    do
    {
       std::cin >> basis;
       std::cout << std::endl;
    
       if(isalpha(basis))
       {
          std::cout << "FEHLER: Falsche Eingabe!\n";
       }
    }
    while(isalpha(basis));
    

    es hat nicht geklapt... 😞

    das programm gibt nicht mal "FEHLER: Falsche Eingabe!" aus.
    Was habe ich falsch gemacht 😕 😕 😕



  • http://www.cplusplus.com/reference/clibrary/cctype/isalpha.html
    isdigit ist wohl besser (mein fehler) als islapha.

    Jedoch denke ich dass dein Test so nicht funktioniert, da std::cin >> basis; die gelesenen character gerade konvertiert, oder?

    isdigit etc. nehmen als Argument ein unsigned int, jedoch ist das ein character (einfach ein Zeichen).



  • simon.gysi schrieb:

    Jedoch denke ich dass dein Test so nicht funktioniert, da std::cin >> basis; die gelesenen character gerade konvertiert, oder?

    isdigit etc. nehmen als Argument ein unsigned int, jedoch ist das ein character (einfach ein Zeichen).

    du hast recht

    hat jemand eine andere idee?

    Weitere infos:
    es handelt sich um eine Benutzereingabe,
    ich muss damit noch rechnen(deswegen möchte ich auch verhindern, dass ein buchstabe gespeichert wird)



  • isalpha, isdigit und konsorten überprüfen jeweils nur ein _zeichen_, also einen character. aber wenn du cin in einen int einlesen lässt, dann hast du kein zeichen eingelesen, sondern eine zahl - und die kann aus mehreren zeichen bestehen.

    es kommt wohl genauer darauf an, welche eingabe du erwartest und wie du darauf reagieren willst.

    wenn ein eingabestream ein problem mit dem lesen hat, dann wird entweder das fail- oder das badbit gesetzt (letzteres zeigt idR an, das man den stream nicht verwenden kann). da C++ relativ streng getypet ist, kannst du also in einen integer einlesen und via failbit überprüfen, ob die eingabe geklappt hat:

    int i;
    cin >> i;
    if (cin.fail()) //eingabe hat nicht funktioniert.
    

    streams bieten darüber hinaus noch die operatoren! und void*. damit ist es möglich, das ganze so zu vereinfachen:

    int i;
    cin >> i;
    if (cin) //alles gut ...
    if (!cin) //... oder nicht?
    

    dann gibt es aber noch eine menge probleme, die bei einer falscheingabe auftreten können, wie z.b. überschüssige zeichen im puffer usw.

    ich empfehle dir zur einführung: http://www.cs.rit.edu/~cs4/pub/doc/iostreams.html



  • Also, nochmal:
    std::isalpha <cctype>

    Wenn du bsw. folgendes hast:

    #include <cctype>
    #include <iostream>
    
    int main()
    {
        const char character('a');
        const char number('1');
        std::cout << "\'" << character << "\' is a number? " << std::isalpha(character) << std::endl;
        std::cout << "\'" << number << "\' is a number? " << std::isalpha(number) << std::endl;
    }
    

    .

    Ein Eingabestring hat ja wie oben stehend ein good, ein fail und ein bad-bit. Das good-bit heißt, es ist alles in Ordnung. failbit, wenn etwas fehlgeschlagen ist. Badbit ist "an error that caused the loss of integrity of the stream".

    bad und failbit kannst du über fail und/oder bad abrufen:

    unsigned int number(0);
    std::cin >> number;
    if (std::cin.fail() == true) std::cerr << "Es wurde keine Zahl eingegeben!" << std::endl;
    

    .
    Nun wurde aber auch der operator! und operator void* überladen. operator! gibt true zurück, wenn fail oder badbit gesetzt ist. operator void* gibt einen Nullpointer zurück, wenn das fail oder badbit gesetzt ist.
    Deswegen können wir das auch so abfragen:

    unsigned int number(0);
    std::cin >> number;
    if (!std::cin) std::cerr << "Es wurde keine Zahl eingegeben!" << std::endl;
    

    Das Design der Streamklassen ist so, dass jeder Streamoperator wieder ein Streamobjekt zurückgibt, wodurch folgendes möglich ist.

    std::cout << "Das " << " ist " << 1 << " (eins) !" << std::endl;
    

    . Wäre die Streamklasse nicht so designt, müsstest du immer folgendes machen:

    std::cout << "Das "; std::cout << " ist "; std::cout << 1;
    

    usw.

    d.h. ist nun folgendes möglich:

    unsigned int number(0);
    if (!(std::cin >> number))std::cerr << "Es wurde keine Zahl eingegeben!" << std::endl;
    

    .

    Jetzt musst du noch wissen, dass man erst ein failbit löschen muss, damit du wieder sauber einlesen kannst. Das macht die Funktion clear.

    std::cin.clear()
    

    Eingabestreams sind gepuffert (zumindest im Falle von std::cin) und deswegen kann sich noch mist im Eingabepuffer befinden. Der muss da raus. Das geht mit ignore.

    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    

    Wobei durch std::numeric_limitsstd::streamsize ein Template genutzt wird, dass dir die Limitierungen eines Datentypes zeigt. (Oftmals werden einfach konstant Werte hinterlegt (durch Templatespezialisierungen)). max() ist dabei die obere Grenze.
    Die Anzahl der im Eingabepuffer befindlichen Daten kann schlecht größer sein als des Buffers Größe und von d.h. ... '\n' ist das Newline-Zeichen und sollte sich von alleine Erklären.

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    

    räumt also für und den Eingabestream wieder auf. Also machen wir uns da mal eine Funktion daraus, damit wir die auch öfters nutzen können.

    std::istream& clear_stream(std::istream& in)
    { 
        in.clear();
        in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        return in;
    }
    

    Nun hab ich ja oben bereits erwähnt, dass die Streamfunktionen meist alle schön eine Referenz von sich zurückgeben. Daran haben wir uns jetzt bei der clear_stream-Funktion auch gehalten. Das erlaubt uns aber noch eine Kürzung, da in.ignore ja wieder in zurückgibt.

    std::istream& clear_stream(std::istream& in)
    { 
        in.clear();
        return in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
    

    Hier könnte man nun mit dem Komma-Operator weiter kürzen, doch da einige in diesem Forum das als unübersichtlich und unprofessionel ansehen, lass ich das jetzt mal.

    Nun haben wir unsere Funktion zum bereinigen des Streams bei Falscheingabe(clear_stream) und wir wissen wie wir falsche Eingabe aufspüren (operator!). Das kombinieren wir jetzt einfach:

    unsigned int number(0);
    while (!(std::cin >> number)) 
    { 
        std::cout << "Falsche Eingabe!" << std::endl;
        clear_stream(std::cin);
    }
    

    Wie man das weiter optimiert habe ich auch in einem anderen Thread schon gezeigt, weshalb ich hier da jetzt nicht genauer drauf eingehe. Wir können jetzt auch noch hingehen und nur Zahlen von 0 bis 1000 odg. zulassen:

    unsigned int number(0);
    while (!(std::cin >> number) || number > 1000) 
    { 
        std::cout << "Falsche Eingabe!" << std::endl;
        clear_stream(std::cin);
    }
    

    .

    Das sollte jetzt mal als Erklärung reichen ... und mein Können ist deinem ja, wie du in dem anderen Post festgestellt hast, bei weitem unterlegen. Von daher gehe ich davon aus das dir das alles schon klar war und du und jetzt nur nochmal testen wolltest. :xmas1:

    Bearbeitung
    Mein Beitrag war wohl zu lang und ich hab zu lange beim Tippen gebraucht. Hab eure Antworten noch nicht gesehen gehabt!



  • erstmal danke ich euch allen sehr

    (D)Evil schrieb:

    Das sollte jetzt mal als Erklärung reichen ... und mein Können ist deinem ja, wie du in dem anderen Post festgestellt hast, bei weitem unterlegen. Von daher gehe ich davon aus das dir das alles schon klar war und du und jetzt nur nochmal testen wolltest. Weihnachten

    Ich glaube du hast mich falsch verstanden, oder ich habe mich falsch ausgedrückt, ich habe nicht an deinem können gezweifelt, ich wollte nur klarstellen, dass das können nichts mit dem alter zu tun hat.



  • (D)Evil schrieb:

    Mein Beitrag war wohl zu lang und ich hab zu lange beim Tippen gebraucht. Hab eure Antworten noch nicht gesehen gehabt!

    Hättest dir auch sparen können :p
    http://c-plusplus.net/forum/viewtopic-var-p-is-1319931.html


Anmelden zum Antworten