Strtol failure detection

How to determine if strtol () is converting a number? I tested it in the following simple case, and it printed 0. The obvious question is, how would I distinguish between non-conversion and conversion 0?

long int li1; li1 = strtol("some string with no numbers",NULL,10); printf("li1: %ld\n",li1); **** li1: 0 
+6
source share
1 answer

The strtol declaration in stdio.h as follows:

 long int strtol(const char *nptr, char **endptr, int base); 

strtol provides a robust error checking and validation scheme that allows you to determine if a valid or invalid value is returned. Essentially, you have 3 basic tools at your disposal. (1) the return value (2) the errno value is set on a call, and (3) the addresses and contents of nptr and endptr provided and specified by strtol . (for more details see man 3 strtol - the example on the man page also provides a shorter set of conditions for checking, but they were disclosed below for explanation).

In your case, you request a return value of 0 and determine if it is valid. As you saw, the value 0 returned by strtol means that it does not mean that the number was read 0 or that 0 valid. To determine if 0 valid, you should also see that errno was set during the call (if it was set). In particular, if errno != 0 and the value returned by strtol is 0 , then the value returned by strtol is INVALID . (this condition will represent either invalid base , underflow , or overflow with errno equal to either EINVAL or ERANGE ).

There is a second condition that can cause strtol return INVALID 0 . The case when the numbers were not read inside the input. When this happens, strtol sets endptr == nptr . Therefore, you should also check if the pointer values ​​are equal before entering the value 0 . (a VALID 0 can be entered with multiple 0's per line)

The following is a brief example of the various error conditions for checking when evaluating the return of strtol along with several different testing conditions:

 #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <limits.h> int main (int argc, char **argv) { if (argc < 2) { fprintf (stderr, "\n Error: insufficient input. Usage: %s int [int (base)]\n\n", argv[0]); return 1; } const char *nptr = argv[1]; /* string to read */ char *endptr = NULL; /* pointer to additional chars */ int base = (argc > 2) ? atoi (argv[2]) : 10; /* numeric base (default 10) */ long number = 0; /* variable holding return */ /* reset errno to 0 before call */ errno = 0; /* call to strtol assigning return to number */ number = strtol (nptr, &endptr, base ); /* output original string of characters considered */ printf ("\n string : %s\n base : %d\n endptr : %s\n\n", nptr, base, endptr); /* test return to number and errno values */ if (nptr == endptr) printf (" number : %lu invalid (no digits found, 0 returned)\n", number); else if (errno == ERANGE && number == LONG_MIN) printf (" number : %lu invalid (underflow occurred)\n", number); else if (errno == ERANGE && number == LONG_MAX) printf (" number : %lu invalid (overflow occurred)\n", number); else if (errno == EINVAL) /* not in all c99 implementations - gcc OK */ printf (" number : %lu invalid (base contains unsupported value)\n", number); else if (errno != 0 && number == 0) printf (" number : %lu invalid (unspecified error occurred)\n", number); else if (errno == 0 && nptr && !*endptr) printf (" number : %lu valid (and represents all characters read)\n", number); else if (errno == 0 && nptr && *endptr != 0) printf (" number : %lu valid (but additional characters remain)\n", number); printf ("\n"); return 0; } 

output:

 $ ./bin/s2lv 578231 string : 578231 base : 10 endptr : number : 578231 valid (and represents all characters read) $ ./bin/s2lv 578231_w_additional_chars string : 578231_w_additional_chars base : 10 endptr : _w_additional_chars number : 578231 valid (but additional characters remain) $ ./bin/s2lv 578some2more3stuff1 string : 578some2more3stuff1 base : 10 endptr : some2more3stuff1 number : 578 valid (but additional characters remain) $ ./bin/s2lv 00000000000000000 string : 00000000000000000 base : 10 endptr : number : 0 valid (and represents all characters read) $ ./bin/s2lv stuff578231 string : stuff578231 base : 10 endptr : stuff578231 number : 0 invalid (no digits found, 0 returned) $ ./bin/s2lv 00000000000000000 -2 string : 00000000000000000 base : -2 endptr : (null) number : 0 invalid (base contains unsupported value) 
+17
source

Source: https://habr.com/ru/post/975948/


All Articles