STL-List: Probleme beim Laden von Objekten



  • Hallo zusammen,

    für mich ist C++ Neuland und deswegen schaffe ich es nicht, gespeicherte Objekte
    wieder in eine Liste zurück zu schreiben. Hier ist mein Ansatz samt Problem:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <list>
    using namespace std;
    
    class person {
    	string name;
    	long telnr;
    public:
    	person(const string& n = "X", long nr = 0L):name(n), telnr(nr){}
    
    	const string& getName() const {return name;}
    	void setName(const string& n) {name = n;}
    
    	void setTelefon(long z) {telnr = z;}
    	long getTelefon() {return telnr;}
    
    	ostream& write(ostream& os) const;
    	istream& read(istream& is);
    };
    
    ostream& person::write(ostream& os) const {
    	os << name << '\0';
    	os.write((char*)&telnr, sizeof(telnr));
    	return os;
    }
    
    istream& person::read(istream& is) {
    	getline(is, name, '\0');
    	is.read((char*)&telnr, sizeof(telnr));
    	return is;
    }
    
    int main()
    {
    	fstream datei;
    
    	long z;
    	string n;
    
    	list<person> liste;
    	list<person>::iterator pos;
    
    	for (int i = 0; i < 5; i++)	{
    		person i;
    		cin >> n >> z;
    		i.setName(n);
    		i.setTelefon(z);
    		liste.push_back(i);
    	}
    	datei.open("test.dat", ios::out | ios::binary);
    	for (pos = liste.begin(); pos != liste.end(); ++pos)
    		pos->write(datei);
    	datei.close();
    	liste.clear();
    	datei.open("test.dat", ios::binary);
    
    	// ab hier bin ich völlig ratlos!
    	for (pos = liste.begin(); pos != liste.end(); ++pos) {
    		person p;
    		pos->read(datei);
    		p.setName(pos);
    		p.setTelefon(pos);
    		liste.push_back(pos);
    		// Kontrollausgabe
    		cout << pos->getName() << ": " << pos->getTelefon() << endl;
    	}
    	return 0;
    }
    

    Wie schreibe ich die Daten in die leere Liste und gebe sie zur Kontrolle aus? 😕
    Vielen Dank!
    newbi3



  • Hallo,

    schau mal im FAQ nach:
    http://www.c-plusplus.net/forum/viewtopic.php?t=39469

    Das erste Beispiel liest eine Datei zeilenweise ein und speichert
    jede Zeile in einem string-Vector. Als letztes wird der Inhalt des
    Vektors (und damit der Inhalt der Datei) nach cout geschrieben.
    Benötigte Header: <iostream>, <fstream>, <vector>, <string> und <iterator>

    using namespace std; 
    ifstream FileIn("Main.cpp"); 
    if (FileIn)     // Falls FileIn gültig ist. 
    { 
        vector<string> Contents;              // Container für die einzelnen Zeilen 
    
        // Solange kein Fehler auftritt und nicht eof 
        for (string ReadString; getline(FileIn, ReadString); )         
            Contents.push_back(ReadString);   // Aktuelle Zeile in den Vektor einfügen 
    
        // Alle Elemente des Vektors ausgeben. 
        ostream_iterator<string> Out(cout, "\n"); 
        copy(Contents.begin(), Contents.end(), Out); 
    }
    

    So ähnlich dürfte es auch bei dir funktionieren..

    MfG



  • Ich habe auch noch eine Frage..

    In C++ wird die Ein- und Ausgabe über sogenannte Ströme (engl. Streams)
    realisiert.

    Ich habe schon öfters Beiträge gelesen, in denen es um Ströme geht.
    Mich interessiert warum Dateien nicht über fopen, fread, fclose eingelesen/bearbeitet werden. (Zumindest haben wir das früher mal so gemacht) Ist das jetzt out?

    Merci



  • ja, es ist out, man hat jetzt die tollen streamklassen, die wirklich alles tun, was man bisher mit 20 verschiedenen funktionen machen musste^^



  • Danke für die Mithilfe, aber das brachte mich noch nicht weiter.
    Ich weiss eben nicht, was ich alles beim Laden falsch angehe.

    for (pos = liste.begin(); pos != liste.end(); ++pos) {
    	pos->read(datei);   // Macht das so überhaupt Sinn ??? 
    	person p;	
    	p.setName();	    // Wie übergebe ich den Wert ...
    	p.setTelefon();	 // ... setName(n) oder setName(pos) ???
    	liste.push_back(p); // Landet damit das Objekt in der Liste?
    	cout << p.getName() << ": " << p.getTelefon() << endl;
    }
    


  • Hm, so ein paar Dinge, die mir auffallen:

    Dein Programm führt den Rumpf der for-Schleife niemals aus. Schliesslich löschst Du die Liste vorher, es sind also keine Elemente mehr vorhanden, durch die Du mit dem Iterator durchlaufen könntest.

    Den Teil innerhalb der for-Schleife kann ich auch nciht so ganz nachvollziehen. Warum durchläufst Du die Liste (mal davon ausgegangen, dass sie nicht leer ist) und füllst die Objekte der Liste mit den Werten aus der Datei, um dann ein neues Objekt zu erstellen, das mit den Werten, die schon in der Liste stehen, zu füllen und dieses dann an die Liste anzuhängen?

    Und setName() musst Du das übergeben, was die Funktion erwartet, in diesem Fall also einen String, und nicht einen Iterator oder so.



  • Mir ist aufgefallen, dass das Speichern und Laden von nur einem Objekt funktioniert.
    Sobald die ganze Liste gespeichert wurde, klappt das Laden nicht mehr.

    Hier ist die Methode zum Speichern der Objektdaten:

    ostream& person::write(ostream& os) const {
        os << name << '\0';
        os.write((char*)&telnr, sizeof(telnr));
        return os;
    }
    

    Hier ist Methode zum Laden der Objektdaten:

    istream& person::read(istream& is) {
        getline(is, name, '\0');
        is.read((char*)&telnr, sizeof(telnr));
        return is;
    }
    

    So speichere ich die Liste mit den Objekten ab:

    list<person> liste;
    list<person>::iterator pos;
    for (pos = liste.begin(); pos != liste.end(); ++pos)
    	pos->write(datei);
    

    Damit habe ich doch die Objekte in entsprechender Reihenfolge gespeichert.

    Wenn ich die Objekte später wieder in eine Liste einlesen möchte,
    muss ich doch die o.a. Methode zum Laden verwenden... Somit meine Fragen:

    1. Wie lade ich am sinnvollsten die gespeicherten Daten?
    2. Wie erzeuge ich mit den geladenen Daten neue Objekte?

    Es tut mir leid, aber ich komme einfach nicht weiter. 😕



  • Wenn das Objekt seine Daten über eine Methode selbst lädt, warum willst Du diese Daten dann noch in eine neues packen? Damit brauchst doch doch im Prinzip zwei Objekte, um am Ende eins mit Werten zu füllen.

    Deshalb lade doch einfach die Daten in die Objekte, und fertig ist es.

    Ersetze den ab-hier-bin-ich-ratlos-Teil durch das, dann gehts:

    person p;
    while(p.read(datei))
    {
        liste.push_back(p);
        cout << p.getName() << " " << p.getTelefon() << endl;
    }
    

    So funktioniert es jedenfalls bei mir.



  • Hurra es funktioniert!!! 😃

    @Asgard:
    VIELEN, VIELEN DANK! 🤡


Anmelden zum Antworten