Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determining if a string is a double

Tags:

c++

string

double

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();
}
like image 558
wrongusername Avatar asked May 09 '11 04:05

wrongusername


4 Answers

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;
}
like image 68
Chris Eberle Avatar answered Nov 02 '22 08:11

Chris Eberle


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;
}
like image 32
Tony Delroy Avatar answered Nov 02 '22 09:11

Tony Delroy


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;
  //....
}
like image 26
Prasoon Saurav Avatar answered Nov 02 '22 07:11

Prasoon Saurav


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");
}
like image 33
Martin York Avatar answered Nov 02 '22 08:11

Martin York