2010-09-25 11 views
53

Qual è la differenza tra atol() & strtol()?atol() v/s. strtol()

Secondo le loro pagine, che sembrano avere lo stesso effetto, così come gli argomenti che corrispondono:

long atol(const char *nptr); 

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

In un caso generalizzato, quando io non voglio utilizzare l'argomento base (devo solo numeri decimali), quale funzione dovrei usare?

risposta

77

strtol fornisce una maggiore flessibilità, in quanto può effettivamente dire se l'intera stringa è stata convertita in un numero intero o meno. atol, quando in grado di convertire la stringa in un numero (come in atol("help")), restituisce 0, che è indistinguibile da atol("0"):

int main() 
{ 
    int res_help = atol("help"); 
    int res_zero = atol("0"); 

    printf("Got from help: %d, from zero: %d\n", res_help, res_zero); 
    return 0; 
} 

Uscite:

Got from help: 0, from zero: 0 

strtol specificherà, utilizzando il suo argomento endptr , dove la conversione è fallita.

int main() 
{ 
    char* end; 
    int res_help = strtol("help", &end, 10); 

    if (!*end) 
    printf("Converted successfully\n"); 
    else 
    printf("Conversion error, non-convertible part: %s", end); 

    return 0; 
} 

Uscite:

Conversion error, non-convertible part: help 

Pertanto, per qualsiasi programmazione seria, ho sicuramente consiglio di usare strtol. È un po 'più complicato da usare, ma questo ha una buona ragione, come ho spiegato sopra.

atol può essere adatto solo per casi molto semplici e controllati.

+3

Credo nel tuo esempio, la condizione dovrebbe essere 'if (! * End)'. Punterà al terminatore null della stringa (se è stato tutto convertito) ma non sarà impostato su NULL stesso. –

+0

@Jeff M: hai ragione, mi spiace digitare –

+0

Questa stessa logica si applica alla funzione del kernel linux 'simple_strtol'? Non riesco a ottenere la condizione 'if (! * End)' per valutare true, usando il modello esatto. –

4

Nel nuovo codice userei sempre strtol. Ha la gestione degli errori e l'argomento endptr consente di vedere quale parte della stringa è stata utilizzata.

Il C99 stati standard sulle ato* funzioni:

Fatta eccezione per il comportamento in caso di errore, essi equivalenti a

atoi: (int)strtol(nptr,(char **)NULL, 10)
atol: strtol(nptr,(char **)NULL, 10)
atoll: strtoll(nptr, (char **)NULL, 10)

4

atol(str) è equivalente a

strtol(str, (char **)NULL, 10); 

Usa strtol se si desidera che il puntatore end (per verificare se ci sono più caratteri da leggere o se in realtà avete letto uno a tutti) o una base diversa da 10. In caso contrario, atol va bene.

2

Se la memoria è disponibile, strtol() ha il vantaggio aggiuntivo di impostare (facoltativo) endptr in modo che punti al primo carattere che non è stato possibile convertire. Se NULL, viene ignorato. In questo modo, se stai elaborando una stringa contenente numeri e caratteri misti, puoi continuare.

ad es.,

char buf[] = "213982 and the rest"; 
char *theRest; 
long int num = strtol(buf, &theRest, 10); 
printf("%ld\n", num); /* 213982 */ 
printf("%s\n", theRest); /* " and the rest" */ 
20

atol funzionalità è un sottoinsieme di funzionalità strtol, tranne che atol vi dà alcuna capacità di gestione degli errori utilizzabili. Il problema più evidente con le funzioni ato... è che comportano un comportamento non definito in caso di overflow. Nota: questo non è solo una mancanza di feedback informativo in caso di errore, questo è comportamento non definito, cioè un errore irreversibile.

Ciò significa che la funzione atol (così come tutte le altre funzioni ato..) è praticamente inutile per qualsiasi serio scopo pratico. È stato un errore di progettazione e il suo posto è nella discarica della storia C. È necessario utilizzare le funzioni del gruppo strto... per eseguire le conversioni. Sono stati introdotti, tra le altre cose, per correggere i problemi inerenti alle funzioni del gruppo ato....

18

Secondo la pagina man atoi, è stato dichiarato obsoleto da strtol.

IMPLEMENTATION NOTES 
The atoi() and atoi_l() functions have been deprecated by strtol() and strtol_l() 
and should not be used in new code. 
1

La pagina man del strtol ha pronunciato la seguente:

ERRORS 
    EINVAL (not in C99) The given base contains an unsupported value. 
    ERANGE The resulting value was out of range. 
    The implementation may also set errno to EINVAL in case no conversion was performed (no digits seen, and 0 returned). 

i seguenti controlli di codice per errori di intervallo. (Modificato un po 'il codice di Eli)

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 

int main() 
{ 
    errno = 0; 
    char* end = 0; 
    long res = strtol("83459299999999999K997", &end, 10); 

    if(errno != 0) 
    { 
     printf("Conversion error, %s\n", strerror(errno)); 
    } 
    else if (*end) 
    { 
     printf("Converted partially: %i, non-convertible part: %s\n", res, end); 
    } 
    else 
    { 
     printf("Converted successfully: %i\n", res); 
    } 

    return 0; 
} 
Problemi correlati