Reputation: 2567
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
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
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
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
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
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;
}
Upvotes: 3
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
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
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