0

I'm making a simple game in C++ and I want the highest score at the end of the game to be written in a text file. I'm using fstream to first read the last saved highscore and compare it to the new highscore. The output in the text file looks like this (0НН) and it shouldn't. I'm realy frustrated with this. Here's a part of my code.

double score_num=0;
fstream datafile("score.pon"); //Declaration of variables

...

if(SPEED>score_num)
{
     score_num=SPEED;
}
//getting the score

...

datafile<<score_num; //Writing it to the file
Martin
  • 710
  • 2
  • 11
  • 18
  • where are you reading the previous scores? what is in the file and what do you expect to be in the file? – dma Apr 24 '11 at 18:19
  • 2
    The [sample code](http://sscce.org/) is not complete. Please make it so (while keeping it concise). – outis Apr 24 '11 at 18:21
  • @dominic-hamon the contents of the file are read but nothing is written in the file @outis these are the lines that I use to read(datafile>>score_num) and write to the file, the others are irrelevant. – Martin Apr 24 '11 at 18:37
  • Irrelevant lines can be left out, but sample code should at least [compile](http://tinyurl.com/so-hints/). Update the code in the question, not by comments. When others try to fill out the code, they may not make the same mistakes that you did (though they may make others). – outis Apr 24 '11 at 18:48
  • @outis - yes I know I'm a newbie but i try. thanks for the advices! – Martin Apr 24 '11 at 18:54

3 Answers3

3
#include <iostream>
#include <fstream>

using namespace std;
#define SPEED 12

int main()
{
    double score_num=0;
    ofstream datafile("score.pon"); //Declaration of variables


    if(SPEED>score_num)
    {
        score_num=SPEED;
    }
    //getting the score

    datafile<<score_num; //Writing it to the file
    return 0;
}

Replaced fstream by ofstream works like a charm. Perhaps you should show more code? Also, closing the file is good habit:

datafile.flush();
datafile.close();

I'll leave errorhandling to you

sehe
  • 374,641
  • 47
  • 450
  • 633
  • ofstream wouldn't work because I have to read the highscore from the file first and compare it to the score in the buffer – Martin Apr 24 '11 at 18:23
  • 2
    Correct me if I'm wrong but I'm pretty sure closing the stream implicitly flushes it as well. – flumpb Apr 24 '11 at 18:25
  • @kisplit: I think that depends (my C++ mem is sloppy here). I imagine that it depends on the stream class used, and whether the buffer is owned or shared etc. – sehe Apr 24 '11 at 18:35
  • @Martin: do you intend to overwrite the file? In that case, where do you do the [`seekp(0)`](http://www.cplusplus.com/reference/iostream/ostream/seekp/)? – sehe Apr 24 '11 at 18:36
  • adding datafile.flush() and datafile.close() after writing to the file did the trick! thanks! – Martin Apr 24 '11 at 18:52
  • 1
    @Martin: [flushing and closing a file stream](http://stackoverflow.com/questions/4802494/do-i-need-to-close-a-stdfstream) shouldn't be necessary (the [library stream buffer destructor](http://www.cplusplus.com/reference/iostream/filebuf/~filebuf/) will [close](http://www.cplusplus.com/reference/iostream/filebuf/close/) the file after [writing all pending output](http://www.cplusplus.com/reference/iostream/filebuf/overflow/)). If it works, it's likely only indirectly addressing the issue (which we could tell you if you posted complete sample code). – outis Apr 24 '11 at 19:10
0

Hacky solution - open the file as an ifstream, read existing value, close it, adjust score, open file as an ofstream, write score, close it. Alternatively, investigate the use of the seekp() function, and write the score as a binary value, not as text.

0

My best guess as to why the original was failing is that when you read the last character from a file, the EOF bit is set. In this state, all read & write operations fail. You can write to a file stream that's reached its end by calling clear first.

// the following doesn't truncate file, or handle other error conditions.
if (datafile.eof()) {
    datafile.clear();
}
datafile.seekp(0, std::ios_base::beg);
datafile << score_num;

However, this won't solve all your problems. If you write less to the file than its current length (e.g. the old high score was "1.5" and the new high score is "2"), part of the old data will still be present at the end of the file. As long as scores never have a fractional part (in which case you should probably be using an integer type, such as unsigned long), you won't notice the bug, since a < b ⇒ len(a) ≤ len(b). To handle this properly, you'll need to use unapersson's recommended approaches (which will either truncate the file or always write the same amount of data to the file), or use a different I/O library (such as your platform's C library or boost) which provide a way to truncate files (such as the POSIX ftruncate).

outis
  • 75,655
  • 22
  • 151
  • 221
  • I was wondering this morning why the fixes worked only sometimes. i.e. i had a score of 9.1 and than made a score of 9.7 but it didn't record it. So i added datafile.clear() before writing to the file and I hope not to have any more trouble with that! thanks! – Martin Apr 25 '11 at 09:41
  • @Martin: note that you should do more than call `clear` before writing to handle errors properly, as the file stream might be in other error states that would cause the write to fail. See update. – outis Apr 25 '11 at 21:04