I have a text file that contains the high scores of a game in this format:
Name Score
Name Score
Name Score
With the file ordered in descending order on score.
I want to insert a new name and its corresponding score in the right place in the file so that it remains ordered correctly. Any suggestions how to do this would be greatly appreciated!
For Example, given the following file:
Edward 100
David 90
Sarah 80
Alice 60
And I want to add.
Name = Jodi
Score = 70
To the file, so the new file reads:
Edward 100
David 90
Sarah 80
Jodi 70
Alice 60
Thanks
At the moment I have the following code:
string playerName = pPlayer->GetName();
int playerScore = pPlayer->GetScore();
std::ofstream score("scores.txt", std::ios_base::app | std::ios_base::out);
score << "\n" << playerName << " " << playerScore;
Which just adds the name to the end of the file. I considered reading in the whole file ordering it then Over righting the old file. But I don't want to do this because it could take ages if the file got large.
There are a few different ways to do this. The one that is simplest to implement is one that reads the entire file into a vector, inserts the new value and writes out the new file.
The second option is to read the file until you find the right place, "mark" where that is in the file (using for example istream::tellg()
), then read all the following elements into a vector, update the new record, and write back out the once beyond that.
A third option is to just keep the list unordered in the file, and sort the information when you read it. That way, you can just append to the end, saving on writing the file over and over again.
In reality, I suspect that writing a VERY large file will still be quick enough to make little or no difference at all. Modern hard drives will write many megabytes per second, and you only have some dozens of bytes per line, so you need to have milions of lines in your file before it makes any difference at all. For example, I just copied some large files amounting to 132MB on my machine, and the compined time to read and write 132mb came to 1.2s. If each of your records are 26 bytes, that's 50 million "scores".
If you carefully define a type to represent your data record:
struct Record {
std::string name; int score;
friend std::istream& operator>>(std::istream& is, Record& r) { return is >> r.name >> r.score; }
friend std::ostream& operator<<(std::ostream& os, Record const& r) { return os << r.name << "\t" << r.score; }
bool operator<(Record const& other) const {
return other.score < score;
}
};
Note that it knows how to
Then, C++ algorithms are your friend once again:
int main()
{
std::ifstream ifs("input.txt");
std::vector<Record> const insert { Record { "Jodi", 70 } };
std::merge(
std::istream_iterator<Record>(ifs), {},
insert.begin(), insert.end(),
std::ostream_iterator<Record>(std::cout, "\n"));
}
See it Live On Coliru
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With