Vektor-Funktion bricht nach einer Eingabe ab



  • @Th69 der compiler ist auf More Warnings eingestellt, aber Warnungen bzgl. der find-Funktion tauchen nicht auf.

    Die Funktion weist doch eine return-Funktion auf:
    return this->users.at(i);

    oder müsste am Ende der find-Funktion return 0 erfolgen?

    Bzgl. des logins kann ich ja eine erneute Abfrage des Logins für den else-Zweig implementieren.

    @wob Das auslagern in eine Funktion geht ja flott, da die Funktionen schon stehen. Das mache ich dann noch, sobald ich die kleinen Probleme aus der Welt geschafft habe.
    Dass ich in Case 2 den Login habe, ist vorgegeben aus der Altklausur-Aufgabe. Ich stelle mir aber auch hier die Frage:
    Der Login ist dafür gedacht, eine Abfrage der Daten, bestehend aus Benutzername und Passwort, zu starten. Normalerweise müsste der Benutzer vorher eine Art Registrierung durchlaufen, damit die Login-Funktion einen Sinn macht, oder liege ich da falsch?



  • @Suprax sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    @Th69 der compiler ist auf More Warnings eingestellt, aber Warnungen bzgl. der find-Funktion tauchen nicht auf.
    Die Funktion weist doch eine return-Funktion auf:
    return this->users.at(i);
    oder müsste am Ende der find-Funktion return 0 erfolgen?

    JEDER Weg aus der Funktion muss ein return haben!

    return 0 geht nicht, denn 0 ist ja kein Benutzer, sondern eine Zahl. Du könntest aber z.B. einen Pointer auf den Benutzer returnen und mit nullptr "nicht gefunden" markieren.

    PS: Deine Logik in case 6 ist auch falsch. Überleg mal, wann bei dir true und wann false rauskommt.



  • @wob so ungefähr?

    return this->users nullptr; 
    

    Zu Case 6: Ich iteriere durch mein Benutzer Vektor und mein Video-Vektor, wenn die ID des Videos gleich der ID des Favoritenvideos ist , dann gibt er Truezurück, andernfalls wurde eines vom beiden nicht gefunden, daher false.
    Oder wo sitzt mein Denkfehler?



  • Einen nullptr kannst du nicht zurückgeben, da die Funktion ja ein Benutzer-Objekt zurückgeben soll (keinen Zeiger).
    Du könntest aber am Ende wenigstens eine Exception werfen (wie in addToFavorites, welche du dann auch entsprechend umschreiben kannst, so daß sie diese find-Funktionen aufruft).

    Noch besser wäre es dann jedoch, die Funktion würde statt einer Kopie eine (konstante) Referenz zurückgeben, also

    const Benutzer& OnlineVideothek::findUser(string name)
    // bzw.
    Benutzer& OnlineVideothek::findUser(string name)
    

    Würdest du bisher nämlich Änderungen an dem zurückgegebenen Benutzer-Objekt machen (z.B. durch Aufruf von setCurrent_video), so wären diese Änderungen nicht im vector<Benutzer>-Objekt des OnlineVideothek-Objekts enthalten!

    Edit: In deinem case 6 hast du denselben Logik-Fehler bzgl. dem else wie in der login-Funktion. Überlege mal, was bisher passiert, wenn der 2. Wert der gefundene sein soll?



  • @Th69

    Benutzer& OnlineVideothek::findUser(string name) {
    
        for (unsigned int i = 0; i < this->users.size(); i++) {
    
            if (this->users.at(i).get_User() == name) {
    
                return this->users.at(i);
            } else {
    
                throw runtime_error("User nicht gefunden");
            }
        }
    // Hier müsste dann eine return funktion stehen
    }
    

    Jetzt erscheint auch die Warnung, dass meine Funktion das Ende einer non-void Funktion erreicht.
    Da wo mein Kommentar liegt, müsste ich da dementsprechend eine Exception schreiben?

    Bzgl. case 6: Die Funktion iteriert durch beide Vektoren, wenn erst der 2. Wert der gefundene sein soll, aber der erste Wert nicht der richtige ist, dann gibt er bereits beim 1. Wert ein false zurück und sucht gar nicht erst nach dem zweiten Wert, oder?



  • Jetzt überlege dir für diese Funktion mal, was passiert, wenn hier der 2. (oder 3. oder ...) Benutzer der zu findende ist?
    Und dann sollte dir dein genereller Logik-Fehler klar sein.



  • @Th69 Theoretisch sucht die Funktion erst gar nicht nach dem 2 oder 3 Benutzer, wenn bereits beim ersten Benutzer ein false zurückgegeben wird, richtig?



  • Ja, genau!



  • Das heißt man bräuchte keine Ausgabe von false, sondern er soll solange suchen, bis er den richtigen User gefunden hat und dann dementsprechend ein true zurückgeben. Also brauche ich in dem Fall kein false?



  • Ja, erst nach der Schleife gibst du false (oder eine Exception) zurück.



  • Super, habe ich geändert.
    Aber bzgl. der Rückgabe sagtest du, dass ich eine Exception werfen soll oder am besten eine konstante Referenz.

    Da müsstest du mir mal auf die Sprünge helfen. Wie würde das aus der Sicht der Syntax aussehen?



  • Das mußt dir dir ja selber überlegen, was du als Rückgabe dann verwenden willst. Bei einem Objekt oder einer (konstanten) Referenz müßtest du ja einen Standard-Benutzer (o.ä.) zurückgeben - und dann entsprechend nach dem Aufruf abfragen.
    Oder aber du nimmst einen Zeiger auf einen (konstanten) Benutzer und gibst dann nullptr zurück und fragst dementsprechend ab (andererseits sind Zeiger immer etwas unschöner zu benutzen, wegen der Dereferenzierung mittels *bzw. ->).
    Wenn du aber eher davon ausgehst, daß es eine Ausnahme ist, daß ein Benutzer nicht gefunden wird, dann würde ich die Variante mit der Exception nehmen.



  • @Th69 sagte in Vektor-Funktion bricht nach einer Eingabe ab:

    Das mußt dir dir ja selber überlegen, was du als Rückgabe dann verwenden willst. Bei einem Objekt oder einer (konstanten) Referenz müßtest du ja einen Standard-Benutzer (o.ä.) zurückgeben - und dann entsprechend nach dem Aufruf abfragen.
    Oder aber du nimmst einen Zeiger auf einen (konstanten) Benutzer und gibst dann nullptr zurück und fragst dementsprechend ab (andererseits sind Zeiger immer etwas unschöner zu benutzen, wegen der Dereferenzierung mittels *bzw. ->).
    Wenn du aber eher davon ausgehst, daß es eine Ausnahme ist, daß ein Benutzer nicht gefunden wird, dann würde ich die Variante mit der Exception nehmen.

    Hm, spannend. Ich habe eine andere Meinung. Für eine Funktion get_user(const string &name) - ok, die returnt einen User (Benutzer&) - fein. Aber wenn ich eine Funktion find_user habe, dann sehe ich schon im Namen, das da etwas gesucht wird, das auch mal nicht gefunden werden kann. Da würde ich grundsätzlich erwarten, dass hier irgendwas rauskommt, das ich testen muss, ähnlich wie bei std::find und Varianten. Ob es nun ein end-Iterator oder ein nullptr ist, egal.

    Daher würde ich

    Benutzer* OnlineVideothek::findUser(const string &name) {
        for (unsigned int i = 0; i < this->users.size(); i++) {
            if (this->users.at(i).get_User() == name)
                return &this->users.at(i);
        }
        return nullptr;
    }
    

    Wobei noch anzumerken wäre, dass ich die for-Schleife so nicht verwenden würde, aber das Beispiel jetzt nicht noch weiter ändern will. Die Frage ist auch, ob man nicht gleich eine map<Username, User> nehmen sollte. Im jetzigen Fall ist der Benutzer, der von dieser Funktion zurückkommt, nicht mehr gültig, wenn man eine andere Person einfügt.
    Und @Suprax, du solltest dringend den Namen der Funktion get_User überdenken! Der User ist doch schon das, was im Array users drin ist. Der sollte für den Namen eine Funktion wie get_name(), get_username() (oder ohne das get_) oder ähnlich haben! Außerdem ist es verwirrend, eine Klasse Benutzer zu haben, diesen aber mit createUser zu erstellen. Nimm einen Namen (den Englischen, wenn möglich).



  • Habs mittlerweile hinbekommen und die Fehler ausgebessert. Danke an alle!


Anmelden zum Antworten