A very good point, Salem; one that I had not realized before.
If using the "read a line, then parse the line as a string" approach, the (void)sscanf() stanzas I showed should be replaced with something like
Code:
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
static int isendorspace(const char *const ptr)
{
return (ptr != NULL && (*ptr == '\0' || isspace(*ptr)));
}
...
char *ptr; /* This points to the line to be parsed */
long count;
double value;
char *endptr;
...
endptr = ptr; errno = 0; count = strtol(ptr, &endptr, 10);
if (endptr > ptr && isendorspace(endptr) && errno == 0) {
/* successful conversion; have valid 'count' */
ptr = endptr;
/* Note: You should still check 'count' is valid, i.e. >= 1L. */
}
endptr = ptr; errno = 0; value = strtod(ptr, &endptr);
if (endptr > ptr && isendorspace(endptr) &&
((errno == 0 && isfinite(value)) ||
(errno == ERANGE && value == 0.0))) {
/* Successful conversion; have valid 'value'.
* It might have been so close to zero it rounded to zero, however.
*/
ptr = endptr;
}
This looks a bit funky, but it should correctly convert even the exact values LONG_MIN, LONG_MAX, -HUGE_VAL, and HUGE_VAL, and stuff like Nan and Inf . The latter should accept values like 1e-500, which are too close to zero to be represented as nonzero doubles.
The isendorspace() is a helper function that returns nonzero/true if and only if the pointer is valid and points to either a whitespace character (including newlines) or at the end of a string.
Is Endor Space, indeed.