2

What's the fastest way to check that a string like "2.4393" or "2" is valid- they can both be represented by a double- whilst the strings "2.343." or "ab.34" are not? In particular, I want to be able to read any string and, if it can be a double, assign a double variable to it, and if it can't be a double (in the case that it's a word or just invalid input), an error message is displayed.

Bob John
  • 3,688
  • 14
  • 43
  • 57
  • 1
    What is your input encoding? Simple ASCII or something else? – tpg2114 Dec 06 '12 at 11:36
  • 1
    http://stackoverflow.com/questions/392981/how-can-i-convert-string-to-double-in-c might help. – dutt Dec 06 '12 at 11:37
  • 2
    put it in a stream (e.g. `std::stringstream`) and do `if ( !(stream >> mydouble) ) { myError(); }`. – stefan Dec 06 '12 at 11:37
  • 1
    @stefan: Won't that accept things like "3z" or "1.1."? – David Schwartz Dec 06 '12 at 11:39
  • If I use atof(string) will that work as well? – Bob John Dec 06 '12 at 11:39
  • If you just want to read double from a string( like reading "123.34ab" as "123.45"), it should be fine to use stringstream. If not, try a regex expression. – sleepsort Dec 06 '12 at 11:39
  • "123.34ab" should be invalid. – Bob John Dec 06 '12 at 11:40
  • @DavidSchwartz: You're right, my apologies. To avoid that, a simple check if the stream is empty should suffice. – stefan Dec 06 '12 at 11:46
  • To make sure there's no leftover cruft at the end (as noticed by @DavidSchwartz), you could try doing `char dummy; if (stream >> dummy) myError();` after successfully reading a `double`. That will try to read a character, after first skipping any whitespace, which it should fail (EOF) iff the string is valid. – j_random_hacker Dec 06 '12 at 11:47
  • 1
    @j_random_hacker: What about `"2 "`? The question doesn't say whether it's valid, the answers below consider it invalid but your code considers it valid because it skips the whitespace and then fails to read a char. – Steve Jessop Dec 06 '12 at 12:41
  • @SteveJessop: The suggested `stringstream` approach already allows whitespace at the start, so I thought it makes sense to allow it at the end. But you're right -- the question itself doesn't say, so we should probably assume whitespace at either end is forbidden. OP? – j_random_hacker Dec 06 '12 at 14:27

4 Answers4

5

Use std::istringstream and confirm all data was consumed using eof():

std::istringstream in("123.34ab");
double val;
if (in >> val && in.eof())
{
    // Valid, with no trailing data.
}
else
{
    // Invalid.
}

See demo at http://ideone.com/gpPvu8.

hmjd
  • 120,187
  • 20
  • 207
  • 252
  • 1
    `in.eof()` would work too, wouldn't it? (That would make it more "C++ stylish" @billybob) – stefan Dec 06 '12 at 11:51
2

You can use std::stod(). If the string can not be converted, an exception is thrown.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
0

as mentioned by stefan, you can use std::istringstream

coords          getWinSize(const std::string& s1, const std::string& s2)
{
  coords winSize;
  std::istringstream iss1(s1);
  std::istringstream iss2(s2);

  if ((iss1 >> winSize.x).fail())
    throw blabla_exception(__FUNCTION__, __LINE__, "Invalid width value");
  /*
   .....
  */
}

in my code, coords is :

typedef struct coords {
    int     x;
    int     y;
} coords;
rxdazn
  • 1,380
  • 1
  • 14
  • 30
0

Use boost::lexical_cast, which throws an exception if conversion fails.

hmjd
  • 120,187
  • 20
  • 207
  • 252
Chris Card
  • 3,216
  • 20
  • 15