Muss die Werte von dem Buch einlesen aber bekomme es nicht richtig hin mit dem Vector 😅



  • Gude ich habe ein Programm geschrieben welches Bücher hinzufügen sowie ausgeben und löschen soll ich hab einen Fehler wo ich das Buch einlesen möchte von dem User in der Zeile (81) und weiß nicht genau wo das Problem liegt könnte mir hier bitte jemand helfen ein Riesen Dankeschön schon voraus (ich programmiere Objekt orientiert) 😅😆

    //
    //  main.cpp
    //  buch
    
    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    //Klasse Buch
    class buch {
    
    private:
    
        string title;
        string autor;
        int jahr;
        int seitenanzahl;
        string kategorie;
    
    public:
    
        //Standartkonstruktor:
        buch();
    
        //Algemeiner Konstruktor
        buch(string t, string a, int j, int s, string k);
    
        //Kopierkonstruktor:
        buch( buch const & buch1);
    
        //Ausgabe methode
        void print();
        
        //Menue methode
        void menue();
    };
    
    
    
    //Buch cpp
    //Standartkonstruktor dekleration
    buch::buch() {
    
        title = "Leer ";
        autor = " Leer";
        jahr = 0;
        seitenanzahl = 0;
        kategorie = "Leer";
    }
    
    
    
    //Allgemeinerkonstruktor dekleration
    buch::buch(string t, string a, int j, int s, string k) {
    
        title = t;
        autor = a;
        jahr = j;
        seitenanzahl = s;
        kategorie = k;
    }
    
    
    //Ausgabe auf dem Display:
    void buch ::print() {
    
        cout << "Titel: " << title << endl << "Autor: " << autor << endl << "jahr: "
        << jahr << endl << "Seitenanzahl: " << seitenanzahl << endl << "Kategorie: "
        << kategorie << endl << endl;
    }
    
    //Die Methode menü defenieren
    void buch ::menue(){
        
        //Vektor erstellen:
        vector<buch> buch_vector;
        
        //Buch hinzufügen
        for(int i = 1; i < 5; i++){
            cin >> buch_vector[i];
                    
        }
          }
    
    
    
    int main(){
    
        //Hier wird der Allgemeiner Konstruktor aufgerufen
        buch k ("Harry", " Potter ", 1998, 1050, " Magie");
        k.print();
        
        //Hier wird der Standartkonstruktor aufgerufen
        buch l;
        l.print();
        
        //Hier wird der Kopierkonstruktor aufgerufen
        buch m;
        m = k;//Objkt k in m objkt kopiert
        m.print();
    
    
        
        return 0;
    
    }
    


  • Du erstellst mit vector<buch> buch_vector einen leeren vector, und da kannst du dann keine Werte an die Indizes schreiben.
    Benutze stattdessen push_back(...) (also erst Wert in temp. buch einlesen und dann hinzufügen).

    PS: Und überlege dir noch mal den Kommentar bei

     //Hier wird der Kopierkonstruktor aufgerufen
    buch m;
    


  • *Achso verstehe meinst du ich soll es so machen?

    buch_vector.push_back(i);
    

    aber das klappt auch nicht... 🙁
    ich bekomme diese Fehlermeldung:
    No matching member function for call to 'push_back'*

    hmm was ist an dem Kommentar falsch mit dem aufrufen des Kopierkonstruktors?


  • Mod

    In einen Buchvector kann man ja auch schlecht ein Zahl wie i einfügen. Vielleicht solltest du es lieber mit einem Buch versuchen?



  • Eine ganz andere Frage: warum ist die Funktion "menue" eine Methode der Klasse "Buch"? Dein "Buchmenü" enthält eine Liste von Büchern. Listen von Büchern vorzuhalten ist aber eher die Aufgabe einer Bibliothek als die Aufgabe eines Buches selbst.



  • @wob achso dann habe ich die Aufgabenstellung nicht ganz verstanden 😩
    Danke dir 😁 👍🏽



  • @SeppJ

    Hmm okay ich habe es damit versucht schau so:

     buch_vector.push_back(buch);
    

    aber es klappt immer noch nicht...



  • @adii950 sagte in Muss die Werte von dem Buch einlesen aber bekomme es nicht richtig hin mit dem Vector 😅:

    @SeppJ

    Hmm okay ich habe es damit versucht schau so:

     buch_vector.push_back(buch);
    

    aber es klappt immer noch nicht...

    Hast du eine Variable mit dem Namen buch?

    Oder heißen die k, l oder m?



  • @DirkB ein die klasse heißt buch



  • @adii950 sagte in Muss die Werte von dem Buch einlesen aber bekomme es nicht richtig hin mit dem Vector 😅:

    @DirkB ein die klasse heißt buch

    Willst du die ganze Klasse in den Vektor schieben oder nur die Inhalte von einer Variablen?



  • Wie initialisierst du denn das buch-Objekt?
    Überlege dir, welchen Konstruktor du dafür benötigst (so wie deine Klasse jetzt definiert ist) und was du dann noch coden mußt.

    @adii950 sagte in Muss die Werte von dem Buch einlesen aber bekomme es nicht richtig hin mit dem Vector 😅:

    hmm was ist an dem Kommentar falsch mit dem aufrufen des Kopierkonstruktors?

    Du rufst dort den Standardkonstruktor auf, und in der anschließenden Zeile den Zuweisungsoperator =.
    Der Kopierkonstruktor wird bei buch m(k); aufgerufen (da du ihn aber nur deklariert, aber nicht definiert hast, käme eine Compilerfehlermeldung). Daher schreibe in der Klasse:

    buch(buch const & buch1) = default;
    


  • @DirkB die Inhalte in der Klasse buch damit ich verschiedene Bücher in den Vektor speichern kann und später das ausgeben sowie auch löschen kann



  • Eine Klasse ist nur eine Vorlage, du benötigst schon ein konkretes Objekt (in deinem Beispiel z.B. die Variablen mit Namen k, l oder m) - daher schrieb ich ja auch:

    also erst Wert in temp. buch einlesen und dann hinzufügen

    damit meinte ich natürlich

    also erst Wert in temp. buch-Objekt (bzw. Variable) einlesen und dann hinzufügen

    Besser ist es, du schreibst erst einmal eine freie Funktion zum Einlesen eines buch-Objekts, welche du dann von deiner Funktion menue (btw.: komischer Name dafür) aus aufrufen kannst, um einen vector zu erstellen.


    Die bessere Lösung wäre die Überladung der Stream-Operatoren <</ >>, aber soweit bis du wohl noch nicht (mit deinem Lernmaterial).



  • @Th69 sagte:

    Die bessere Lösung wäre die Überladung der Stream-Operatoren <</ >>, aber soweit bis du wohl noch nicht (mit deinem Lernmaterial).

    Wenn man das mal wüsste, zumindest weiß er wohl, dass es sowas gibt:

    @adii950 sagte:

    //Vektor erstellen:
    vector<buch> buch_vector;
    
    //Buch hinzufügen
    for(int i = 1; i < 5; i++){
        cin >> buch_vector[i];


  • willst Du das Ganze nicht besser so lösen:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    struct buch
    {
    string titel;
    string autor;
    int jahr;
    int seitenanzahl;
    string kategorie;	
    };
    
    void neu(vector<buch>& v)
    {
    buch b;
    
    cout << "Bitte titel eingeben:\n" ;
    getline(cin , b.titel);
    cout << "Bitte autor eingeben:\n" ;
    getline(cin , b.autor);
    //code
    v.push_back(b);
    }
    
    void ausgabe(vector<buch>& v)
    {
    for(buch& b: v)
    	{
    	cout << b.titel << "\n";
    	cout << b.autor << "\n";
    	//code	
    	cout << "\n";
    	}
    }
    
    void loeschen(vector<buch>& v)
    {
    //code
    }
    
    int main()
    {
    
    vector<buch> verzeichnis;
    
    char cha;
    string str;
    
    while(cha != 'e' )
    	{
    	cout << "Bitte eingeben: e(für ende), n(eu), a(usgabe) oder l(oeschen)\n" ;
    	getline(cin , str);	
    	if(str.length() > 1)
    		continue;
    	else
    		cha = str[0];
    	switch (cha)
    		{
    		case 'e':
    		break;
    		case 'n':
    		neu(verzeichnis);
    		break;
    		case 'a':
    		ausgabe(verzeichnis);
    		break;
    		case 'l':
    		loeschen(verzeichnis);
    		break;
    		}
    	}
    
    return 0;
    }
    
    


  • @yxcvbn In wie weit besser?

    Also, warum bekommt eine Funktion die "neu" heißt, eine Referenz auf einen Vektor übergeben und gibt nichts zurück?
    Warum macht eine Funktion die neu heißt Ausgaben auf std::cout
    Warum übernimmt eine Funktion die ausgabe heißt, eine Referenz und dürfte somit Änderungen an der Datenstruktur vornehmen.

    Warum ist ein Bücherverzeichnis ein Vektor und keine eigene Klasse, die Verzeichnis Funktionalitäten wie hinzufügen, löschen, vlt irgendwann mal nach bestimmten Sachen suchen usw. kapseln kann?

    Hier wurde schon von Überladung der Stream Operatoren geschrieben, warum wurde das nicht gemacht, dann kann man sich unabhängig von std::cin und std::out machen und Funktionalitäten auch automatisiert testen. Und, vor allem, in eine "echten" Anwendung würde man so ein Verzeichnis ja wahrscheinlich auch nicht manuell befüllen, sondern aus z.B. eine CSV Datei auslesen. Wenn man das geschickt löst, kann man vlt die manuelle Eingabe und die automatisierte Version dann mit dem selben Code abarbeiten.

    Vlt ist deine Lösung eine Variante, die die konkrete Aufgabenstellung von @adii950 löst, aber der Ansatz als solcher ist für das Gesamtproblem meiner Meinung nach nicht unbedingt besser geeignet (wenn man von so Kleinigkeiten wie Compilierbarkeit und Ausführbarkeit mal absieht 😉 )



  • @Schlangenmensch
    Wenn ich mir den Code von adii950`s erstem Beitrag und vor allem die Zeilen 73-84 anschaue, ist eine Lösung des von Dir deklariertem Gesamtproblems wohl eher zweitrangig .

    Warum übernimmt eine Funktion die ausgabe heißt, eine Referenz und dürfte somit Änderungen an der Datenstruktur vornehmen.

    Weil ich heute zu geizig für const bin.

    Also, warum bekommt eine Funktion die "neu" heißt, eine Referenz auf einen Vektor übergeben und gibt nichts zurück?

    Gefällt Dir "neues_buch_eingeben" besser?

    Warum macht eine Funktion die neu heißt Ausgaben auf std::cout

    Entweder bist Du blöd oder ich.



  • @yxcvbn sagte in Muss die Werte von dem Buch einlesen aber bekomme es nicht richtig hin mit dem Vector 😅:

    @Schlangenmensch
    Wenn ich mir den Code von adii950`s erstem Beitrag und vor allem die Zeilen 73-84 anschaue, ist eine Lösung des von Dir deklariertem Gesamtproblems wohl eher zweitrangig .

    Es mag sein, dass @adii950 noch C++ Grundlagen fehlen, aber ich bin der Meinung, dass man C++ Nachwuchs auch direkt zeigen muss, wie man Software ordentlich designed. Viele Probleme mit denen sich Anfänger sonst nämlich irgendwann rum schlagen, treten dann gar nicht auf.

    @yxcvbn sagte in Muss die Werte von dem Buch einlesen aber bekomme es nicht richtig hin mit dem Vector 😅:

    Weil ich heute zu geizig für const bin.

    Sollte man, gerade in einem öffentlichen Beitrag, nicht sein. Das sehen nur Leute, die das nicht beurteilen können und das nach machen.
    Ich habe ein Projekt geerbt, in dem 20 Jahre keinerlei const verwendet wurde. Das macht keinen Spaß zu debuggen.

    @yxcvbn sagte in Muss die Werte von dem Buch einlesen aber bekomme es nicht richtig hin mit dem Vector 😅:

    Gefällt Dir "neues_buch_eingeben" besser?

    Auch dann würde es mir besser gefallen, wenn die Funktion ein Buch zurück gibt und nicht auf einer Vektor Referenz hantiert.

    @yxcvbn sagte in Muss die Werte von dem Buch einlesen aber bekomme es nicht richtig hin mit dem Vector 😅:

    Entweder bist Du blöd oder ich.

    Kann schon sein, dass ich blöd bin. Aber ich würde gerne auch neue Buchobjekte erstellen können, wenn ich kein Terminal zur Verfügung habe. Überhaupt, erwarte ich von einer Funktion die ein neues Buchobjekt erstellen sollte, eigentlich keine Ausgabe irgendwo.

    Für mich sind std::cin und std::cout auch globale Objekte, die man nur spärlich einsetzen sollte, da man im Zweifel deren Zustand nicht kennt und die es schwer machen Unittests zu schreiben. Ich würde zumindest Stream Objekt Referenzen in die Funktion geben die dann bei bedarf mit std::cin und std::cout aufgerufen werden können (ähnlich wie std::getline da macht).

    Als alternative

    buch neu(std::istream& in, std::ostream& out)
    {
      buch b;
      out << "Bitte titel eingeben:\n";
      getline(in, b.titel);
      out << "Bitte autor eingeben:\n";
      getline(in, b.autor);
      return b;
    }
    

    Finde ich auch noch nicht schön, ist immer noch Eingabe und Ausgabe in einer Funktion, aber damit ließen sich zumindest Unit Test schreiben.

    User Eingaben über die Konsole zu verarbeiten ist irgendwie nie schön und finde ich daher auch immer etwas unpassend, wenn es darum geht jemandem C++ beizubringen. Auf der anderen Seite sieht man da recht schnell Ergebnisse.

    Besser wäre es wahrscheinlich sich ein Eingabe Format zu überlegen, wie
    <Buch Titel>;<Autor>; <Jahr>...
    Das ganze in einer Zeile einzulesen und dann zu parsen. Dann hat man aber das Problem, was macht man wenn ein ";" im Titel vorkommt... wieder extra Fälle, die den Code umfangreicher machen. Dafür kann man das dann auch verwenden um aus einer CSV direkt eine ganze Liste Bücher einzulesen.


Anmelden zum Antworten