检测strtol失败
如何检测strtol()是否未转换数字? 我在下面的简单案例中对它进行了测试并输出了0.现在显而易见的问题是如何区分非转换和0的转换?
long int li1; li1 = strtol("some string with no numbers",NULL,10); printf("li1: %ld\n",li1); **** li1: 0
stdio.h
的strtol
声明如下:
long int strtol(const char *nptr, char **endptr, int base);
strtol
提供了强大的错误检查和validation方案,允许您确定返回的值是valid
还是invalid
。 从本质上讲,您可以使用3种主要工具。 (1)返回的值, (2)通过调用设置值errno
,以及(3)提供给strtol
并由strtol
设置的nptr
和endptr
的地址和内容。 (有关完整详细信息,请参阅man 3 strtol
– man
页中的示例还提供了一组较短的检查条件,但它们已在下面进行了扩展以进行说明)。
在您的情况下,您询问0
返回值并确定它是否有效。 如您所见, strtol
返回的0
值并不意味着读取的数字为0
或0
表示有效。 要确定0
是否有效,还必须查看调用期间设置的errno
值(如果已设置)。 具体来说,如果errno != 0
且strtol
返回的值为0
,则strtol
返回的值为INVALID 。 (此条件将表示invalid base
, underflow
或overflow
其中errno
等于EINVAL
或ERANGE
)。
第二个条件可能导致strtol
返回INVALID 0
。 在输入中没有读取数字的情况。 发生这种情况时, strtol
设置endptr == nptr
的值。 因此,在输入0
值之前,还必须检查指针值是否相等。 (可以在字符串中输入多个0's
VALID 0
)
下面提供了一个简短的示例,说明在评估strtol
的返回以及几个不同的测试条件时要检查的不同错误条件:
#include #include #include #include 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; }
输出:
$ ./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)