I would like to see if a string contains a double as its sole contents. In other words, if it could possibly be the output of the following function:
string doubleToString(double num)
{
stringstream s;
s << num;
return s.str();
}
You want the strtod function.
bool isOnlyDouble(const char* str)
{
char* endptr = 0;
strtod(str, &endptr);
if(*endptr != '\0' || endptr == str)
return false;
return true;
}
You've been offered C-style and boost alternatives, but in the style of your doubleToString
implementation:
bool is_double(const std::string& s)
{
std::istringstream iss(s);
double d;
return iss >> d >> std::ws && iss.eof();
}
Here, you're checking iss >> d
returns iss
, which will only evaluate to true
in a boolean context if the streaming was successful. The check for nothing but whitespace before eof()
ensures there's no trailing garbage.
If you want to consider leading and trailing whitespace garbage too:
return iss >> std::nowkipws >> d && iss.eof();
This can be generalised into a boolean-returning test similar to boost's lexical_cast<>
...
template <typename T>
bool is_ws(const std::string& s)
{
std::istringstream iss(s);
T x;
return iss >> x >> std::ws && iss.eof();
}
template <typename T>
bool is(const std::string& s)
{
std::istringstream iss(s);
T x;
return iss >> std::noskipws >> x && iss.eof();
}
...
if (is<double>("3.14E0")) ...
if (is<std::string>("hello world")) ...; // note: NOT a single string
// as streaming tokenises at
// whitespace by default...
You can specialise the template for any type-specific behaviours you'd like, such as:
template <>
bool is<std::string>(const std::string& s)
{
return true;
}
You can use the Boost lexical_cast
to check whether a string contains double or not.
#include <boost/lexical_cast.hpp>
....
using boost::lexical_cast;
using boost::bad_lexical_cast;
....
template<typename T> bool isValid(const string& num) {
bool flag = true;
try {
T tmp = lexical_cast<T>(num);
}
catch (bad_lexical_cast &e) {
flag = false;
}
return flag;
}
int main(){
// ....
if (isValid<double>(str))
cout << "valid double." << endl;
else
cout << "NOT a valid double." << endl;
//....
}
Or use streams directly:
#include <string>
#include <sstream>
#include <iostream>
template<typename T>
bool isValid(std::string const& num)
{
T value;
std::stringstream stream(num);
stream >> value;
// If the stream is already in the error state peak will not change it.
// Otherwise stream should be good and there should be no more data
// thus resulting in a peek returning an EOF
return (stream) &&
stream.peek() == std::char_traits<typename std::stringstream::char_type>::eof();
}
int main()
{
isValid<double>("55");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With