Warum ergibt das eine Endlosschleife?



  • Moin, habe nen kleines Problem. Wenn ich in der zweiten schleife den Eingabe Stream per EOF (im Windows mit STRG+Z) auf false setzen will. Geht er in eine Dauerschleife...

    Warum? und wie kann ich es besser machen :)?

    Criseas

    #include <iostream>
    #include "Sales_item.h"
    using namespace std;
    
    int main() {
        Sales_item eingabe, item1, item2, item3, item4;
        int count=1;
        while(count==1) 
        {
          cout<<"Geben sie ihre ISBN ein!"<<endl;
          cin>>item1;
          cout<<"next"<<endl;
          while(count<=3) 
          {
            cin>>eingabe
            if(eingabe.same_isbn(item1)) 
            {
              item1 = item1 + eingabe;
              cout<<"next"<<endl;
              count++; 
            } else {
              cout<<"Ungültige eingabe!"<<endl; 
            }
          }
          cout<<count<<" Transaktionen: "<<item1<<endl;
          cout<<"1. Weiter | 2. Abbruch"<<endl;
          cin>>count;
          if(count!=1) {
                     return 0;
                     } 
          return 0;
        }
    }
    


  • Du solltest irgendwo den Status des Eingabestreams abfragen und ggf. die Schleife verlassen.

    if (!cin)
      return;
    


  • Noch als Ergaenzung und Antwort auf das 'Warum':
    Weil die IO-Streams, wenn in einem Fehlerzustand (wozu auch EOF zaehlt), einfach nichts machen, d.h. weder einen Wert lesen noch den uebergebenen Wert veraendern.

    while(count<=3) 
          {
            cin>>eingabe
            if(eingabe.same_isbn(item1)) 
            {
              item1 = item1 + eingabe;
              cout<<"next"<<endl;
              count++; 
            } else {
              cout<<"Ungültige eingabe!"<<endl; 
            }
          }
    

    Hier kann z.B. eine Endlosschleife entstehen, wenn !cin.good - in dem Fall wird ggf. count nie veraendert (weil eingabe.same_isbn(item1) ggf. nie erfuellt).



  • Hey danke dir für deine Antworten.

    Tut mir leid mir ist gerade aufgefallen das ich den falschen Quelltext gepostet habe.
    Hatte 2 Versionen und hab natürlich den falschen erwischt...
    Es ist nur ein kleiner unterschied bei der zweiten schleife...
    Aber gleiche Frage wie oben^^.

    #include <iostream>
    #include "Sales_item.h"
    using namespace std;
    
    int main() {
        Sales_item eingabe, item1, item2, item3, item4;
        int count=1;
        while(count==1) 
        {
          cout<<"Geben sie ihre ISBN ein!"<<endl;
          cin>>item1;
          cout<<"next"<<endl;
          while(cin>>eingabe) 
          {
            if(eingabe.same_isbn(item1)) 
            {
              item1 = item1 + eingabe;
              cout<<"next"<<endl;
              count++; 
            } else {
              cout<<"Ungültige eingabe!"<<endl; 
            }
          }
          cout<<count<<" Transaktionen: "<<item1<<endl;
          cout<<"1. Weiter | 2. Abbruch"<<endl;
          cin>>count;
          if(count!=1) {
                     return 0;
                     } 
          return 0;
        }
    }
    

  • Mod

    Aber gleiche Frage wie oben^^.

    Gleiche Antwort wie oben.



  • Okey aber wenn ich in der While(cin>>variable)

    hab und ich des mit strg+z abbreche.. müsste es doch weiterlaufen bis zu der eingabe wo ich das Programm beenden oder Weiterlaufen müsste... oder seh ich das falsch?



  • Allgemein versteh ich auch nicht so ganz was du da veranstaltest. Du hast 4 Items und eine Eingabe, dann lässt du den Benutzer eine ISBN eingeben, die unter item1 abgespeichert wird. Dann lässt du den Benutzer nochmal eine ISBN eingeben, die unter eingabe gespeichert wird und prüfst über eine Funktion, ob diese gleich sind (wie wärs wenn du den == Gleichheitsoperator überlädst?) und wenn sie gleich sind, dann verbindest du item1 mit der eingabe (ich hoffe du hast den + Operator überladen). Was macht das für einen Sinn? Du verbindest sie nur wenn beide gleich sind und wenn nicht, ist die Eingabe ungültig.



  • [OT]
    @FreakY<3Cpp
    Du alter freak, sag nicht du gehst morgens vor der Schule noch ins Forum 😃
    [/OT]



  • Kóyaánasqatsi schrieb:

    [OT]
    @FreakY<3Cpp
    Du alter freak, sag nicht du gehst morgens vor der Schule noch ins Forum 😃
    [/OT]

    DU alter freak :p ...
    Naja die verdammten Züge meinen nicht zu fahren. Jetzt muss ich erst mal gleich zur Schule gefahren werden und weil was wichtiges ist, muss ich da auch noch hin. Ansonsten würde ich wieder im Bett liegen und von Sachen träumen, was genau, will ich jetzt nicht weiter erläutern.


  • Mod

    Criseas schrieb:

    Okey aber wenn ich in der While(cin>>variable)

    hab und ich des mit strg+z abbreche.. müsste es doch weiterlaufen bis zu der eingabe wo ich das Programm beenden oder Weiterlaufen müsste... oder seh ich das falsch?

    Haste eigentlich Recht, war gestern ein bisschen spät, als ich geantwortet habe 🙄 . Kannst du mal deinen Operator >> zeigen?



  • Hmm okey schon, ich weiß das ich das mit counter oder einer eindeutigen Bedingungen machen könnte.

    Aber es geht ja auch das die While solange läuft wie man eingaben tätigt.. Jedenfalls steht es so im C++ Primer

    while(cin>>eingabe)
    

    Und das durch ein EOF die While unterbrochen wird.

    Allerdings gerate ich dadurch wie oben geschrieben in eine Dauerschleife.. und ich versteh nicht warum.

    Die Variablen item2-4 kann man vergessen die sind noch nicht deklariert.

    @SeppJ das ist "eingabe"

    Viele Grüße



  • Criseas schrieb:

    @SeppJ das ist "eingabe"

    ???????????????????

    Der Sepp hat dich gebeten den >>Operator für die Klasse Sales_item herzuzeigen.

    Es sieht im Moment so aus, als wurde für die Klasse Sales_item der >>Operator überladen. Um dir helfen zu können müsste man daher wissen, was dort gemacht wird.



  • Achsoo,
    ja sorry bin noch nicht soweit in der Materie, in dem Buch sind die mir Bekannten Operationen von der Klasse das Addieren von Sales_item objekten. Sowie das Vergleichen von 2 ISBNs mittels variable.same_isbn(variable) als Elementfunktion sowie das lesen und schreiben sowie zuweisen mit cin und cout und =.

    Mehr ist mir von der Klasse noch nicht bekannt.
    Wenn ihr mir sagt was ich euch nun genau zeigen soll kann ich das tun. So versteh ich aber nicht was ihr mit Überladen meint.

    Danke euch soweit schonmal^^

    Grüße

    Criseas


  • Mod

    Irgendwo, vermutlich in einer Datei namens sales_item.cpp oder so ähnlich, gibt es sowas in der Art:

    std::ostream& operator<<(std::ostream& lhs, Sales_item const& rhs) // Genaue Syntax und Variablennamen können anders sein
    {
     // Und das was hier steht, müssen wir wissen um dir zu helfen
    }
    


  • Was Sepp wohl meint ist

    istream& operator>>(istream&, Sales_item&);
    

    Also, Eingabe und nicht Ausgabe.


  • Mod

    hmpf schrieb:

    Was Sepp wohl meint ist

    istream& operator>>(istream&, Sales_item&);
    

    Also, Eingabe und nicht Ausgabe.

    Ähh, ja, bin gerade durcheinander gekommen.



  • So ich hoffe ich darf das posten ansonsten sagt mir bescheid dann lösch ich das wieder :).

    /*
     * This file contains code from "C++ Primer, Fourth Edition", by Stanley B.
     * Lippman, Jose Lajoie, and Barbara E. Moo, and is covered under the
     * copyright and warranty notices given in that book:
     * 
     * "Copyright (c) 2005 by Objectwrite, Inc., Jose Lajoie, and Barbara E. Moo."
     * 
     * 
     * "The authors and publisher have taken care in the preparation of this book,
     * but make no expressed or implied warranty of any kind and assume no
     * responsibility for errors or omissions. No liability is assumed for
     * incidental or consequential damages in connection with or arising out of the
     * use of the information or programs contained herein."
     * 
     * Permission is granted for this code to be used for educational purposes in
     * association with the book, given proper citation if and when posted or
     * reproduced.Any commercial use of this code requires the explicit written
     * permission of the publisher, Addison-Wesley Professional, a division of
     * Pearson Education, Inc. Send your request for permission, stating clearly
     * what code you would like to use, and in what specific way, to the following
     * address: 
     * 
     * 	Pearson Education, Inc.
     * 	Rights and Contracts Department
     * 	75 Arlington Street, Suite 300
     * 	Boston, MA 02216
     * 	Fax: (617) 848-7047
    */ 
    
    #ifndef SALESITEM_H
    #define SALESITEM_H
    
    // Definition of Sales_item class and related functions goes here
    
    #include <iostream>
    #include <string>
    
    class Sales_item {
    friend bool operator==(const Sales_item&, const Sales_item&);
    // other members as before
    public:
        // added constructors to initialize from a string or an istream
        Sales_item(const std::string &book):
                  isbn(book), units_sold(0), revenue(0.0) { }
        Sales_item(std::istream &is) { is >> *this; }
        friend std::istream& operator>>(std::istream&, Sales_item&);
        friend std::ostream& operator<<(std::ostream&, const Sales_item&);
    public:
        // operations on Sales_item objects
        // member binary operator: left-hand operand bound to implicit this pointer
        Sales_item& operator+=(const Sales_item&);
        // other members as before
    
    public:
        // operations on Sales_item objects
        double avg_price() const;
        bool same_isbn(const Sales_item &rhs) const
            { return isbn == rhs.isbn; }
        // default constructor needed to initialize members of built-in type
        Sales_item(): units_sold(0), revenue(0.0) { }
    // private members as before
    private:
        std::string isbn;
        unsigned units_sold;
        double revenue;
    
    };
    
    // nonmember binary operator: must declare a parameter for each operand
    Sales_item operator+(const Sales_item&, const Sales_item&);
    
    inline bool 
    operator==(const Sales_item &lhs, const Sales_item &rhs)
    {
        // must be made a friend of Sales_item
        return lhs.units_sold == rhs.units_sold &&
               lhs.revenue == rhs.revenue &&
    	   lhs.same_isbn(rhs);
    }
    
    inline bool 
    operator!=(const Sales_item &lhs, const Sales_item &rhs)
    {
        return !(lhs == rhs); // != defined in terms of operator==
    }
    
    using std::istream; using std::ostream;
    
    // assumes that both objects refer to the same isbn
    inline
    Sales_item& Sales_item::operator+=(const Sales_item& rhs) 
    {
        units_sold += rhs.units_sold; 
        revenue += rhs.revenue; 
        return *this;
    }
    
    // assumes that both objects refer to the same isbn
    inline
    Sales_item 
    operator+(const Sales_item& lhs, const Sales_item& rhs) 
    {
        Sales_item ret(lhs);  // copy lhs into a local object that we'll return
        ret += rhs;           // add in the contents of rhs 
        return ret;           // return ret by value
    }
    
    inline
    istream& 
    operator>>(istream& in, Sales_item& s)
    {
        double price;
        in >> s.isbn >> s.units_sold >> price;
        // check that the inputs succeeded
        if (in)
            s.revenue = s.units_sold * price;
        else 
            s = Sales_item();  // input failed: reset object to default state
        return in;
    }
    
    inline
    ostream& 
    operator<<(ostream& out, const Sales_item& s)
    {
        out << s.isbn << "\t" << s.units_sold << "\t" 
            << s.revenue << "\t" <<  s.avg_price();
        return out;
    }
    
    inline
    double Sales_item::avg_price() const
    {
        if (units_sold) 
            return revenue/units_sold; 
        else 
            return 0;
    }
    
    #endif
    

  • Mod

    Nie im Leben gibt das eine Endlosschleife. Ist das ganz sicher der richtige Code? Mit allen Klammern exakt so wie hier geschrieben?

    while(count==1)
        {
          cout<<"Geben sie ihre ISBN ein!"<<endl;
          cin>>item1;
          cout<<"next"<<endl;
          while(cin>>eingabe)
          {
            if(eingabe.same_isbn(item1))
            {
              item1 = item1 + eingabe;
              cout<<"next"<<endl;
              count++;
            } else {
              cout<<"Ungültige eingabe!"<<endl;
            }
          }
          cout<<count<<" Transaktionen: "<<item1<<endl;
          cout<<"1. Weiter | 2. Abbruch"<<endl;
          cin>>count;
          if(count!=1) {
                     return 0;
                     }
          return 0;
        }
    

    Wie sieht denn die Ausgabe aus?



  • SeppJ schrieb:

    Nie im Leben gibt das eine Endlosschleife. ...

    Sehe ich auch so. Im Gegenteil durch das return 0 innerhalb der while (count==1) Schleife ist man sogar früher als geplant aus dem Programm heraus.

    Der hier präsentierte Quelltext stimmt wohl nicht mit dem überein, was der Fragesteller daheim ausführt.



  • Die Ausgabe sieht wie folgt aus:

    F:\Salesitem2.exe
    Geben sie ihre ISBN ein!
    0-201-78345-x 5 50.00
    next
    0-201-78345-x 3 25.00
    next
    0-202-78343-x 2 20.00
    Ung³ltige eingabe!
    0-201-78345-x 3 25.00
    next
    ^Z
    3 Transaktionen: 0-201-78345-x 11 400 36.3636
    1. Weiter | 2. Abbruch

    F:\

    wie mann nach
    1. Weiter | 2. Abbruch

    sehen kann konnte ich nixmehr eingeben!

    Aber durch eine Änderung weiter oben nehmlich

    cout<<"Geben sie ihre ISBN ein!"<<endl;
          cin>>item1;
          cout<<"next"<<endl;
          while(cin>>eingabe)
    

    geht es auch nichtmehr in eine Dauerschleife und ich weiß warum!! AHA

    Die Frage ist nun geklärt. Aber warum Funktioniert es nicht so wie gewünscht? Also warum kann ich vor der IF den Eingabestream nicht benutzen?


  • Mod

    😡 Dann war die frage die ganze Zeit, warum das keine Endlosschleife ergibt? Na vielen Dank, das hätten wir dir auch sofort beantworten können. 😡

    Criseas schrieb:

    Die Frage ist nun geklärt. Aber warum Funktioniert es nicht so wie gewünscht?

    Um es mal direkt zu sagen: Weil dein Code ein totales Schlamassel ist. FreakY<3Cpp hat schon ein paar passende Bemerkungen gemacht. Dein Einsatz der Kontrollstrukturen ist total wirr und sinnlos. Schmeiss den ganzen Code weg. Mach dir erstmal Gedanken, wie dein Programm ablaufen soll. Das malst du dir dann auf einem Blatt Papier als Ablaufplan hin. Und diesen Plan übersetzt du dann in C++ Kontrollstrukturen. Und dann wird das auch funktionieren.


Anmelden zum Antworten