2014-09-28 14 views
5

strtol() bir sayı dönüştürmediğini nasıl anlayabilirim? Aşağıdaki basit durumda test ettim ve 0 çıktı. Açık olan soru şu ki, dönüşüm olmayan ve 0'ın dönüşümü arasındaki farkı nasıl ayırt edebilirim? aşağıdaki gibi stdio.h içindeStrtol hatası algılıyor

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

**** 
li1: 0 
+2

[C++ - strtol doğru kullanım] (http: // stackoverflow. com/sorular/14176123/doğru-kullanma-of-strtol) – DOOM

cevap

15

strtol bildirimi:

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

strtol döndürülen değeri valid veya invalid olup olmadığını belirlemeye olanak tanır güçlü bir hata denetimi ve doğrulama düzeni içerir. Esasen, elinizde 3 temel araç var. (1) değeri (2), errno çağrısı ile ayarlanır değeri dönen ve (3) adresleri ve nptr ve Resim endptr içeriği ile, ve strtol ayarlayın. (tüm ayrıntılar için bkz. man 3 strtol - man sayfasındaki örnek ayrıca kontrol edilmesi gereken daha kısa koşullar kümesi sağlar, ancak açıklama için aşağıda genişletilmiştir).

Sizin durumunuzda, 0 dönüş değeriyle ilgili olup olmadığını ve geçerli olup olmadığını belirtebilirsiniz. Gördüğünüz gibi, strtol tarafından döndürülen 0 değeri , okunan sayının 0 olduğunu veya 0'un geçerli olduğu anlamına gelir. 0'un geçerli olup olmadığını belirlemek için, arama sırasında errno'un ayarlanmış değerine de bakmanız gerekir (ayarlanmışsa). Özellikle, errno != 0 ve strtol tarafından döndürülen değer 0 ise, strtol tarafından döndürülen değer INVALID'dur. (Bu koşul, EINVAL veya ERANGE için veya ERANGE) ile invalid base, underflow veya overflow'u temsil eder.

bir GEÇERSİZ0 dönen strtol neden olabilir ikinci koşul yoktur. no rakamlarının girilmediği durumda, giriş içinde okundu. Bu olduğunda, strtol, endptr == nptr değerini ayarlar. Bu nedenle, 0 değeri girilmeden önce işaretçi değerlerinin eşit olup olmadığını da kontrol etmeniz gerekir. (A0 dizede çoklu 0's girilebilir GEÇERLİ ) aşağıdaki farklı test koşulları ile birlikte strtol dönüşünü değerlendirirken kontrol etmek için farklı hata koşullarını kısa bir örneğini sağlar

:

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

çıkışı:

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