if((x = strtol(argv[1], NULL, 10))==0)
exit(EXIT_FAILURE);
That catches non-numeric input alright, but zero is a perfectly
good number that might be input to my program. How can I use
strtol() to convert zero while checking for non-numeric input?
That's what the second argument to strtol() is good for: if you
pass it a pointer to a char pointer it returns the position in
the input string where the conversion stopped. If that's identi-
cal to the string you passed to strtol() you know that nothing
got converted and thus the input was non-numeric. So use it like
char *ep;
x = strtol( argv[ 1 ], &ep, 10 );
if ( argv[ 1 ] == ep )
exit( EXIT_FAILURE );
Of course, you should also check that the input value didn't
under- or overflow, i.e. was less than LONG_MIN or larger than
LONG_MAX - in that case the return value is either LONG_MIN or
LONG_MAX, respectively, and errno is set to ERANGE.
Regards, Jens
--
\ Jens Thoms Toerring ___ Jens.T...@physik.fu-berlin.de
\__________________________ http://www.toerring.de
It only catches some non-numeric input. For example, try
it on "99bottles" ...
strtol() uses three count them three channels to tell you
about conversion errors. First, there's the returned value:
zero if nothing could be converted, LONG_MIN or LONG_MAX if
the input was numeric or out of range. Of course, these three
values could also be returned by a successful conversion, as
you've observed.
If you get LONG_MIN or LONG_MAX, you can distinguish range
errors from legitimate conversions by setting `errno' to zero
before the call and checking whether it's been set to ERANGE
afterward. (Actually, I think Section 7.5 paragraph 3 of the
Standard implies that `errno' will only be set to ERANGE if an
error occurs, assuming it wasn't ERANGE already, so checking
for LONG_MIN and LONG_MAX might be avoidable. Gurus?)
Finally, you can distinguish "no conversion" from an actual
zero (and catch the "99bottles" problem) by making use of the
second argument, so strtol() can tell you where conversion
stopped.
All this rummaging around is inconvenient, and it's probably
best to write a wrapper function to shield yourself from the
unpleasantness. (Sad, isn't it, that a Standard library function
is so unpleasant -- but we are victims of "prior art" here.)
One simple-minded wrapper might take the string and a pointer
to a variable that receives the converted value, and return a
code indicating whether all went well, something like
#include <stdlib.h>
#include <limits.h> /* might not be needed */
#include <errno.h>
/* Returns 0 for success, -1 for failure */
int wrapper(const char *string, long *value) {
char *end;
errno = 0; /* anything other than ERANGE */
*value = strtol(string, &end, 10);
/* the first part of this test might be unneeded */
if ((*value == LONG_MIN || *value == LONG_MAX)
&& errno == ERANGE)
return -1; /* input out of range */
if (end == string)
return -1; /* no conversion possible */
if (*end != '\0')
return -1; /* trailing garbage */
return 0; /* success! */
}
Fancier wrappers are possible too, of course.
Marlene Stebbins wrote:
You need to use the endp feature(2nd parameter) of function
endp.
char *endp;
s = strtol(argv[1], &endp, 10);
You then check the value to what endp points which will
help you determine if a string is what you consider a valid zero.
You should study the description of this function in detail as
it offers many robust features that you can use.
Example:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
char input[6][16] = {"","0a"," 0", "0 ", " 0 ","0"};
char *endp;
long i, value;
for(i = 0; i < 6; i++)
{
value = strtol(input[i],&endp,10);
if(!value && endp != input[i] && *endp == '\0' &&
!isspace((unsigned char)input[i][0]))
printf("\nThe string \"%s\" is in fact zero\n",input[i]);
else printf("The string \"%s\" is not zero\n",input[i]);
}
return 0;
}
--
Al Bowers
Tampa, Fl USA
mailto: xabo...@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/
Assume this prototype..
long strtol(const char *s, char **endp, int base);
Rather than passing NULL as the second argument, pass the address of
a local char* like this..
long x;
char *end;
x = strtol(argv[1], &end, 10);
if (argv[1] == end) exit(EXIT_FAILURE);
--
Joe Wright mailto:joeww...@comcast.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Explanation and illustration:
http://jk-technology.com/c/code/strtol.html
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html