STL-Listen in Datei schreiben



  • So natürlich nicht, für Listen müsstest du durchiterieren.
    Schau mal hier: http://www.boost.org/libs/serialization/doc/index.html



  • Hallo,

    Vielleicht zeigst du uns mal etwas Code. Insbesondere die Deklaration der Klasse, die du speichern möchtest.
    Prinzipiell ist es natürlich so, dass write einfach nur die Inhalte aller Variablen rausschreibt (so eine Art flache Kopie). Du mußt dir hier eine eigene write-Funktion (als Member deiner Klasse) schreiben, die auch die Inhalte der dynamisch verwalteten Membervariablen mit rausschreibt.



  • Das ist die Deklaration einer Klasse, die in der Liste gespeichert wird.
    Die andere Klasse ist ähnlich.

    #include<string>
    
    using std::string;
    
    class BombLaunch
    {
    public:
            BombLaunch()
            {}
            ~BombLaunch()
            {}
            void setBombId(string);
            void setBombLaunchTime(unsigned int);
            void setBombLaunchGroup(unsigned int);
            void setBombLaunchSlot(unsigned int);
            string getBombId();
            unsigned int getBombLaunchTime();
            unsigned int getBombLaunchGroup();
            unsigned int getBombLaunchSlot();
    
    private:
            string BombId;
            unsigned int BombLaunchTime;
            unsigned int BombLaunchGroup;
            unsigned int BombLaunchSlot;
    };
    

    Das ist ein Teil der Deklaration meiner Projektklasse:

    typedef list<BombLaunch> BombLaunchList;
    
    class Project
    {
    public:
    	Project(string FileName)
    	{
    		BombList=new BombLaunchList;
    	}
            ~Project()
            {
    		delete BombList;
    	}
    ...
    private:
    	BombLaunchList* BombList
    	BombLaunchList::iterator BombIter;
    ...
    

    Die STL-Liste BombList gilt es zu speichern und auch wieder zu laden.

    Die Funktion

    Status Project::FileAccess(Action _Action,string _FileName)
    

    wird vom Hauptprogramm aufgerufen, um das Speichern oder Laden einzuleiten.
    Action ist ein Aufzählungstyp, der über Erfolg oder Fehlschlag informiert.
    Das Hauptprogramm bekommt durch die Methode getBombs() einen Zeiger auf die
    Liste, was auch wunderbar funktioniert.



  • Wo liegt genau das Problem ???
    Einfach die Liste durchlaufen und "string BombID" in ne Datei schreiben...

    Mehr hast du ja nicht zum speichern.
    Oder operator<< überladen und es so wie in der FAQ machen 😉

    Edit: Sry habe die ganzen uint's übersehen die natürlich auch 😃



  • Ich wollte die Liste am Stück speichern, aber das scheint ja nur mit Vectoren
    zu gehen.
    Das Problem ist hauptsächlich, dass ich beim Laden nicht bis eof lesen kann,
    da noch eine zweite Liste ins gleiche File soll.
    Ok, ich könnte vor dem schreiben der eigentlichen Liste jeweils den Wert
    von size() voranstellen, dass ich weiss, wie weit ich lesen muss.
    In dem Fall wäre es wahrscheinlich besser, die Datei binär zu schreiben.
    Dann sieht man das ganze Durcheinander nicht mehr 🙄
    Also dann praktisch so:

    fstream ProjectFile;
    ProjectFile.open(_FileName.c_str(),ios_base::out);
    ProjectFile<<BombList->size()<<"\n"; //Optional
    for(BombIter=BombList->begin();BombIter!=BombList->end();BombIter++)
    {
    ProjectFile<<BombIter->getBombId()<<"\n";
    ProjectFile<<BombIter->getBombLaunchTime()<<"\n";
    ProjectFile<<BombIter->getBombLaunchGroup()<<"\n";
    ProjectFile<<BombIter->getBombLaunchSlot()<<"\n";
    }
    ProjectFile.close();
    

    Dann zum Lesen:

    BombList->clear();
    ProjectFile.open(_FileName.c_str(),ios_base::in);
    ProjectFile>>int size;
    for(int i=1;i!=size;i++)
    {
    //Dann die entsprechenden Typen einlesen und mit meiner add-Methode wieder
    zur Liste hinzufügen
    }
    

    Oder geht das irgendwie besser?



  • Ich hab's grad probiert, speichern geht zumindest.
    Jetzt mal laden probieren.



  • string tempBombId;
    	unsigned int tempBombLaunchTime,tempBombLaunchGroup,tempBombLaunchSlot,size;
    
    	//If LOAD_PROJECT is selected for action
    	if(_Action==LOAD)
    	{
    		//Open projectfile
    		ProjectFile.open(_FileName.c_str(),ios_base::in);
    		if(!ProjectFile)
    		{
    			return LOAD_ERROR;
    		}
    
    		//Read data from projectfile and write it to the musiclist and bomblist
    		BombList->clear();
    		ProjectFile>>size;
    		for(int i=1;i!=size;i++) 
    		{
    			ProjectFile>>tempBombId>>tempBombLaunchTime>>tempBombLaunchGroup>>tempBombLaunchSlot;
    			editBombs(ADD,tempBombId,tempBombLaunchTime,tempBombLaunchGroup,tempBombLaunchSlot,i,0);
    		}
    
    		ProjectFile.close();
    

    So hab ich jetzt das Laden realisiert. Jedoch wird nur 1 Eintrag gelesen,
    obwohl ich zum Test 2 drin hab.
    size wird mit 2 ausgelesen.
    Die editBombs-Methode wird also nur 1 mal ausgeführt.



  • mase schrieb:

    Ich wollte die Liste am Stück speichern, aber das scheint ja nur mit Vectoren
    zu gehen.File

    Meinst du mit am Stück weil da nur ein Zeile mit copy steht ???
    Das könntest du auch machen, nur müsstest du dafür op<< überladen, aber das ist ja egal, lerns erstmal zu Fuß...

    mase schrieb:

    Das Problem ist hauptsächlich, dass ich beim Laden nicht bis eof lesen kann,
    da noch eine zweite Liste ins gleiche File soll.
    Ok, ich könnte vor dem schreiben der eigentlichen Liste jeweils den Wert
    von size() voranstellen, dass ich weiss, wie weit ich lesen muss.

    Suche dir nen eigenes Makierungszeichen und lese immer bis dahin, bzw mit deinem size.

    Dein Laden muss ungefähr so aussehen. Du brauchst zwei Schleifen, eine für die ganze Datei und eine für die einzelnen Listen dadrin.

    while(!ProjectFile.eof() && !ProjectFile.fail())
    {
          int size;
          ProjectFile >> size;
    
          for(int i=0;i<size && !ProjectFile.fail();++i)
          {
              if((ProjectFile>>tempBombId) && (ProjectFile>>tempBombLaunchTime)
                 && (ProjectFile >>tempBombLaunchGroup) && (ProjectFile>>tempBombLaunchSlot))
                                        edit(...);       
          }  
    }
    
    // Prüfen ob alles ohne Fehler gelesen wurde
    

    Das:

    for(BombIter=BombList->begin();BombIter!=BombList->end();BombIter++)
    {
    ProjectFile<<BombIter->getBombId()<<"\n";
    ProjectFile<<BombIter->getBombLaunchTime()<<"\n";
    ProjectFile<<BombIter->getBombLaunchGroup()<<"\n";
    ProjectFile<<BombIter->getBombLaunchSlot()<<"\n";
    }
    

    Sollte dann demensprechend so aussehen:

    for(BombIter=BombList->begin();BombIter!=BombList->end();++BombIter)
    {
    ProjectFile <<BombIter->getBombId() << " " <<BombIter->getBombLaunchTime()
    <<" " <<BombIter->getBombLaunchGroup() <<" "
    <<" " <<BombIter->getBombLaunchSlot() <<endl;
    }
    

    Jedoch wird nur 1 Eintrag gelesen,
    obwohl ich zum Test 2 drin hab.
    size wird mit 2 ausgelesen.
    Die editBombs-Methode wird also nur 1 mal ausgeführt.

    Schau dir mal den Kopf der Schleife genau an und gehe mal den Wert von size und i im Kopf durch 😉



  • Steh ich jetzt auf'm Schlauch?
    size ist im Testfall 2.
    Solange i ungleich 2 ist, wird die Schleife weiter durchlaufen.
    Au sch...
    Du hast recht!

    for(unsigned int i=0;i!=size;i++)
    		{
    			ProjectFile>>tempBombId>>tempBombLaunchTime>>tempBombLaunchGroup>>tempBombLaunchSlot;
    			editBombs(ADD,tempBombId,tempBombLaunchTime,tempBombLaunchGroup,tempBombLaunchSlot,i+1,0);
    		}
    

    So geht's!



  • Ein kleines Problem hab ich noch.
    Eine Variable eines gespeicherten Objekts in der Liste ist ein Aufzählungstyp:

    enum Gap {NONE,FADE,CROSSFADE};
    

    Den Typ Gap kann ich in die Datei schreiben.
    Doch auslesen als Gap geht nicht. Da hab ich den Umweg gewählt, Gap als unsigned int
    in eine temporäre Variable auszulesen und mit

    switch(tempGap)
    			{
    				case 0:MusicGap=NONE;break;
    				case 1:MusicGap=FADE;break;
    				case 2:MusicGap=CROSSFADE;break;
    			}
    

    der eigentlichen Variablen vom Typ Gap zuzuweisen.
    Vielleicht nicht so ganz elegant, aber es geht.



  • MusicGap = static_cast<Gap>(tempGap);
    

    reicht hier auch. Da brauchst du kein switch.
    Wieso eigentlich unsigned int?



  • Ja, das mit dem static_cast hat auch funktioniert.
    Bei den Operatoren zur Typenumwandlung bin ich noch nicht angelangt 😃
    Warum unsigned int? Ok, int hätte gereicht.
    Aber ich hab mir irgendwie angewöhnt, integer, die nur positiv sein können,
    als unsigned zu deklarieren.


Anmelden zum Antworten