Sign in to follow this  
password

std::string to int

Recommended Posts

I'm making a highscore system that sorts all highscore with the highest first and the lowest at the bottom. I've managed to print out all the highscores from the file, but now I want to be able to get the score value too. The highscores are added into the textfile like this: name - 5021 name - 1236 name - 1337 name - 768 In order to pick out the number value from the current line I use two for loops like this:
ifstream highscore("highscore.dat", ios_base::in);
                      
string numbers="0123456789";
                      
int scores[10];
int counter=0;
int HY = 230;
              
string currentscore;
string temp;

while(!highscore.eof()) {
    getline(highscore, temp);
                          
    for (int i=0;i<temp.size();i++) {
        for (int a=0;a<10;a++) {
            if (temp[i] == numbers[a]) {
                for (int c=i;c<temp.size();c++) currentscore += temp[c];

                i=temp.size();
                a=10;
                break;
            }
        }
    }

    buffer = TTF_RenderText_Blended(font2, temp.c_str(), fontColor2);
    BlitSurface(210, HY, buffer);
    HY+=12;
                          
    counter++;
}

I can't make the "currentscore" variable to a char with many elements, because that can't be converted to an int. If I convert that to an int, it's only possible to convert one at a time and += will only result in addition if I use an int in the first place like this. scores[counter] += temp[c]; If it is possible to convert a string to an int, this will be a piece of cake. Any suggestions?

Share this post


Link to post
Share on other sites
The function atoi(std::string) can be used to convert a string to an int.
Also, atof(std::string) for string to float.

Share this post


Link to post
Share on other sites
You can use boost::lexical_cast, or manually convert with a std::stringstream.

std::stringstream sstr;
sstr.str(some_string);
sstr >> some_integer;

Share this post


Link to post
Share on other sites
Quote:
Original post by Sol462
The function atoi(std::string) can be used to convert a string to an int.
Also, atof(std::string) for string to float.


atoi() and atof() don't take a std::string as arguments.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Quote:
Original post by Sol462
The function atoi(std::string) can be used to convert a string to an int.
Also, atof(std::string) for string to float.


atoi() and atof() don't take a std::string as arguments.

Oops. Or was it (your string).cstr()?

Share this post


Link to post
Share on other sites
Of course. It's a generic stream.

If you want to be specific, you can create a stringstream that can only be read by using 'istringstream', or only written by using 'ostringstream' (note that in either case you still have the usual access to the buffer with .str()). This is analogous to file streams.

The code you have right now, in addition to the problem of trying to do things yourself that the standard library is more than happy to take care of (by the way, the standard library can do your sorting, too), there are numerous technical problems:

- the 'currentscore' is a sum of digits rather than an actual value.
- The inner loop value doesn't have to be set before you use that technique to "break out of multiple loops", just the outer one.
- Even for doing something yourself, the string interface provides a much nicer way to look for the digit.
- Since you always have a '-' separating the name from the score, it would make more sense to read the name via the 3-arg form of getline, and then read the score. Note that you can just read in the int value from the stream normally, and then use the usual resetting logic.
- You really should create some kind of structure to represent high score entries. If you do it as a "proper" class, you can have it handle the process of reading or writing a single score, encapsulating the "inner loop" and better organizing the code.

Based off of these ideas (and extra knowledge of the standard library :) ), we can refactor things as follows:


// A high score structure.
class Score {
string name;
int score;
public:
friend istream& operator>>(ostream& os, Score& s) {
std::getline(source, s.name, '-');
// Trim one trailing space from the name
s.name = s.name.substr(0, s.name.length() - 1);
// The '-' is extracted but not stored, so we can read the number now.
return source >> s.score >> std::ws;
}
friend ostream& operator<<(ostream& os, const Score& s) {
return os << s.name << " - " << score;
}
// To sort things, they must be comparable.
bool operator<(const Score& other) {
return score < other.score;
}
void draw(int x, int y) {
// put rendering code here
}
};

// Reading in:
std::ifstream highscore("highscore.dat"); // you don't need to specify "in" for ifstreams!
std::vector<Score> scores;
Score s;
std::copy(std::istream_iterator<Score>(highscore),
std::istream_iterator<Score>(),
std::back_inserter(scores));
// istream_iterator and back_inserter come from <iterator>.
// copy and sort come from <algorithm>.

// Sort the scores
std::sort(scores.begin(), scores.end());
// Draw the scores
for (int i = 0; i < scores.size(); ++i) {
scores[i].draw(210, 230 + i*12);
}
// Saving (assuming the file has since been closed or we're in another function)
std::ofstream highscore("highscore.dat");
std::copy(scores.begin(), scores.end(), ostream_iterator<Score>(highscore, "\n"));

Share this post


Link to post
Share on other sites
boost::lexical_cast is the best option, but if you want to do it with stringstreams, you better write a templated function so you can handle more types later if you want to:


template <class T> T ExtractVal(std::string s)
{
T result;
std::stringstream ss;
ss.str(s);
ss>>result;
return result;
}

...
float f=ExtractVal<float>("3.14")
...


Share this post


Link to post
Share on other sites
wow, thanks a bunch for posting all that code. Even if i've already managed to solve everything by using plain code, using a class and STL like that looks so much more efficient.

In my code, I used valarray and made a function that checked for the max value and returned its element and so on..

Quote:
Original post by mikeman
boost::lexical_cast is the best option, but if you want to do it with stringstreams, you better write a templated function so you can handle more types later if you want to:

*** Source Snippet Removed ***


That's a good idea, but I only need to use integers this time, will keep that in mind for the future though.

Share this post


Link to post
Share on other sites
Quote:
Original post by password
wow, thanks a bunch for posting all that code. Even if i've already managed to solve everything by using plain code, using a class and STL like that looks so much more efficient.


It's not a matter of efficiency but of organization. Unless you are talking about the efficiency of your time :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this