Inno
Inno

Reputation: 2567

Is there a stl or boost function to determine if a string is numeric?

I'm very new to C++, boost etc.

I would like to know if there is already a function in boost or STL I can use to determine if a string is numeric.

Numeric strings may look like: 100

or

100.52

I know there are tons of examples how to write such a function but I would like to know if there is already a function I can use for this.

I'm looking for a pure C++-solution, not C.

[UPDATE: I'm already using lexical_cast to convert my strings, I'm just wondering if there is a method like is_numeric I can use for this...]

Upvotes: 12

Views: 13057

Answers (9)

Matt Curtis
Matt Curtis

Reputation: 23624

No, there's not a ready-made way to do this directly.

You could use boost::lexical_cast<double>(your_string) or std::stod(your_string) and if it throws an exception then your string is not a double.

C++11:

    bool is_a_number = false;
    try
    {
        std::stod(your_string);
        is_a_number = true;
    }
    catch(const std::exception &)
    {
        // if it throws, it's not a number.
    }

Boost:

    bool is_a_number = false;
    try
    {
        lexical_cast<double>(your_string);
        is_a_number = true;
    }
    catch(bad_lexical_cast &)
    {
        // if it throws, it's not a number.
    }

Upvotes: 12

Jian Hu
Jian Hu

Reputation: 31

The following code

The following sentense, return true if "str" is composed of 0~9 only, otherwise, return false.

return str.find_first_not_of("0123456789") == std::string::npos

Upvotes: 3

andreee
andreee

Reputation: 4679

From C++11, you can simply use one of std::stof, std::stod, std::stold for converting to float, double and long double, respectively. They convert a string to the numerical value or throw an exception, if there's a problem (see the reference). Here is an example with std::stod:

bool isNumeric(const std::string& str) {
  try {
    std::stod(str); // can safely ignore the return value, function is not [[nodiscard]]
    return true;
  }
  catch (const std::exception&) {
    return false;
  }
}

Also have a look at the functions to convert a string to signed and unsigned integers.

Upvotes: 1

Bernhard Leichtle
Bernhard Leichtle

Reputation: 181

There is no boost needed, only stl ... A single char could be checked as an int (c >= '0' && c <= '9'), find_if_not will find the first char not matching the condition between [first] and [last]. If no match was found, it will return [last].

If additional chars like space,.- should be checked, add them.

#include <string>
#include <algorithm>
bool isNumeric(std::string strValue) 
{
    if (strValue.empty())
        return false;
    else
        return (std::find_if_not( std::begin(strValue)
                            , std::end(strValue)
                            , [](char c)
                              { return (c >= '0' && c <= '9'); }
                            ) == std::end(strValue)
                );
}

P.S. @Jian Hu is an empty string numeric ?

Upvotes: 0

Sergey
Sergey

Reputation: 243

bool is_numeric(std::string number)
{
    char* end = 0;
    std::strtod(number.c_str(), &end);

    return end != 0 && *end == 0;
}


bool is_integer(std::string number)
{
    return is_numeric(number.c_str()) && std::strchr(number.c_str(), '.') == 0;
}

Source

Upvotes: 3

ildjarn
ildjarn

Reputation: 62975

If performance is a concern at all, I would use boost.spirit.qi rather than std::stringstream:

#include <string>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_numeric.hpp>

bool is_numeric(std::string const& str)
{
    std::string::const_iterator first(str.begin()), last(str.end());
    return boost::spirit::qi::parse(first, last, boost::spirit::double_)
        && first == last;
}

If you want to allow trailing whitespace then do the following instead:

#include <string>
#include <boost/spirit/include/qi_parse.hpp>
#include <boost/spirit/include/qi_numeric.hpp>
#include <boost/spirit/include/qi_char_class.hpp>
#include <boost/spirit/include/qi_operator.hpp>

bool is_numeric(std::string const& str)
{
    std::string::const_iterator first(str.begin()), last(str.end());
    return boost::spirit::qi::parse(first, last,
            boost::spirit::double_ >> *boost::spirit::qi::space)
        && first == last;
}

Upvotes: 6

James Kanze
James Kanze

Reputation: 153919

boost::regex (or std::regex, if you have C++0x) can be used; you can defined what you want to accept (e.g. in your context, is "0x12E" a number or not?). For C++ integers:

"\\s*[+-]?([1-9][0-9]*|0[0-7]*|0[xX][0-9a-fA-F]+)"

For C++ floating point:

"\\s*[+-]?([0-9]+\\.[0-9]*([Ee][+-]?[0-9]+)?|\\.[0-9]+([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)"

But depending on what you're doing, you might not need to support things that complex. The two examples you cite would be covered by

"[0-9]+(\\.[0-9]*)?"

for example.

If you're going to need the numeric value later, it may also be just as easy to convert the string into an istringstream, and do the convertion immediately. If there's no error, and you extract all of the characters, the string was a number; if not, it wasn't. This will give you less control over the exact format you want to accept, however.

Upvotes: 9

Giovanni Funchal
Giovanni Funchal

Reputation: 9190

Use a stringstream and return true if the convertion "ate" all the characters in the original string (=eof()).

bool is_numeric(const std::string& str) {
    std::stringstream conv;
    double tmp;
    conv << str;
    conv >> tmp;
    return conv.eof();
}

Upvotes: 3

Stefan N&#228;we
Stefan N&#228;we

Reputation: 3104

You could try a lexical_cast on the string.

Upvotes: 2

Related Questions