Streamlänge prüfen oder Eingabe überprüfen



  • Hallo, ich hab folgendes Problem.

    Schwer zu erklären aber ich versuchs mal

    Ich habe folgenden Bildschirm

    Eingabe von verschiedenen Zahlen

    zb
    Zahl1:3
    Zahl2:4
    Zahl3: hier gebe ich nun nichts ein und drücke nur die Enter Taste.

    Hier nun die Frage: Kann ich irgendwie eine Exception auswerfen wenn ich nur die Enter Taste drücke OHNE Inhalt.Von mir aus "Geben Sie irgendwas ein hauptsache es steht da was" oder so. Die anderen Inhalte werden nach drücken der Enter Taste in einem Array gespeichert. Durch drücken der Taste Enter wartet er aber nur auf eine Eingabe die aber nicht kommen soll. Geht das irgendwie mit dem Überprüfen ob da nun nichts drin steht oder nicht bzw wie?



  • Schau faq



  • über enter taste drücken ohne inhalt (normalerweise kann man immer noch nach enter eingeben, da >> newlines ignoriert) steht afaik noch nichts in der faq.
    hier, so sollte es funktionieren

    int i;
    
       cout << "Eingabe: ";
       for (;;)
       {   
          stringstream str;
          if (cin.get(*str.rdbuf()))
          {
             if (str >> i)
             {
                cout << "Eingabe war " << i << endl;
                break;
             }
             else
             {
                cout << "Sie haben keine Zahl eingegeben!\n";
             }
          }
          else
          {
             cout << "Sie haben nichts eingegeben!\n";
          }
          cout << "Eingabe wiederholen: ";
          cin.clear(); //falls einmal was nicht klappt, sonst gibt es eine endlosschleife ohne eingabe
          cin.get(); //das get oben liest kein newline ein. deshalb hier das newline aus dem string rausschleudern
       }
    


  • Super danke Enter, schön wärs wenn wir/ich (unser Studentenprojektteam) auch mal auf sowas kommen würden

    Aber wir haben eigentlich vor daraus ein Exception Handling zu basteln. Mit dem Beispiel von dir geht das glauben wir etwas schlecht, daher mal ein Ausschnitt aus unserem Quellcode. Wäre nett wenn das einer so umschreiben könnte, dass wir das auch verwenden können. Nochmal Danke für eure Mühe

    double getnumber(istream &ein)
    { 
      double i;
    
    // Eingabe
    
      ein >> i;
    
    // Falls die Eingabe fehlgeschlagen ist wirft er 1 weiter
    
      if (ein.fail( )) throw 1;
      return i;
    }
    

    und dann der Aufruf

    for (i=0;i<10;i++)
                              {   cout<<endl<<endl<<endl;
    							  cout<<"                 Zahl"<<i+1<<": ";
    
    // Der try-Block für das Exception Handling um Eingabe zu überprüfen
    
    						    try
                                {zahl = getnumber(cin);
                                 erfolgreich = true;
                                }
                                catch(const int z)
                                { 
                                  textcolor(red);
    							  cout<<"                        Falsche Eingabe ! Es sind nur Zahlen erlaubt !"<<endl;
                                  textcolor(white);
    							  getch();
    
                                  cin.clear();
    
                                  while (cin.get() != '\n');
                                  i--;
                                  erfolgreich = false;
                                }
                                if(erfolgreich) darray[i] = zahl;
                              }
    


  • woran hapert's denn?
    den code von mir in eine funktion auszulagern?
    sichergehen, dass cin.clear() und cin.get() am ende der funktion aufgerufen werden?
    schmeißen von exceptions?

    ein erster ansatz sieht so aus (hab auch eure main etwas aufpoliert... sieht ja grässlich aus, so - btw. der stil ist zwar geschmackssache, aber dein code ist doch etwas unleserlich)

    #include <iostream>
    #include <sstream>
    using namespace std;
    
    class InputError //Weil int schmeißen heißt auf exception handling scheißen
    {
    };
    
    class NoInput : public InputError
    {
    };
    
    class WrongFormat : public InputError
    {
    };
    
    /* get_number liest eine zahl auf einem istream und wirft WrongFormat, wenn sich keine zahl darin befindet,
       oder NoInput, wenn der eingabestream mit einem newline endet. get_number arbeitet zeilenweise */
    int get_number (istream &in)
    {
       //da wir mehrere exceptions werfen wollen, müssen wir sichergehen,
       //dass in.clear() und in.get() den stream reparieren. code wiederholung ist allerdings überflüssig
       //der destruktor von cleanup wird nämlich auf jedenfall aufgerufen (RAII)
       struct cleanup {
          istream &in;
          cleanup (istream &in) : in(in) {}
          ~cleanup () { in.clear(); in.get(); }
       } cleaner(in);
    
       //um zu überprüfen, ob überhaupt etwas eingegeben worden ist, wenden wir einen kleinen trick an. (ist dasselbe, wie oben)
       //wir lassen von in direkt in den buffer eines streams schreiben, was nur dann fehlschlägt, wenn keine
       //zeichen im buffer von in sind (das bedeutet, es wurde nichts eingegeben). ansonsten hätten müssten
       //wir auf eine eingabe warten und druck auf enter würde nichts bewirken.
       stringstream str;
       if (in.get(*str.rdbuf()))
       {
          int i;
          //und hier dann ganz normal überprüfen, ob es denn auch wirklich eine zahl war, die eingegeben wurde
          if (str >> i) return i;
          else throw WrongFormat();
       }
       else throw NoInput();
    }
    
    //etwas überarbeitet; hoffe, das macht dir nichts aus.
    int main ()
    {
       //bool erfolgreich; //brauchen wir nicht mehr.
       int darray[10];
       int i = 0;
       while (i<10) //variable i erst so spät wie möglich definieren
       {
          //cout<<endl<<endl<<endl; //pfui. wenn schon, dann cout << "\n\n\n"; 
          try
          {
             cout<<"Zahl "<<++i<<": ";
             darray[i] = get_number(cin);
             cout<<"Erfolgreich. Zahl = " << darray[i] << '\n';
    
          }
          catch(WrongFormat&)
          {
             cout<<"Falsche Eingabe! Es sind nur Zahlen erlaubt!\n";
          }
          catch(NoInput&)
          {
             cout <<"Keine Eingabe. Bitte wiederholen.\n";
          }
       }                       
    }
    

    ist doch gar nicht so schwer.
    jetzt noch ein bisschen flexibler machen.. wenn ich schon dabei bin..

    #include <iostream>
    #include <sstream>
    using namespace std;
    
    class InputError
    {
    };
    
    class NoInput : public InputError
    {
    };
    
    class WrongFormat : public InputError
    {
    };
    
    template <class T>
    struct ExactFormat
    {
       static T read (istream &in)
       { 
          T tmp;
          if (!(in >> tmp)) throw WrongFormat();
          return tmp;
       }
    };
    
    template <>
    struct ExactFormat<string>
    {
       static string read (istream &in)
       {
          string s;
          in >> s;
          return s;
       }
    };
    
    struct NotEmpty
    {
       stringstream str;
       NotEmpty (istream &in)
       {
          if (!in.get(*str.rdbuf())) throw NoInput();
       }
       stringstream &prepare ()
       {
          return str;
       }
    };
    
    struct ClearAndGet
    {
       istream &in;
       ClearAndGet (istream &in) : in(in){}
       ~ClearAndGet () { in.clear(); in.get(); }
    };
    
    template <class T, class FormatPolicy=ExactFormat<T>,
              class StreamPolicy=NotEmpty, class CleanUpPolicy=ClearAndGet>
    class reader
    {
       istream &in;
    public:
       reader (istream &in) : in(in) {}
       T operator () ();
    };
    
    template <class T, class FormatPolicy, class StreamPolicy, class CleanUpPolicy>
    T reader<T, FormatPolicy, StreamPolicy, CleanUpPolicy>::operator () ()
    {
       CleanUpPolicy clean(in);
       return FormatPolicy::read(StreamPolicy(in).prepare());
    }
    
    int main ()
    {
       int i = 0;
       while (i<10) 
       {
          try
          {
             cout<<"Eingabe "<<++i<<": ";
             string x = reader<string>(cin)();
             cout<<"Erfolgreich. Eingabe: " << x << '\n';
    
          }
          catch(WrongFormat&)
          {
             cout<<"Falsche Eingabe! Es sind nur Zahlen erlaubt!\n";
          }
          catch(NoInput&)
          {
             cout <<"Keine Eingabe. Bitte wiederholen.\n";
          }
       }                       
    }
    

    dann kannst du z.b. eine format-policy angeben, wenn du weißt, dass dein endbenutzer gerne tausender mit whitespaces streibt

    template <class T>
    struct IgnoreWhitespaces
    {
       static T read (istream &in)
       {
          char c;
          stringstream str;
          while (in.get(c)) if (c != ' ') str << c; 
          return ExactFormat<T>::read(str);
       }
    };
    //benutzen dann eben so
    double d = reader<double, IgnoreWhitespaces<double> >(cin)();
    

    ein bisschen overengineered? kann sein...



  • Wow ich bin beeindruckt ! Naja *g* wie gesagt wir sind "noch" Anfänger hoffentlich werden wir auch mal so gut wie du

    Erneut 1000 Dank

    PS: Es ging im Projekt um Heap Sort Algorithmus, aber wir wollten das halt en bisschen aufpeppen mit Ex. Hand. usw. wenn wir das eh schon in der Vorlesung hatten.

    Bis dann


Anmelden zum Antworten