Klassenattribut nach einlesen überschreiben



  • Hallo,

    ich speichere ein Objekt in eine Datei und lese dieses dann wieder ein.
    Das Objekt enthält eine std::list und diese macht Probleme. Diese Liste besitzt beim Speichern 0 Einträge und nach dem einlesen wird auch nur eine leere Liste benötigt.
    Das Problem ist, dass die Liste zwar im Debugger richtig als leer angezeigt wird, aber wenn man auf die Liste zugreifen will geht er ins Nirvana.
    Wie kann ich nach dem Einlesen, dass Attribut mit einer neuen Liste überschreiben. Es müsste irgendwie über nen Pointer gehen der auf das Attribut zeigt und dann an diese Stelle müsste dann eine leere Liste kommen.

    Hoffe ihr versteht, was ich meine.

    Danke

    MfG
    NiBurhe



  • poste doch bsp. code



  • Kurs.h

    #pragma once
    #include "Dozent.h"
    #include "Student.h"
    #include <string>
    #include <list>
     using namespace std;
    class Dozent;
    class Student;
    /*
    Diese Klasse stellt einen Kurs dar.
    */
    class Kurs
    {
    private:
    	//Das Thema des Kurses.
    	std::string _thema;
    	//Das Spezialgebiet welches der Dozent benötigt um den Kurs halten zu dürfen.
    	std::string _gebiet;
    	//Semester für welches der Kurs geeignet ist.
    	int _semester;
    	//Liste der Studenten die in dem Kurs sind.
    	std::list<Student*> _studenten;
    	//Der Dozent, der den Kurs liest.
    	Dozent *_dozent;
    	//Gibt der Anzahl der teilnehmenden Studenten zurück.
    	int getAnzahlTeilnehmer();
    	//Id des Dozenten zum Speichern.
    	int _dozentenId;
    	//Id der Studenten zum Speichern.
    	int _studentenId[20];
    
    };
    

    Wobei ich die _studenten beim speichern nich benötigt werden, da es über das Int Array rekonstruiert wird.

    Zum einlesen:

    //erzeugt ein studentenobjekt
    	Student student("","",0,0);
    
    	//erzeugt eine studentenliste
    	 std::list<Student> liste;
    	 //erstellt die betreffenden streams
    	 ifstream in(fileN1.data(), ios::binary);
    	 ifstream objekte(fileN.data(), ios::binary);
    
    	 //liest die anzahl vorhandener objekte ein
    	 objekte.read((char*)&anzahlObjekte,sizeof(anzahlObjekte));
    
    	 //liest die vorhandenen objekte ein und legt sie in der studentenliste ab
    	 if(anzahlObjekte>0)
    	 {
    		for(int i=0;i<anzahlObjekte;i++)
    		{
    			in.read((char*)&student, sizeof(student));
    
    			liste.push_back(student);
    		}
    	 }
    

    Das einlesen in das Kurs Objekt funktioniert, aber das Attribut _studenten des Kurses ist nicht mehr gültigt, dadurch stürzt push_back ab. Daher möchte ich das Attribut _studenten von Kurs durch eine neue leere Liste überschreiben, die Liste die gespeichert wurde ist auch leer gewesen.

    Hoffe jetzt ist klarer.

    MfG
    NiBurhe



  • klar sind vor allem mehrere Dinge:

    - du benutzt im header ein using namespace std. Das solltest du dir gleich wieder abgewoehnen, mehr zu dem Thema hier

    - an die Mebmer deiner Kurs-Objekte kommt niemand heran, da alles private ist und du keinerlei Methoden definiert hast

    - Die Art wie du deine Objekte abspeicherst ist alles andere als portabel, da du Die Objekte so, wie sie intern von deinem Compiler in den Speicher gelegt werden, aus der Datei ausliest, das ist pfui 😉 Versuch eventuell erstmal durch Ueberladen von operator<< deine Studenten im Klartext abzuspeichern, wenn das dann klappt, kannst du daran gehen, eine portable binaere Speichermethode zu entwickeln (was nicht unbedingt trivial ist)



  • Hi,
    Du benutzt ja beim einlesen die variable _studenten gar nicht.

    Du könntest es so machen:

    class Kurs
    {
    private:
        //Liste der Studenten die in dem Kurs sind.
        std::list<Student> _studenten;
        // ... weitere Deklarationen
    };
    

    In der einlese Funktion:

    //erstellt die betreffenden streams
    ifstream in(fileN1.data(), ios::binary);
    ifstream objekte(fileN.data(), ios::binary);
    
    //liest die anzahl vorhandener objekte ein
    objekte.read((char*)&anzahlObjekte,sizeof(anzahlObjekte));
    
    //liest die vorhandenen objekte ein und legt sie in der studentenliste ab
    if(anzahlObjekte>0)
    {
       // Lösche alle Objekte aus der Liste vor dem erneuten füllen.
       _studenten.clear();
    
       for(int i=0;i<anzahlObjekte;i++)
       {
          //erzeugt ein studentenobjekt
          Student student("","",0,0);
          in.read((char*)&student, sizeof(student));
          _studenten.push_back(student);
       }
    }
    

    So werden die Student Objekte in die Liste kopiert und Du musst dich nicht explizit ums Speicher allozieren/freigeben kümmern. Natürlich müssen die Student Objekte kopierbar sein.

    Simon



  • @pumuckl

    Das mit dem Namespace std stammt so eins zu eins aus der Vorlesung 😉

    Das muss nicht schön sein, es muss erstmal nur funktionieren, dumme unbenotete Testate.

    Das Speichern und auslesen an sich funktioniert, das Objekt sieht im Debugger richtig aus. Nur die Liste _studenten macht Probleme, sie scheint zwar im Debugger eine leere Liste zu sein, sobald man aber auf die Liste zugreifen will, schiesst er sich ab. Daher wollte ich die Liste _studenten, die mit ausgelesen wurde, mit einer neuen Liste überschreiben, da ich ja nur eine leere Liste brauche. Er scheint halt eine Speicheradresse für die Liste zu speichern, aber wenn es wieder ausliest ist diese Speicheradresse nicht mehr gültig, deswegen wollte ich ne neue Liste anlegen und die Liste _student dann auf die neue Liste verbiegen, ohne direkt mit einem Zeiger auf eine Liste zu arbeiten, da ich sonst wieder alle Methoden ändern muss, also ein Workarround, nicht schön, aber soll nur funktionieren.

    @simon
    Ne, ich verwende die Variable an sich nicht direkt. Die Variable befindet sich halt im Kurs und wird später über eine andere Methoden und mithilfe des Id arrays wieder befüllt. Deswegen sollte die Liste _studenten im Objekt kurs überschrieben werden.

    MfG
    NiBurhe



  • NiBurhe schrieb:

    Das mit dem Namespace std stammt so eins zu eins aus der Vorlesung 😉

    Dann hau deinen Prof 😃

    Das muss nicht schön sein, es muss erstmal nur funktionieren, dumme unbenotete Testate.

    Das mag sein, trotzdem wirst du hier immer wieder
    Schoenheitstipps bekommen, denn schoen bedeutet lesbar, leicht wartbar und vor allem schnell verstaendlich. Und wer gleich von Anfang an schoenen (= lesbaren, wartbaren,...) Stil praktiziert, quaelt spaeter sich (und uns) nicht mit grausamem hack&slay-Code 😉

    Das Speichern und auslesen an sich funktioniert, das Objekt sieht im Debugger richtig aus. Nur die Liste _studenten macht Probleme, sie scheint zwar im Debugger eine leere Liste zu sein, sobald man aber auf die Liste zugreifen will, schiesst er sich ab. Daher wollte ich die Liste _studenten, die mit ausgelesen wurde, mit einer neuen Liste überschreiben, da ich ja nur eine leere Liste brauche. Er scheint halt eine Speicheradresse für die Liste zu speichern, aber wenn es wieder ausliest ist diese Speicheradresse nicht mehr gültig, deswegen wollte ich ne neue Liste anlegen und die Liste _student dann auf die neue Liste verbiegen, ohne direkt mit einem Zeiger auf eine Liste zu arbeiten, da ich sonst wieder alle Methoden ändern muss, also ein Workarround, nicht schön, aber soll nur funktionieren.

    Das Listenobjekt das du in deinem Kurs-Objekt hast, verwaltet intern seine Insassen mit Pointern. Die werden natuerlich ungueltig, sobald du das Objekt abspeicherst. Auch deshalb int das bitweise kopieren von Objekten aus dem Speicher in Dateien wirklich sehr, sehr, sehr, sehr unschoen. Mich wundert eh, dass das bisher bei dir funktioniert hat, schliesslich scheinen die Studenten-Objekte auch entweder const char* oder std::string-Member zu besitzen, die auch intern pointer besitzen, weshalb das bitweise Abspeichern und Auslesen in der Datei schiefegehn sollte (es sei denn du benutzt in student char-Arrays fester Laenge, was wiederum auch ein no-go in C++ ist).

    Zeig uns doch mal den restlichen Code, also die Methoden von Kurs. Denn irgendwie scheinst du ja auf die Innereien von Kurs-Objekten Einfluss nehmen zu koennen.

    Noch zwei Anmerkugnen:

    1. Die Liste die du beim Auslesen der Datei benutzt und die Liste _studenten in deiner Kurs-Klasse haben verschiedenen Typ. Die eine speichert studenten, die andere pointer auf studenten!
    2. vermeide fuehrende Unterstriche bei Variablennamen (z.B. _studenten, _Dozent etc.) einige Bezeichner mit fuehrenden Unterstrichen (und auch mit doppelten Untestrichen innerhalb des Namens) sind fuer die Compiler reserviert. Daher ist es besser, sich fuehrende Unterstriche von vornherein grundsaetzlich abzugewoehnen, bevor man irgendwann Stunden damit verbringt, einen subtilen Bug zu finden, der entstehen kann, wenn z.B. ein Compiler ein Makro definiert hat das man unbewusst benutzt hat.

Anmelden zum Antworten