Reputation: 153
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.
Upvotes: 6
Views: 17530
Reputation: 392893
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
Upvotes: 3
Reputation: 6005
One way is to load the file and then rewrite it having included the new data:
1) You have to load the file in a structure using C++ file handling API (or any that you might think it is better).
2) Data will be, because of being loaded sequentially, sorted in the structure.You must then add the node (your new data) you want in the structure in an order that it remains sorted.
3) Finally, rewrite your file from the structure.
For your case, you could maybe use an std::vector
. You can open the file and load all of its lines into that vector. You can isolate data by doing string manipulation.
Then, put your data in the structure, in order that it remains sorted. You can, for example, split a line and then take the score part, parse it as int
and make your comparisons with the new data score. After that, the structure contains your data state.
Open the file and rewrite it line by line.
Upvotes: 0
Reputation: 129314
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".
Upvotes: 5
Reputation: 3127
How does it behave depends on file system. There is no solution for general. But I don't think there is a real-life filesystem where you can do such things.
Thing about how would file look on disk before and after such operation. File is one big block on disk. So rewriting is action that need to be done.
There could be a solution if you are open on some different approaches. Think about this file like about memory. How would you do this if it weren't on disk? Which data structure you could use inside an array (we could fink about file as about an array)?
If you don't want to create your own, use sth, which is done. Personally I would use database for such task. It is just what you want. You can insert data and then get it sorted and it works fast. It is optimized to work in such environment like hard drive. If you want to have it on file you can use SQLite
.
Upvotes: 0