c - 检测控制故障

标签 c

<分区>

如何检测 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 提供了一个强大的错误检查和验证方案,允许您确定返回的值是有效还是无效。基本上,您可以使用 3 个主要工具。 (1) 返回的值,(2)errno 由调用设置为,(3) 提供给 strtol 并由其设置的 nptrendptr 的地址和内容。 (有关完整详细信息,请参阅 man 3 strtol - man 页面中的示例还提供了一组较短的条件来检查,但它们已在下面进行了扩展以进行解释)。

在您的情况下,您询问有关 0 返回值并确定它是否有效。如您所见,strtol 返回的 0表示读取的数字是 0 或者0 有效。要确定 0 是否有效,您还必须查看调用期间设置的值 errno(如果已设置)。具体来说,如果errno != 0并且strtol返回的值为0,那么strtol返回的值无效。 (此条件将表示 invalid baseunderflowoverflow,其中 errno 等于 EINVAL ERANGE)。

还有第二种情况会导致 strtol 返回 INVALID 0。输入中未读取任何数字的情况。发生这种情况时,strtol 设置 endptr == nptr 的值。因此,在断定输入了 0 值之前,还必须检查指针值是否相等。 (VALID 0 可以在字符串中输入多个 0)

下面提供了在评估 strtol 的返回时要检查的不同错误条件的简要示例以及几个不同的测试条件:

#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;
}

输出:

$ ./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)

关于c - 检测控制故障,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26080829/

相关文章:

c - 在 unix 系统中执行

c++ - 从 C 调用 C++ 函数以返回 char *

c - 为什么我们可以同时使用函数指针作为 (*func_ptr)() 和 func_ptr() 来调用函数,但数组指针却不能呢?

c - 如何用 C 语言编写 LLVM Pass

C: 如何用更新的 GtkWidget 对齐属性替换 GtkAlignment 函数

c: unsigned long long 仅在 HP-UX 上被分配了错误的值

c - 节点*和*节点有什么区别?

c++ - 如何为 Linux 编写自己的自定义启动画面?

c - 一个 Void 指针的内存

c - 如何降低遍历字符串的时间复杂度?