2014-09-28 17 views
5

Wie kann ich feststellen, ob STRTOL() eine Zahl nicht konvertiert hat? Ich habe es im folgenden einfachen Fall getestet und es hat 0 ausgegeben. Die offensichtliche Frage ist nun, wie würde ich zwischen einer Nicht-Umwandlung und der Umwandlung von 0 unterscheiden?Erkennen von STRTOL-Fehlern

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

**** 
li1: 0 
+2

[C++ - korrekte Verwendung von strtol] (http: // Stackoverflow. com/questions/14176123/korrekte-Verwendung-von-Strtol) – DOOM

Antwort

15

Die strtol Erklärung in stdio.h ist wie folgt:

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

strtol bietet eine robuste Fehlerprüfung und Validierung Schema, das Sie, ob der Wert zurückgegeben bestimmen können, ist valid oder invalid. Im Wesentlichen haben Sie 3 Hauptwerkzeuge zur Verfügung. (1) der Wert zurückgegeben, (2) den Werterrno durch den Anruf eingestellt ist, und (3) die Adressen und Inhalte nptr und endptr bereitgestellt und eingestellt durch, strtol. (siehe man 3 strtol für vollständige Details - das Beispiel in der man Seite bietet auch eine kürzere Reihe von Bedingungen zu überprüfen, aber sie wurden unten zur Erläuterung erweitert).

In Ihrem Fall fragen Sie nach einem 0 Rückgabewert und bestimmen, ob dieser gültig ist. Wie Sie gesehen haben, bedeutet ein 0 Wert, der von strtol zurückgegeben wird, nicht, dass die gelesene Nummer 0 war oder dass 0 gültig ist. Um festzustellen, ob 0 gültig ist, müssen Sie sich auch den Wert errno ansehen, der während des Aufrufs gesetzt wurde (wenn er eingestellt wurde). Wenn errno != 0 und der von strtol zurückgegebene Wert 0 ist, ist der von strtol zurückgegebene Wert INVALID. (Diese Bedingung wird entweder invalid base, underflow oder overflow mit errno entsprechen entweder oder ERANGE).

Es gibt eine zweite Bedingung, die in strtol Zurücksenden ein INVALID0 führen kann. Der Fall, in dem keine Ziffern innerhalb des Eingangs gelesen wurden. Wenn dies der Fall ist, wird den Wert endptr == nptr festgelegt. Daher müssen Sie auch prüfen, ob die Zeigerwerte gleich sind, bevor Sie den Wert 0 eingegeben haben. (A VALID0 kann mit mehreren 0's in der Zeichenfolge eingegeben werden)

Im Folgenden wird ein kurzes Beispiel der unterschiedlichen Fehlerbedingungen zu überprüfen, wenn die Rückkehr von strtol zusammen mit mehreren verschiedenen Testbedingungen Auswertung:

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

Ausgabe:

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