1

I'm considering to use the strtod() function to convert a string to a double in C, which siganture is:

double strtod (const char* str, char** endptr);

being str the string to be converted and endptr a pointer to be set to to the first character after the number.

Documentation says:

On success, the function returns the converted floating point number as a value of type double. If no valid conversion could be performed, the function returns zero (0.0).

Thus, as far as I understand, it is not possible to detect situations in which str has a format error (e.g. "foo", "-3ab" or "3o3") from situations in which the str represents 0 (e.g. "0", "0.000", "-0.0", "0e10").

How strtod() function could be used avoiding that problem in zero conversion?

EDIT: I have seen a similar question here. However, I think I'm not asking the same, as my question is about the ambiguity problem between 0 and wrongly formated string, while that other post is about detecting formating errors in general.

Community
  • 1
  • 1
fgalan
  • 11,732
  • 9
  • 46
  • 89
  • Duplicate of http://stackoverflow.com/questions/5580975/problem-with-string-conversion-to-number-strtod – Andrew Henle Oct 01 '15 at 20:27
  • See also [Rationale behind C library functions never setting errno to zero](http://programmers.stackexchange.com/a/209731) – wimh Oct 01 '15 at 20:29
  • And see [Detecting strtol failure](http://stackoverflow.com/a/26083517/33499) as `strtol` behaves like `strtod` – wimh Oct 01 '15 at 20:47

2 Answers2

2

That's precisely why you have endptr. If after the call endptr == str, then no number was parsed.

Amit
  • 45,440
  • 9
  • 78
  • 110
  • Not sure if that's correct in all cases... eg. if `str` is "3ab4" then str points to 3. After invoking strtod(), the fuction return 3 (double) and `endptr` points to 'a' (which happens to be *the first character after the number*), i.e. `str` + 1 . Thus, this is a case in which there is a format error and the `endptr == str` condition fails to detect it. – fgalan Oct 01 '15 at 20:37
  • @fgalan That's not a format error at all. The function is defined to parse and return the maximum number of characters it can, and in this case, it's just that single character. – Amit Oct 01 '15 at 20:41
  • @fgalan, if you want to know if the entire str contributed to the result (was parsed), simply check that `(*endptr == 0)` – Doug Currie Oct 01 '15 at 20:42
2

Also, if you want to detect other errors, like "3.14xyz", strtod will return 3.14, but endptr will point to the 'x', so, if after strtod, 'endptr' is not pointing to 'str' AND 'endptr' points to only whitespace (or EXACTLY 0 if you want to be strict), then 'str' is indeed a valid float. Also errno is set to ERANGE if the string 'str' would provoke an overflow.

Here is an implementation of it:

bool isDouble(const char* s)
{
  char* rest = (char*) s;

  strtod(s, &rest);

  if ((rest == s) || (errno == ERANGE))
    return false;

  // If all WS after the last char used in the conversion, then the string is considered a 'clean float'
  while ((*rest == ' ') || (*rest == '\t') || (*rest == '\n'))
    ++rest;

  return (*rest == 0);
}
kzangeli
  • 403
  • 2
  • 8
  • 1
    Why not use [`isspace()`](http://linux.die.net/man/3/isspace) to detect whitespace? – wimh Oct 01 '15 at 20:50
  • Because I've never heard of the function :-) Yes, doesn't seem like a bad idea. Especially as it is implemented as a macro. – kzangeli Oct 01 '15 at 21:17