Reputation: 11190
Basically, i want to read highscores from a file and check if the user has scored enought points to be on the scoreboard. I'm trying to do it like this:
string initials[10];
int scores[10];
//load txt
ifstream highscores("highscores.txt");
if(highscores.is_open())
{
while(highscores.good())
{
for(int x=0;x<10;x++)
{
getline(highscores,initials[x],' ');
highscores >> scores[x];
}
}
}
the initials are only 3 chars long, so i could implement a 2 dim. array but i wanted to try it with strings. It shows that i mad one string of size 10. How should i write it so it will work with 10 arrays instead of 1? (I know i could make 10 arrays naming them from array1.. to 10, looping through them sound much better. The highscores file is just a set of 10 initialas AAA,BBB etc. and some scores.
Example of highscores.txt:
AAA 5000
BBB 4000
CCC 3000
Upvotes: 0
Views: 205
Reputation: 414835
There are two tasks:
add a new user score if it is high enough
// Add a new score (score => name pair); pop the lowerest score and return it
template <class Map> typename Map::value_type
add_score_if(Map& scores, typename Map::value_type new_score) {
scores.insert(new_score);
// pop the lowerest score
auto it = scores.begin();
typename Map::value_type lowerest(*it);
scores.erase(it);
return lowerest;
}
add_score_if()
pops the lowerest score thus if new_score
is not high enough it won't stay in the score table i.e., the content of the scores
will be the same before/after add_score_if()
in this case.
load scores from the file
// Load scores (score => name pairs) from input stream
// where each line is: name score
// Return whether all scores have been loaded
template <class Istream, class Map> bool
load_scores(Istream& in, Map& scores) {
std::string name; int score;
while (in >> name >> score) scores.insert(std::make_pair(score, name));
return in.eof(); //XXX ignore errors at eof
}
#include <iostream>
#include <map>
template<class Map> void
dump_scores(std::ostream& out, const Map& scores) {
for (auto it = scores.rbegin(); it != scores.rend(); ++it)
out << it->second << ' ' << it->first << '\n';
}
int main() {
// load scores
std::multimap<int, std::string> scores;
if (! load_scores(std::cin, scores)) {
std::cerr << "error: not all scores have been loaded\n";
return 1;
}
std::cout << "Before:\n";
dump_scores(std::cout, scores);
// add new score
add_score_if(scores, std::make_pair(4000, "AAA"));
std::cout << "\nAfter:\n";
dump_scores(std::cout, scores);
}
$ g++ -std=c++0x *.cc && printf "AAA 5000\nCCC 3000\nBBB 4000" | ./a.out
Before:
AAA 5000
BBB 4000
CCC 3000
After:
AAA 5000
AAA 4000
BBB 4000
Upvotes: 1
Reputation: 6901
Got your question after re-reading it :)
1. string str[10]
as you mentioned does not create an array of 10 strings as strings are created on heap not on stack.
If you want to create an array of strings to put your data to..then it should be char * name[10];
and every time you read a line and get the first 3 characters you do new char[3]
(you gotta store it in char * right ??).
Else, to be more efficient and depending upon your data, you can create a char arr[30]
and do the alignment of 3 bytes for reading all by yourself.
Now, you can make your life much easier by using the STL containers..
vector < map < string,int > > arr; arr.reserve(10);
The advantages are many: 1) No memory management to be done by you.
2) Use of iterators to loop through.
3) And there wont be much difference in performance also if you compare it with my first method.
Upvotes: 0
Reputation: 122011
Use std::map
to hold initials and associated score. For example:
int main()
{
// Map is keyed by initials.
std::map<std::string, int> scores;
std::ifstream in("highscores.txt");
if (in.is_open())
{
for (;;)
{
std::string line;
std::getline(in, line);
if (!in.good())
{
break;
}
const size_t space_idx = line.find(' ');
if (std::string::npos != space_idx)
{
// The initials are everthing before the space.
// Score everything after the space.
scores[line.substr(0, space_idx)] =
atoi(line.substr(space_idx + 1).c_str());
}
}
in.close();
}
// Check who has achieved required score.
for (std::map<std::string, int>::iterator i = scores.begin();
i != scores.end();
i++)
{
if (i->second > 3500)
{
std::cout << i->first << "\n";
}
}
return 0;
}
Upvotes: 1