C++ String to a number

Started by
21 comments, last by Chad Smith 11 years, 1 month ago

First basic problem is that your IsNumber() function works the same for every single number type, but not every number type has the same valid format. What's a valid float is not necessarily a valid int. Secondly, you're only looking at valid characters without looking at the pattern of characters. IsNumber() would return true for "....." but this isn't a valid number for any data type. Next, if you're going to bring in a locale, then you should be looking at valid number formats for the given locales. For instance "10,000" is a valid formatted integer with a thousands separator for en-US, but the same number number formatted for de-DE is "10.000" neither of which would be parsed by std::stringstream properly as an integer. IsNumber() also misses the exponent portion of a float which generally starts with an "e" or "E". Also being a properly formatted number doesn't mean that the conversion would succeed. For instance, what happens when you want to format "10000000000000000000000000000" into a 32-bit int?

The ternary operator can be replaced very simply with validNumber = IsNumber(text);.

But again, the whole IsNumber() logic is simply duplicating the work std::stringstream already does when parsing the number itself. It would be less work, both in terms of programmer effort and in clock cycles at run time, and less bug prone to just to check the state of the stream after extraction.

Thanks for that SiCrane. I'm not sure why exactly I was so focused on writing an entire IsNumber function from scratch. I actually just got rid of it and will just allow std::stringstream do it's job.

Now the ToNumber function works pretty well by just letting std::stringstream do it's job. I also check what in_avail returned to see if anything is left in the buffer. It works pretty well. Only thing is what you brought up. If I enter a string that is too large to fit in a 32-bit int then I will get a wrong conversion. though the function will think everything was converted just fine. I at first thought I would use the std::numeric_limits min and max and check if the converted value was less than or greater than those but since the number would just be filled with garbage it would fall within the range (and my testing did confirm this it seems). So now I am a bit unsure on how to check that the number is within the range allowed for that type. Any tips for that or something I should look up real fast?

Or am I entering something that I really don't want to deal with and should just deal with what I have? I mean since I really am just doing this for a really quick way to work with and check the input used in the small university projects I get. We aren't really graded for console input/output. Really on that we understood the basics of Linked List, Binary Search Tree, or something like that. Limits are also set to allow us to assume as of right now that the user did use the right input for the most part. So while it would be ok to use what I have really I'd rather have it more complete.

NOTE: I don't actually expect it to get fully complete where it would "rival" the C++11 way or the boost::lexical_cast. Just work for the basic numerical data. It would never be seen in any production code or something. I for sure would use C++11 or boost:lexical_cast for that!

Thanks for all the help. I'm just having fun experimenting with this right now just to see what I could come up with.

Advertisement
If you want to see if an extraction operation failed on a stream check the stream state. If something like the number being too big happens then the stream fail bit will be set, which you can check with the fail() member function. Alternately, you can convert the stream itself to a boolean context which gives you the opposite of the fail() function. Note that this kind of check is in addition to checking if there's still input in the stream buffer.

If you want to see if an extraction operation failed on a stream check the stream state. If something like the number being too big happens then the stream fail bit will be set, which you can check with the fail() member function. Alternately, you can convert the stream itself to a boolean context which gives you the opposite of the fail() function. Note that this kind of check is in addition to checking if there's still input in the stream buffer.


Got it!
Thanks for all the help! I need to go through the posts and rate up these helpful posts!

This topic is closed to new replies.

Advertisement