easy way to get numbers from a string

Started by
7 comments, last by Zahlman 18 years, 4 months ago
Hey guys, I was wondering; what is a fast way to see if a particular string is a number? I'm parsing lines of input from the user, and if it is a number, I want it to do a certain thing. Once i determine whether or not it is a number, i can easily use atof()... p.s. no extra #include files, if possible.
Deep Blue Wave - Brian's Dev Blog.
Advertisement
if youre using c you could iterate over the string, and check if all the chars are between '0' and '9', with 1 '.' and an optional '-' at the start...

[EDIT]
and 'e' or 'E', with another optional '-' before it...
true, but is there no stdlib function that could do that for me?

(sorry, I should have been more specific about "extra" include files. I am currently using <string>, <iostream>, and <stdlib>)
Deep Blue Wave - Brian's Dev Blog.
Pretty easy way is to subtract the value of '0' from the character. If it's less than 0, then you have an alpha character, otherwise it's the value of the number(i.e. '3' - '0' = 3)

so you could just iterate through:

if(char - '0' < 0)
// Alpha character
else
// Numeric character


You can also use the just use the stdio isalpha() function. :)
Quote:Original post by BTownTKD
true, but is there no stdlib function that could do that for me?

(sorry, I should have been more specific about "extra" include files. I am currently using <string>, <iostream>, and <stdlib>)


strtod(), strtol() are what you're after I think, defined in stdlib.
You could use strtof and check the returned end pointer, i.e. verify that it's pointing at the null terminator and there's at least one character in the string.
It won't complain about initial whitespace however, so you'd have to add detection for that manually. Similarily you may want to ignore any whitespace at the end of the string.

A better way to handle whitespace (by ignoring it) may be to use sscanf with a 'canary' character at the end.
if(sscanf(string, "%lf %*c", &value) != 1) { // error}
At least I think that'd work..

edit: 10 seconds too late..
In C++ this is easy, although it will require one more include file (why the resistance to this? Only the bits that are actually needed will get put into your exe, if you do the right stuff when compiling, and it's pretty small compared to the flat one-time cost of "the C++ CRT"):

// other includes - I noticed you have 'string', which is good#include <sstream>using namespace std;// This checkes whether it is a number and also gets the number out if possible.string input;stringstream ss(input);int value;// As an added bonus, if we want to change the code to read hex numbers, for// example, it's as easy as uncommenting this:// ss << hex; // <-- that's a "stream manipulator"; the << gets translated into// a call like "std::hex(ss)", which in turn tells this stringstream object// to change its "reading mode" so that it assumes hex when looking for numbers.// I don't think there exist manipulators for arbitrary number bases, however;// but there are still many other useful things you can do here.if (ss >> value) {  // there was a number at the beginning of the string, and now it is stored in  // value.  char garbage;  if (ss >> garbage) {    // if we get here, there is something after the number within the string.    // Maybe you don't want to do the 'number' handling in this case; maybe    // you do.  } else {    // we definitely have a number.  }} else {  // the string definitely does not hold a number.  // The stringstream is now in a "fail state" just like cin is if you try  // to read a number when there isn't one, and similarly no data has been  // read from it. And naturally, 'value' is still uninitialized here.}


If you're willing to go to Boost, they also provide a nice wrapper for this sort of process: boost::lexical_cast. It will throw an exception if the conversion cannot be done, and return the int (or whatever) as a new value if it can.
I'm unsure of the performance of this, but here's yet another way:

#include <algorithm>	// for find_first_of#include <iostream>#include <string>bool stringContainsNumber( std::string s ) {	const std::string numberSet( "0123456789" );	std::string::iterator it( std::find_first_of( s.begin(), s.end(), numberSet.begin(), numberSet.end() ) );	if( it != s.end() ) return true;	return false;}int main() {	std::string testString1( "This string contains no numbers" );	std::string testString2( "This string contains 1 number" );		if( stringContainsNumber( testString1 ) )		std::cout << "testString1 contains number(s)" << std::endl;	if( stringContainsNumber( testString2 ) )		std::cout << "testString2 contains number(s)" << std::endl;	return 0;}


You could also use std::find_first_of(...) to get a number within a (alphanumeric) string, if that's what you're expecting.

Zahlman's suggestion is a little cleaner, though.
:stylin: "Make games, not war.""...if you're doing this to learn then just study a modern C++ compiler's implementation." -snk_kid
That's ok except that it will (a) detect numbers with leading zeroes; (b) detect numbers too big to fit into an int; (c) not detect negative numbers. It will also only tell you where the first number starts, so you still have to go in and do the work of extracting the number. And anyway, complex searches are often better handled by a regex library (assuming a good understanding of regexes).

But yes, string::find_first_of() is a good tool to be aware of.

This topic is closed to new replies.

Advertisement