I like to use sscanf for rock-solid parsing of numeric input. For a single number:
/* Given: */
int n;
char extra;
long result;
char *string = ???;
...
n = sscanf(" %ld %c", &result, &extra);
if (n == 1)
{
...success!
}
else
{
... error--either no number was seen, or there was nonblank garbage afterward
}
The spaces before and after %ld allow for leading and trailing whitespace. (%ld will also skip leading whitespace, so the first space is just "documentation".) The %c at the and will match anything that's left in the string after skipping any trailing whitespace. If that succeeds, then there was something in the string besides the number parsed by the %ld format. sscanf returns the number of values stored, so n==1 means that the %ld succeeded and the %c did not, while n!=1 means something else happened.
You can combine that with other formats: " %d , %d %c" with n==2 for success will accept a comma-separated pair of ints, and nothing else will be allowed.
Edit: strtol() has the same problems as atol() for error detection...there isn't any. There can't be, with a simple function syntax. A long result can't both encode every valid long number, AND an error indicator that's distinct from every valid value. There's no such number. (For float and double, there are NAN values, but they have their own problems.)
When I need conversions in multiple places, I tend to make a function like:
/* Convert string to long. Return nozero on success. */
int parseLong( const char *input; long *pvalue)
{
char extra;
long value;
int n = sscanf(" %ld %c", value, extra);
if (n != 1) return 0;
*pvalue = value; /* store value only on 100% success */
return 1;
}
Now you can use:
if ( !parseLong(input, myLongVar) )
{
printf("I don't understand %s\n", input);
continue:
}
...or whatever's appropriate to your validation logic.