2014-09-28 136 views
5

如何檢測strtol()是否未轉換數字?我在下面的簡單案例中測試了它,它輸出了0.現在明顯的問題是如何區分非轉換和0轉換?檢測strtol失敗

long int li1; 
li1 = strtol("some string with no numbers",NULL,10); 
printf("li1: %ld\n",li1); 

**** 
li1: 0 
+2

[C++ - 正確strtol將的用途](HTTP://計算器。 COM /問題/ 14176123 /正確的用法 - 的 - 與strtol) – DOOM 2014-09-28 05:54:25

回答

15

strtol聲明中stdio.h如下:

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

strtol提供了一個強大的錯誤檢查和驗證方案,允許您確定返回值是否爲validinvalid。從本質上講,你有3個主要工具可供您使用。 (1)返回的值,(2)errno由呼叫設置爲值,和(3)的地址和nptr,並提供給內容endptr,並且通過,strtol設置。 (有關完整的詳細信息,請參見man 3 strtol - man頁面中的示例還提供了一組較短的檢查條件,但在下面對它們進行了擴展以供解釋)。

在你的情況下,你問關於0返回值並確定它是否有效。如您所見,strtol返回的0而非表示讀取的數字爲00有效。要確定0是否有效,您還必須查看呼叫期間設置的值errno(如果已設置)。具體而言,如果errno != 0strtol返回的值是0,則strtol返回的值是無效。 (該條件將代表invalid base,underflowoverflow,errno等於EINVALERANGE)。

還有第二種情況,可能導致strtol返回無效0沒有數字被讀入的情況。發生這種情況時,strtol將設置值endptr == nptr。因此,在結束輸入0值之前,還必須檢查指針值是否相等。 (一個VALID0可以與多個0's字符串中被輸入)

以下提供的不同錯誤條件一個簡單的例子來檢查評估的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)