Struct in Binärdatei schreiben: Eintrag ist immer doppelt in der Datei vorhanden
-
Das Problem ist ja, dass eof erst gesetzt wird, wenn die letzte Operation das Ende erreicht hat. Und da du das zuerst überprüfst, läuft die Schleife noch einmal durch, obwohl das Ende bereits erreicht wurde. Überprüf einfach nach dem read, ob eof gesetzt ist und dann mit break raus. (in einer Endlosschleife).
-
Das ist ja eine gemeine Falle...
Danke für den Hinweis. Habe es jetzt folgendermaßen gemacht:while(!HighscoreFile.std::ios::eof()) { HighscoreFile.read((char*)&Entry, sizeof(Entry)); if (!HighscoreFile.std::ios::eof()) { std::cout << Entry.name << ": " << Entry.punkte << std::endl; }; };Mit der Abfrage fange ich nun die doppelte Ausgabe ab.
Später werden es auch mehr Elemente sein und die werden dann in eine Liste gepusht. Sollte jetzt so funktionieren.Danke für die Hilfe!
MfG
Hundefutter
-
Hundefutter schrieb:
Das ist ja eine gemeine Falle...
.. und ich kenne niemanden, der da nicht schon reingetappt wäre. => Mach Dir nichts draus.

1.)
Eine Alternative wäre nochwhile(HighscoreFile.read((char*)&Entry, sizeof(Entry))) { std::cout << Entry.name << ": " << Entry.punkte << std::endl; };Das klappt, weil
- read() einen istream& zurückliefert,
- bei dem es im Falle von eof das fail-Bit setzt und
- es für iostream einen entsprechenden Konvertierungsoperator (void*) gibt, der fail- und bad-Bit überprüft.
Letztlich willst Du ja vermutlich den Input auch nicht weiterverarbeiten, wenn der Stream korrupt (failBit oder badBit) ist....
2.)
Eine weitere Möglichkeit wäre, den Stream bei Auftreten von eof eine exception werfen zu lassen. Das kann an ihm "beibringen" überHighscoreFile.exceptions(ios_base::eofbit);(ungetestet)
3.)
... und "schließlich bin ich der Meinung, dass Karthago zer ...." äh, dass man nur in besonderen Ausnahmefällen structs binär ablegen sollte. Die Files sind compilerspezifisch (Plattform, Version, Optionen, ...) und damit nur sehr eingeschränkt dauerhaft.Gruß,
Simon2.
-
Danke für die Ergänzungen.
Ich habe ein Highscore-System, welches eben immer Paare von Name und Punktzahl speichern soll.
Daher habe ich eben das Ganze mit ner struct gelöst:struct highscoreEntry { char name[30]; int punkte; };Wenn man structs nicht binär speichern sollte, wie soll ich es denn alternativ lösen?
Es muss eben immer ein Name mit einer zugehörigen Punktzahl gespeichert werden.MfG
Hundefutter
-
Simpel kannst du es speichern, indem du stumpf in Textdateien schreibst.
Je eine Zeile für den Namen und einen für die Punkte. Wenn du alles in eine Zeile schreiben würdest, dürftest du entweder keine Namen mit Leerzeichen nehmen oder müsstest mit Trennzeichen arbeiten. Zwei Zeilen sind da einfacher.Exceptions würde ich in dem Fall aber auch nicht verwenden, da diese ja nur in Ausnahmen (wie der Name schon sagt) verwendet werden sollten und das das Ende einer Datei erreicht wird, ist ja nicht wirklich die Ausnahme sondern eher die Regel.

-
Zeilen weise die Scores sichern.
Datei:
1. Zeile : Player1 - Score1
2. Zeile : Player2 - Score2
...Dann einfach mit getline auslesen.
Greetz Tobi
-
T0bi schrieb:
Zeilen weise die Scores sichern.
Datei:
1. Zeile : Player1 - Score1
2. Zeile : Player2 - Score2
...Dann einfach mit getline auslesen.
Dann nenn ich mich "Huhn - 9999999"

-
Fellhuhn schrieb:
...Exceptions würde ich in dem Fall aber auch nicht verwenden, ...
Ich auch nicht ... habe es aber "vollständigkeitshalber" aufgenommen.
Gruß,
Simon2.
-
Simon2 schrieb:
Fellhuhn schrieb:
...Exceptions würde ich in dem Fall aber auch nicht verwenden, ...
Ich auch nicht ... habe es aber "vollständigkeitshalber" aufgenommen.
Hatte ich auch nicht angenommen, wollte nur nicht das sich jemand dazu verleitet fühlt ohne drüber nachzudenken.

-
Fellhuhn schrieb:
T0bi schrieb:
Zeilen weise die Scores sichern.
Datei:
1. Zeile : Player1 - Score1
2. Zeile : Player2 - Score2
...Dann einfach mit getline auslesen.
Dann nenn ich mich "Huhn - 9999999"

Was haste davon, wenn du Huhn - 9999999 heißt, dein Score aber bei 0 liegt

Greetz Tobi
-
Kann ich das Zeilenweise sichern auch in ner Binärdatei machen?
Möchte nämlich keine Textdatei nehmen, da sonst jeder Hegel die Highscore ganz einfach manipulieren kann...MfG
Hundefutter
-
haeng einfach nen std::ios::binary dran oder nenn die Datei einfach *.bin dann und machs wiw gewohnt mit ner *.txt Datei.
Greetz Tobi
-
Binär schützt nicht vor Manipulation, auch wenn der Personenkreis der die editieren kann, doch deutlich kleienr sein dürfte als der derer die eine Textdatei editieren können.

Wenn du es sicherer haben willst, schreib noch eine Checksumme rein oder etwas in der Art. Einfach irgend eine Zahl mit irgend einem Algorithmus anhand des Namens, der Punktezahl und der Position in der Datei plus Gesamtzahl der Einträge und speicher die mit in die Datei und überprüf die beim Laden.
-
Das mit der Checksumme ist natürlich noch etwas sicherer..
Denke aber, dass ich es erstmal bei einer Binärdatei belasse, das sollte eigentlich Schutz genug sein.. Die Highscore ist ja auch erstmal nur für einen SinglePlayer, also betrügt man sich ja eh nur selbst, wie man so schön sagt
-
T0bi schrieb:
Was haste davon, wenn du Huhn - 9999999 heisst, dein Score aber bei 0 liegt

dann steht in einer zeile
Huhn - 9999999 - 0wenn beim auslesen ueber split gearbeitet wird (
name = eintrag[0]; hiscr = eintrag[1];) hat man den falschen Wert
-
Hundefutter schrieb:
...Denke aber, dass ich es erstmal bei einer Binärdatei belasse, das sollte eigentlich Schutz genug sein.. Die Highscore ist ja auch erstmal nur für einen SinglePlayer, also betrügt man sich ja eh nur selbst, wie man so schön sagt

Ich denke, dass falsch einschätzt:
- welche Probleme Du Dir mit Binärdateien einhandelst (unterschätzt Du)
- wie "sicher" sie sind (überschätzt Du)
- wieviel "Sicherheit" Du brauchst (überschätzt Du)
- wie schwierig eine Checksumme (die mehr Sicherheit bietet als "binär") (überschätzt Du)... aber vllt. bist Du auch einfach an dem Punkt, wo Du denkst "Ist doch egal - Hauptsache, es läuft jetzt endlich". Ich kenne dieses "Abkürzungsschild" und kann Dir sagen: Diese Entscheidung wird Dir eher früher als später in den Hintern beißen.

Andererseits: Hier geht's auch nur um Highscore-Files eines kleinen selbstprogrammierten Spiels. Wenn die weg/falsch/korrupt sind, fliegt kein AKW auseinander.... vielleicht brauchst Du die Erfahrung ja.

Gruß,
Simon2.
-
Simon2 schrieb:
Ich denke, dass falsch einschätzt:
- welche Probleme Du Dir mit Binärdateien einhandelst (unterschätzt Du)
- wie "sicher" sie sind (überschätzt Du)
- wieviel "Sicherheit" Du brauchst (überschätzt Du)
- wie schwierig eine Checksumme (die mehr Sicherheit bietet als "binär") (überschätzt Du)Ich möchte nur eine kleine Highscore-Liste mit 5-10 Einträgen sichern. Da hier jeder das Spiel normalerweise alleine spielt, muss es nicht unglaublich sicher sein, aber eine Textdatei will ich auch nicht nehmen, weil die gerade zu dazu einläd die Highscore zu manipulieren. Wenn jemand es dann doch umbedingt machen will und die Binärdatei ändert, dann soll er das von mir aus tun. Aber es soll eben nicht zu einfach und offensichtlich sein.
Simon2 schrieb:
... aber vllt. bist Du auch einfach an dem Punkt, wo Du denkst "Ist doch egal - Hauptsache, es läuft jetzt endlich". Ich kenne dieses "Abkürzungsschild" und kann Dir sagen: Diese Entscheidung wird Dir eher früher als später in den Hintern beißen.

Andererseits: Hier geht's auch nur um Highscore-Files eines kleinen selbstprogrammierten Spiels. Wenn die weg/falsch/korrupt sind, fliegt kein AKW auseinander.... vielleicht brauchst Du die Erfahrung ja.

Ich arbeite grundsätzlich nicht nach dem Prinzip "hauptsache es läuft"!
Welche Variante würdest du denn vorschlagen, welche die Manipulation nicht so einfach macht wie eine Textdatei? Ist da eine Binärdatei nicht die logische Konsequenz?MfG
Hundefutter
-
Welche Variante würdest du denn vorschlagen, welche die Manipulation nicht so einfach macht wie eine Textdatei? Ist da eine Binärdatei nicht die logische Konsequenz?
Du kannst das ganze noch verschlüsseln. Ist aber den Aufwand kaum Wert. Das einfachste wäre wohl das irgendwie zu speichern und vlt. die Zahl ein wenig zu manipulieren, damit man sie nicht so schnell findet. Also zum Highscore noch 5 dazuzählen und dann das ganze durch 2 rechnen. Dann kann man die Zahl nicht mehr (so schnell) mit einen Punktestand in Verbindung bringen.
-
Das "beste" wäre sicherlich sich für jede Komponente die du in deinem Spiel hast, wozu auch die Highscorespeicherung gehört, ausreichend Zeit zu nehmen, um dies generisch zu gestalten.
Das hat mehrere Vorteile:
a) es ist sauber und daher leicht zu warten
b) es ist wiederverwendbar (für spätere Spiele)
c) man lernt was dabeiWenn du nun zB eine Klasse schreibt, der du per Schnittstelle die Daten gibst, die dann selbstständig Checksummen erstellt und eventuell sogar verschlüsselt, hast du einen gewissen Lernfaktor dabei. Wenn du dann noch per Parameter angeben kannst wie die Daten geschrieben werden sollen, also ob binär oder textuell, hast du wieder was "wiederverwertbarer" gemacht.
Ist nämlich später ziemlich frustrierend wenn man nach ein paar kleinen Spielen das erste "vernünftige" machen will, nur um dann festzustellen das man das Rad zum x.ten mal neu erfinden muss, nur weil man es nie generisch gestaltet hat und es zu schwer ist aus dem alten Kram zu extrahieren, weil eh alles unterschiedlich aufgebaut ist.
Hab noch so viele alte Projekte die ich gerne beenden würde, würde aber wohl bei dem Versuch die Sachen noch zu verstehen (trotz Kommentare) Selbstmord begehen.

-
Hundefutter schrieb:
...
Ich arbeite grundsätzlich nicht nach dem Prinzip "hauptsache es läuft"!...Sorry, ich wollte Dir nicht auf den Schlips treten - ich kenne Dich einfach noch nicht gut genug, daher die Mutmaßung.
Hundefutter schrieb:
...
Welche Variante würdest du denn vorschlagen, welche die Manipulation nicht so einfach macht wie eine Textdatei? Ist da eine Binärdatei nicht die logische Konsequenz?..."Binär" hat ja nunmal nichts mit "sicher" zu tun ... deswegen ist es IMHO alles andere als "die logische Konsequenz".
Eine recht "preiswerte" Variante einer Verschleierung wäre ein binäres XOR mit einem festen Schlüsselwert.
(Vorteil: Zur Verschlüsselung kann man denselebn Algorithmus verwenden wie bei der Entschlüsselung und XOR ist ein bereits eingebauter Operator)Gruß,
Simon2.