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

1

22.12.2011, 17:53

Problem mit fstreams

Hallo Miteinander,

Ich habe ein Problem mit der Datenspeicherung über fstream. Ich komme wirklich nicht mehr weiter und habe auch schon einiges versucht (z.b. Debugger). Also es geht immer noch um das textbasierte Strategiespiel aus meinem letzten Thread. Das Spiel selbst funktioniert, aber als ich eine neue Funktion (Autospeichern) etablieren wollte, bin ich an die Grenze meiner Kenntnisse über streams gestoßen (was nicht viel heissen will). Die Idee ist folgende: Ich habe acht durchnummerierte Flotten, die ich mittels eines Arrays aus der Klasse CFleet erzeugt habe. Nun möchte ich die Werte jeder Flotte in einen eigens erzeugten Ordner schreiben. Eine Datei pro Flotte. Dazu kopiere ich die Werte jeder Flotte in eine normal erzeugt Klasse und speichere diese dann in einem Dateipfad, der über ein char Array pro Datei variiert. Zum Auslesen mache ich das gleiche nur mit ifstream, aber ich zeige eeinfach mal den Code...

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
void CRun::SaveGame () 
{ 
_mkdir ("./Saves"); 
_mkdir ("./Saves/SOL"); 
_mkdir ("./Saves/INV"); 
CFleet CSave; 

// Flotten speichern: 
for ( int p = 0; p<LVL ; p++ ) 
{ 
CSave.LocNum = p ; 
CSave.activated = pFleet[p+1].activated ; 
CSave.AdmEP = pFleet[p+1].AdmEP ; 
CSave.Admiral = pFleet[p+1].Admiral ; 
CSave.friendly = pFleet[p+1].friendly ; 
CSave.Loc = pFleet[p+1].Loc ; 
CSave.CurrIntegrity = pFleet[p+1].CurrIntegrity; 
CSave.CountCruiser = pFleet[p+1].CountCruiser ; 
CSave.CountFrigate = pFleet[p+1].CountFrigate ; 
CSave.CountSShips = pFleet[p+1].CountSShips ; 

SaveFile ( p, CSave); 
} 
} 
void CRun::SaveFile (int FNum, CFleet CSave) 
{ 
char data[20] = "./Saves/xxx/Flx.txt"; 
if ( LvlName == "Sol") 
{ 
data[8] = 'S'; 
data[9] = 'O'; 
data[10] = 'L'; 
} 

data[14] = FNum + 48; 
remove (data); 
ofstream OSave (data, ios::binary); 
OSave.write ((char*) &CSave, sizeof (CSave)); 
OSave.close (); 

} 
void CRun::LoadGame (int LvlNum) 
{ 
CFleet CSave; 
char data[19] = "/Saves/xxx/Flx.sfs"; 
if ( LvlNum == 1 ) 
{ 
data[7] = 'S'; 
data[8] = 'O'; 
data[9] = 'L'; 
plvlsize = new int; 
LVL = 8; 
pRound = new int; 
*pRound = 1; 
plvllength = new int; 
*plvllength = 15; 
InitSolSystem (); 
pFleet = NULL; 
pFleet = new CFleet[9]; 
InitPlayer (); 
pPlayer->SetPlayer (LvlNum); 
} 
for ( int z = 1; z<=LVL ; z++ ) 
{ 
data[13] = z - 1 + 48; 
ifstream ILoad (data, ios::binary); 
ILoad.read ((char *) &CSave, sizeof (CSave)); 
if ( ILoad == NULL ) 
{ 
cout << " Fehler beim Lesen!"<<endl; 
cout << data<<endl; 
AnyKey = getch (); 
} 
CSave.Loc = pPlanet[z].PlanetName; 
pFleet[z].InitFleet (CSave.CountCruiser, CSave.CountFrigate, CSave.CountSShips, CSave.Admiral, CSave.AdmEP, 
CSave.Loc, CSave.friendly, CSave.LocNum, CSave.activated); 
pFleet[z].CurrIntegrity = CSave.CurrIntegrity; 
ILoad.close (); 
} 
}


... Also beim Laden wird bloß die Datei ausgelesen und per InitFleet in die jeweilige Flotte geschrieben. Ich hätte mir den Fehler ja anhand der Ausgabe überlegen können, aber der Compiler gibt auch eine Fehlermeldung aus. Manchmal wird zwar nur angezeigt, dass das programm nicht funktioniert, aber normalerweise kommt das, was ich in dem Dateianhang gespeichert habe. Ich habe (glaube ich) alle Regeln aus dem Buch befolgt, aber dieses Thema ist dort leider nur recht kurz angeschnitten. Ich bedanke mich schon mal im Voraus für konstruktive Hilfe, frohe Wheinachten!
»Prime« hat folgendes Bild angehängt:
  • ERROR.jpg

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

22.12.2011, 18:00

Oioio, da geht aber einiges durcheinander. Zunächst mal solltest Du die Werte nicht in einer neue Instanz kopieren, das ist absolut überflüssig. Zweitens solltest Du nicht einfach eine Klasse über ihre Referenz in eine Datei schreiben, da landet doch lauter Quatsch in der Datei. Genau da liegt auch das Problem des Ladens wieder.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

3

22.12.2011, 18:16

Welche Referenz? Ich habe CSave eigens, temporär für die jeweilige Funktion erschaffen. Dann ist das doch keine Referenz, oder meinst du ich sollte sie nicht als Parameter übergeben? Außerdem ist pFleet ein Pointer den ich für die new Funktion verwendet habe, deshalb denke ich nicht, dass ich ihne direkt speichern kann... oder?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

22.12.2011, 18:21

Referenz auf Speicher:
OSave.write ((char*) &CSave, sizeof (CSave));
Du solltest nicht einen Pointer auf eine Instanz an write() oder
load() übergeben, da kommt nur Quatsch bei rum, wie Du ja siehst.

Du solltest nicht CSave erstellen, sondern direkt pFleet[x] an die SaveGame Methode übergeben.

Du kannst auch direkt in pFleet[x] reinspeichern. Wäre ja grauenhaft, wenn nicht.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

5

22.12.2011, 18:27

Ok, aber was übergebe ich anstatt eines Zeigers?? In dem Lehrbuch von dieser Seite C++ für Spieleprogrammierer wird gesagt, dass man der write Funktion im ersten Parameter einen char Zeiger übergeben muss (und auch bei read). Könntest du mir bitte schreiben, was ich stattdessen machen müsste. Danke übrigens für die schnellen Antworten!

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

22.12.2011, 18:29

Also ich würde jeden Member einzeln übergeben. Das hat "diverse" Vorteile. ;)
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

7

22.12.2011, 18:33

Ich bin mir nicht ganz sicher was du meinst, da in dem Buch immer nur char zeiger übergeben werden soll ich dann als ersten Parameter die Klasse direkt übergeben?? Was hätte das für Vorteile?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

22.12.2011, 18:39

Nein, Du sollst eben nicht die Klasse übergeben (an write)(man übergibt übrigens Instanzen und keine Klassen), sondern nur die Member. Das hat den Vorteil, dass Du weder den Speicher an Stellen liest oder beschreibst, wo Du es nicht sollst, Du kannst selektiv auswählen, was überhaupt wirklich gespeichert werden muss und nicht zuletzt kannst Du nur damit Referenz-Member korrekt speichern, weil Du sonst nämlich nur Adressen in die Datei schreibst.

An "SaveFile" sollst Du aber direkt die Eintrage aus pFleet übergeben, statt erst alles unnötig in eine lokale Variable zu kopieren und dann die zu übergeben.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

9

22.12.2011, 18:49

Aber, dass ich die einzelnen Variablen bei der Übergabe an write () in char zeiger casten muss stimmt schon noch? Ich bin nur etwas verwirrt, da es eigentlich so im buch steht....

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

10

22.12.2011, 18:51

Das wirst Du wohl müssen, ja. Aber auch da sei Dir ein ordentlicher C++ Cast an's Herz gelegt (reinterpret_cast), der C-Cast (char*) ist eher ungut.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Werbeanzeige