Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

Quin

Frischling

  • »Quin« ist der Autor dieses Themas

Beiträge: 23

Wohnort: Engelthal

  • Private Nachricht senden

1

11.08.2010, 15:35

Problem beim schreiben und auslesen von Daten

Hallo,

ich hab ein Problem mit list und ofstream/ifstream. Ich möchte eine Liste von Spielern in eine Datei speichern und wieder in die Liste laden, aber das Programm stürzt ab, wenn die Daten aus der Liste gelöscht werden und neu geladen werden sollen. Wenn die Daten aus der Liste nicht gelöscht werden geht es aber. ?(

Kann mir da jemand weiterhelfen?


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include 
#include 
#include 
#include 

using namespace std; 

class CRaumschiff 
{ 
public: 
string Name; 
int Energie; 
int Farbe; 
int Team; 
float Geschwindigkeit; 
}; 

int main() 
{ 
list lSpieler; 
list::iterator iSpieler; 

CRaumschiff Spieler1; // Raumschiff von Spieler 1 
CRaumschiff Spieler2; // Raumschiff von Spieler 2 

// Startwerte für Spieler 1 festlegen 
Spieler1.Name = "Hans"; 
Spieler1.Energie = 1000; 
Spieler1.Farbe = 3; 
Spieler1.Team = 1; 
Spieler1.Geschwindigkeit = 250.35f; 
// Daten am Ende der Liste schreiben 
lSpieler.push_back(Spieler1); 

// Startwerte für Spieler 1 festlegen 
Spieler2.Name = "Peter"; 
Spieler2.Energie = 1000; 
Spieler2.Farbe = 2; 
Spieler2.Team = 2; 
Spieler2.Geschwindigkeit = 190.85f; 
// Daten am Ende der Liste schreiben 
lSpieler.push_back(Spieler2); 

// Datei zum Schreiben öffnen 
ofstream Output("Spielstand.sps", ios::binary); 

if(!Output) 
{ 
cout << "Datei konnte nicht geoeffnet werden." << endl; 
system("pause"); 
return -1; 
} 


// Instanz in die Datei schreiben 
for (iSpieler = lSpieler.begin(); iSpieler != lSpieler.end(); ++iSpieler) 
{ 
Output.write((char*) &(*iSpieler), sizeof(CRaumschiff)); 
} 

// Datei schliessen 
Output.close(); 

// Dateien der Liste wieder löschen 

lSpieler.clear(); 

// Datei zum Lesen öffnen 
ifstream Input("Spielstand.sps", ios::binary); 

if(!Input) 
{ 
cout << "Datei konnte nicht geoeffnet werden." << endl; 
system("pause"); 
return -1; 
} 

// Instanz aus der Datei lesen 
iSpieler = lSpieler.begin(); 
for (size_t i = 0; i < 2; ++i, ++iSpieler) 
{ 
CRaumschiff Temp; 
lSpieler.push_back(Temp); 
Input.read((char*) &(*iSpieler), sizeof(CRaumschiff)); 
} 

// Werte ausgeben 
for (iSpieler = lSpieler.begin(); iSpieler != lSpieler.end(); ++iSpieler) 
{ 
cout << "Name : " << iSpieler->Name << endl 
<< "Energie : " << iSpieler->Energie << endl 
<< "Farbe : " << iSpieler->Farbe << endl 
<< "Team : " << iSpieler->Team << endl 
<< "Geschwindigkeit : " << iSpieler->Geschwindigkeit << endl << endl; 
} 

// Datei schliessen 
Input.close(); 

system("pause"); 
return 0; 
}

Harry222

Alter Hase

Beiträge: 864

Beruf: Student

  • Private Nachricht senden

2

11.08.2010, 15:42

Kannst du mal bitte Einschübe einbauen. So ist das meiner Meinung nach echt schwer lesbar!
Am besten ungefähr so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
main(){
   int i = 0;
   if(i = 0){
      return 0;
   }
   else{
      return 1;
   }
}


MFG Harry222

3

11.08.2010, 15:43

Hey,

den Fehler hab ich am Anfang auch gemacht ... Ich hab damals ne Multimap verwendet. Hier der Link.

Du kannst keine Liste in eine Datei schreiben. Du musst die einzelnen Elemente in die Datei schreiben und beim einlesen die Liste neu erstellen.
Also musst du die Elemente "Energie", "Farbe", "Name", etc. speichern und diese dann eben einlesen.

Hoffe, der Thread von mir hillft dir weiter.

Liebe Güße!

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

4

11.08.2010, 16:05

neenee das müsste schon funktionieren. das problem liegt in zeile 83 und 84

C-/C++-Quelltext

1
2
lSpieler.push_back(Temp); 
Input.read((char*) &(*iSpieler), sizeof(CRaumschiff));


lösung:

C-/C++-Quelltext

1
2
Input.read((char*) &Temp, sizeof(CRaumschiff)); 
lSpieler.push_back(Temp);


natürlich nicht getestet. müsste aber gehen.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Quin

Frischling

  • »Quin« ist der Autor dieses Themas

Beiträge: 23

Wohnort: Engelthal

  • Private Nachricht senden

5

11.08.2010, 18:34

C-/C++-Quelltext

1
Input.read((char*) &(*iSpieler), sizeof(CRaumschiff));


Ich glaub so müsste es schon richtig sein, weil wenn ich

C-/C++-Quelltext

1
lSpieler.clear();


rauslasse hab ich keinen Fehler, wenn ich es aber in eine andere Liste aus der Datei einlesen will geht es aber wieder nicht.

So auf Wunsch nochmal den Code etwas in abgeänderter Form (ohne lSpieler.clear)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <iostream>
#include <string>
#include <fstream>
#include <list>

using namespace std;

class CRaumschiff
{
    public:
        string Name;
        int Energie;
        int Farbe;
        int Team;
        float Geschwindigkeit;
};

int main()
{
    list<CRaumschiff> lSpieler;
    list<CRaumschiff>::iterator iSpieler;
    
    CRaumschiff Spieler1; // Raumschiff von Spieler 1 
    CRaumschiff Spieler2; // Raumschiff von Spieler 2 

    // Startwerte für Spieler 1 festlegen
    Spieler1.Name = "Hans";
    Spieler1.Energie = 1000;
    Spieler1.Farbe = 3;
    Spieler1.Team = 1;
    Spieler1.Geschwindigkeit = 250.35f;
    // Daten am Ende der Liste schreiben
    lSpieler.push_back(Spieler1);

    // Startwerte für Spieler 1 festlegen
    Spieler2.Name = "Peter";
    Spieler2.Energie = 1000;
    Spieler2.Farbe = 2;
    Spieler2.Team = 2;
    Spieler2.Geschwindigkeit = 190.85f;
    // Daten am Ende der Liste schreiben
    lSpieler.push_back(Spieler2);

    // Datei zum Schreiben öffnen
    ofstream Output("Spielstand.sps", ios::binary);

    if(!Output)
    {
        cout << "Datei konnte nicht geoeffnet werden." << endl;
        system("pause");
        return -1;
    }
    

    // Instanz in die Datei schreiben
    for (iSpieler = lSpieler.begin(); iSpieler != lSpieler.end(); ++iSpieler)
    {
        Output.write((char*) &(*iSpieler), sizeof(CRaumschiff));
    }

    // Datei schliessen
    Output.close();

    // Dateien der Liste wieder löschen
    
    //lSpieler.clear();

    for (iSpieler = lSpieler.begin(); iSpieler != lSpieler.end(); ++iSpieler)
    {
        iSpieler->Name = "";
        iSpieler->Energie = 0;
        iSpieler->Farbe = 0;
        iSpieler->Team = 0;
        iSpieler->Geschwindigkeit = 0;
    }
    
    // Datei zum Lesen öffnen
    ifstream Input("Spielstand.sps", ios::binary);

    if(!Input)
    {
        cout << "Datei konnte nicht geoeffnet werden." << endl;
        system("pause");
        return -1;
    }
    
    // Instanz aus der Datei lesen
    iSpieler = lSpieler.begin();
    for (size_t i = 0; i < 2; ++i, ++iSpieler)
    {
        CRaumschiff Temp;
        lSpieler.push_back(Temp);
        Input.read((char*) &(*iSpieler), sizeof(CRaumschiff));
        
    }

    // Werte ausgeben
    for (iSpieler = lSpieler.begin(); iSpieler != lSpieler.end(); ++iSpieler)
    {
        cout << "Name            : " << iSpieler->Name << endl
             << "Energie         : " << iSpieler->Energie << endl
             << "Farbe           : " << iSpieler->Farbe << endl
             << "Team            : " << iSpieler->Team << endl
             << "Geschwindigkeit : " << iSpieler->Geschwindigkeit << endl << endl;
    }
    
    // Datei schliessen
    Input.close();
    
    system("pause");
    return 0;
}

Harry222

Alter Hase

Beiträge: 864

Beruf: Student

  • Private Nachricht senden

6

11.08.2010, 18:43

Ah, schon viel besser! :D
TIPP: Hättest eigentlich nur deine alte Nachricht ändern müssen! ;)

Aber leider muss ich dir sagen, dass ich dir dabei nicht helfen kann, weil ich immer mit fopen & Co. gearbeitet habe!
Sorry!

MFG Harry222

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

7

11.08.2010, 18:44

hast du es denn ausprobiert? wenn nicht hast du wohl keine hilfe verdient.
wenn du schon clear weg lässt darfst du nicht pushback verwenden, die schleife verlassen wenn iSpieler != lSpieler.end(). ausserdem brauchst du dann die temporäre instanz vom spieler beim einlesen nicht.(ist natürlich alles ein bisschen gefährlich...)

achja... der spieler enthält einen string.(hab ich vorhin wohl übersehen) den musst du natürlich anders speichern.(siehe Ombalats post) am besten kommentierst du ihn erstmal aus und probierst nochmal obs mit meinem vorschlag klappt.
am besten wär natürlich eine methode für die klasse die das macht. an deiner stelle würd ich das mit den datein erstmal lassen, da muss man ne menge beachten. schreib lieber nen taschenrechner der benutzereingaben entgegen nimmt oder so^^
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »NachoMan« (11.08.2010, 18:52)


BurningWave

Alter Hase

Beiträge: 1 106

Wohnort: Filderstadt/Konstanz

Beruf: Student

  • Private Nachricht senden

8

11.08.2010, 19:12

Ich habe für mein aktuelles Projekt eine Klasse geschrieben, mit der sich kinderleicht komlizerte Daten wie Strings und Listen speichern lassen. Ich benutze zwar auch fopen, fwrite,... das sollte sich aber leicht umschreiben lassen. Falls es dich interessiert, wie ich es gemacht habe: Hier ist der Code:

File.cpp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//---------------------------------------------------------------------------

#include "SDIMAIN.h"

#pragma package(smart_init)
//---------------------------------------------------------------------------

void CFile::write(AnsiString const &rsString)
{
    check();
    char acTmp[16];

    sprintf(acTmp, "%i", rsString.Length() * sizeof(char));
    if(!fwrite(acTmp, sizeof(acTmp), 1, m_pFile))
        throw xWriteErrorString();
    if(rsString.Length() == 0)
        return;
    if(!fwrite(rsString.c_str(), rsString.Length() * sizeof(char), 1, m_pFile))
        throw xWriteErrorString();
}
//---------------------------------------------------------------------------

void CFile::read(AnsiString *psString)
{
    check();
    char acTmp[16];

    if(!fread(acTmp, sizeof(acTmp), 1, m_pFile))
        throw xReadErrorString();
    if(atoi(acTmp) == 0)
        return;
    psString->SetLength(atoi(acTmp));
    if(!fread(psString->c_str(), atoi(acTmp), 1, m_pFile))
        throw xReadErrorString();
}
//---------------------------------------------------------------------------


File.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//---------------------------------------------------------------------------

#ifndef FileH
#define FileH

class CFile
{
public:
    //Funktionen
    CFile()             {m_pFile = NULL;}
    CFile(FILE *pFile)  {m_pFile = pFile;}
    ~CFile()            {m_pFile = NULL;}

    CFile       operator= (FILE *pFile) {m_pFile = pFile; return *this;}

    void        write(AnsiString const &rsString);
    template <class T>
    void        write(T const &rValue);
    template <class T>
    void        write(list<T> const &rList);
    void        read(AnsiString *psString);
    template <class T>
    void        read(T *pValue);
    template <class T>
    void        read(list<T> *pList);

    //Exception-Classes
    class xFileError {
        protected:
            const type_info *m_pType_Info;
        public:
            xFileError() : m_pType_Info(NULL) {}
            const char* DataType() {
                if(m_pType_Info)
                    return m_pType_Info->name();
                else
                    return "Unbekannter Datentyp";
            }
    };
    class xWriteError : public xFileError {
        public:
            xWriteError() {m_pType_Info = NULL;}
            xWriteError(type_info const *pType_Info) {m_pType_Info = pType_Info;}
    };
    class xWriteErrorString : public xWriteError {
        public:
            xWriteErrorString() {m_pType_Info = &typeid(AnsiString);}
    };
    class xWriteErrorList : public xWriteError {
        public:
            template <class T>
            xWriteErrorList(list<T> const rList) {m_pType_Info = &typeid(rList);}
    };
    class xReadError : public xFileError {
        public:
            xReadError() {m_pType_Info = NULL;}
            xReadError(type_info const *pType_Info) {m_pType_Info = pType_Info;}
    };
    class xReadErrorString : public xReadError {
        public:
            xReadErrorString() {m_pType_Info = &typeid(AnsiString);}
    };
    class xReadErrorList : public xReadError {
        public:
            template <class T>
            xReadErrorList(list<T> const rList) {m_pType_Info = &typeid(rList);}
    };

private:
    //Zeiger auf eine Datei, auf die sich die write()- und read()-Funktionen beziehen
    FILE        *m_pFile;

    //interne Funktion zum Überprüfen, ob m_pFile ein gültiger Zeiger ist
    void        check() {if(!m_pFile) err("Fatal Error: Ein ungültiges Dateihandle wurde übergeben", __FILE__, __LINE__, ERR_NULL_POINTER, GetForegroundWindow(), true);}
};
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

template <class T>
void CFile::write(T const &rValue)
{
    check();

    if(!fwrite(&rValue, sizeof(T), 1, m_pFile))
        throw xWriteError(&typeid(T));
}
//---------------------------------------------------------------------------

template <class T>
void CFile::write(list<T> const &rList)
{
    check();
    char acTmp[16];
    T ListEntry;

    sprintf(acTmp, "%i", rList.size() * sizeof(T));
    if(!fwrite(acTmp, sizeof(acTmp), 1, m_pFile))
        throw xWriteErrorList(rList);

    for(list<T>::const_iterator ci = rList.begin(); ci != rList.end(); ++ci)
    {
        ListEntry = *&*ci;
        if(!fwrite(&ListEntry, sizeof(T), 1, m_pFile))
            throw xWriteErrorList(rList);
    }
}
//---------------------------------------------------------------------------

template <class T>
void CFile::read(T *pValue)
{
    check();

    if(!fread(pValue, sizeof(T), 1, m_pFile))
        throw xReadError(&typeid(T));
}
//---------------------------------------------------------------------------

template <class T>
void CFile::read(list<T> *pList)
{
    check();
    char acTmp[16];
    T ListEntry;

    if(!fread(acTmp, sizeof(acTmp), 1, m_pFile))
        throw xReadErrorList(*pList);

    for(unsigned int i = 0; i < (atoi(acTmp) / sizeof(T)); i++)
    {
        if(!fread(&ListEntry, sizeof(T), 1, m_pFile))
            throw xReadErrorList(*pList);

        pList->push_back(ListEntry);
    }
}
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#endif


Beispiel (Schreiben)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Result CProject::WriteHeaderChunk()
{
    CFile File(m_pProjectFile);
    SChunkHeader tmpChunkHeader;
    tmpChunkHeader.Type = CT_HEADER_CHUNK;
    tmpChunkHeader.iSize = 0;

    try
    {
        File.write(tmpChunkHeader);

        File.write(m_HeaderChunk.iFileFormatVersion);
        File.write(m_HeaderChunk.iNumChunks);
        File.write(m_HeaderChunk.iYear);
        File.write(m_HeaderChunk.iTrackNumber);
        File.write(m_HeaderChunk.sProjectName);
        File.write(m_HeaderChunk.sTitle);
        File.write(m_HeaderChunk.sSubTitle);
        File.write(m_HeaderChunk.sAlbum);
        File.write(m_HeaderChunk.sInterpreters);
        File.write(m_HeaderChunk.sGenre);
        File.write(m_HeaderChunk.sCopyright);
        File.write(m_HeaderChunk.sComments);
    }
    catch(CFile::xWriteError &E) {
        char acTmp[256];
        sprintf(acTmp, "Exception xWriteError occurred:\nFehler beim Schreiben von \"%s\" in die Datei", E.DataType());
        return err(AnsiString(acTmp), __FILE__, __LINE__, ERR_FAILED, SDIAppForm->Handle);
    }
    catch(...) {
        return err("Exception ... occurred:\nUnbekannte Ausnahme", __FILE__, __LINE__, ERR_FAILED, SDIAppForm->Handle);
    }

    return ERR_OK;
}


Beispiel (Lesen):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Result CProject::ReadHeaderChunk()
{
    CFile File(m_pProjectFile);
    SChunkHeader tmpChunkHeader;

    try
    {
        File.read(&tmpChunkHeader);
        if(tmpChunkHeader.Type != CT_HEADER_CHUNK)
            throw CFile::xReadError(&typeid(tmpChunkHeader));

        File.read(&m_HeaderChunk.iFileFormatVersion);
        File.read(&m_HeaderChunk.iNumChunks);
        File.read(&m_HeaderChunk.iYear);
        File.read(&m_HeaderChunk.iTrackNumber);
        File.read(&m_HeaderChunk.sProjectName);
        File.read(&m_HeaderChunk.sTitle);
        File.read(&m_HeaderChunk.sSubTitle);
        File.read(&m_HeaderChunk.sAlbum);
        File.read(&m_HeaderChunk.sInterpreters);
        File.read(&m_HeaderChunk.sGenre);
        File.read(&m_HeaderChunk.sCopyright);
        File.read(&m_HeaderChunk.sComments);
    }
    catch(CFile::xReadError &E) {
        char acTmp[256];
        sprintf(acTmp, "Exception xReadError occurred:\nFehler beim Lesen von \"%s\" aus der Datei", E.DataType());
        return err(AnsiString(acTmp), __FILE__, __LINE__, ERR_FAILED, SDIAppForm->Handle);
    }
    catch(...) {
        return err("Exception ... occurred:\nUnbekannte Ausnahme", __FILE__, __LINE__, ERR_FAILED, SDIAppForm->Handle);
    }

    return ERR_OK;
}

jokester

Treue Seele

Beiträge: 125

Wohnort: Mainz

  • Private Nachricht senden

9

11.08.2010, 19:14

@NachoMan: Ob es einen string enthält oder nicht - das Verhalten von diesem read() ist undefiniert, wenn das Objekt kein POD ist. (Ist es nicht, weil es private Datenmember enthält.) (Edit: Oh, die Dinger sind ja nur public. Egal, das hier zählt trotzdem: ) Außerdem wird Alignment missachtet, das is also ziemlich unportabel.
Am besten überlädt man einfach operator<< und >> dafür, oder nutzt ein System wie boost.serialize.
"There is a theory which states that if ever anyone discovers exactly what the Universe is for and why it is here, it will instantly disappear and be replaced by something even more bizarre and inexplicable. There is another theory which states that this has already happened" -- Douglas Adams.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

10

11.08.2010, 19:44

das wollt ich ihm auch sagen. er scheint aber noch ziemlich wenig erfahrung zu haben weshalb ich ihm das erspart habe.
es ging erstmal nur darum, dass es funktioniert. ich hab ja in meinem vorherigen post geschrieben, dass es da für einen anfänger zu viel zu beachten gibt.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Werbeanzeige