2010-09-25 16 views
53

¿Cuál es la diferencia entre atol() & strtol()?atol() v/s. strtol()

Según sus páginas man, que parecen tener el mismo efecto, así como los argumentos que emparejan:

long atol(const char *nptr); 

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

En un caso generalizado, cuando no desea utilizar el argumento base (sólo tengo números decimales), ¿qué función debo usar?

Respuesta

77

strtol le ofrece más flexibilidad, ya que realmente puede decirle si toda la cadena se convirtió en un número entero o no. atol, cuando es incapaz de convertir la cadena en un número (como en atol("help")), devuelve 0, que es indistinguible de 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; 
} 

Salidas:

Got from help: 0, from zero: 0 

strtol especificará, mediante su argumento endptr , donde la conversión falló

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

Salidas:

Conversion error, non-convertible part: help 

Por lo tanto, para cualquier programación seria, sin duda recomiendo el uso de strtol. Es un poco más complicado de usar, pero esto tiene una buena razón, como expliqué anteriormente.

atol puede ser adecuado solo para casos muy simples y controlados.

+3

Creo en su ejemplo, la condición debe ser 'if (! * End)'. Señalará el terminador nulo de la cadena (si se convirtió todo) pero no se establecerá en NULL. –

+0

@Jeff M: tienes razón, perdón error –

+0

¿Se aplica esta misma lógica a la función del núcleo de Linux 'simple_strtol'? No puedo obtener la condición 'if (! * End)' para evaluar a verdadero, usando su modelo exacto. –

4

En el nuevo código, siempre usaría strtol. Tiene control de errores y el argumento endptr le permite ver qué parte de la cadena se utilizó.

El C99 estados estándar sobre los ato* funciones:

Excepto por el comportamiento en caso de error, que equivale a

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

4

atol(str) es equivalente a

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

Uso strtol si desea que el puntero del final (para comprobar si hay más caracteres para leer o si, de hecho, ha leído ninguna en absoluto) o una base distinta de 10. De lo contrario, atol está muy bien.

2

Si la memoria se sirve, strtol() tiene la ventaja adicional de configurar el (opcional) endptr para que apunte al primer carácter que no se pudo convertir. Si NULL, se ignora. De esa manera, si está procesando una cadena que contiene números y caracteres mezclados, puede continuar.

p. Ej.,

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 funcionalidad es un subconjunto de la funcionalidad strtol, excepto que atol te ofrece ninguna capacidad de manejo de errores utilizables. El problema más destacado con las funciones ato... es que conducen a un comportamiento indefinido en caso de desbordamiento. Nota: esto no es solo una falta de retroalimentación informativa en caso de error, este es comportamiento indefinido, es decir, generalmente es una falla irrecuperable.

Esto significa que la función atol (así como todas las demás funciones ato..) es bastante inútil para propósitos prácticos serios. Fue un error de diseño y su lugar está en el depósito de chatarra de la historia de C. Debe usar las funciones del grupo strto... para realizar las conversiones. Se les presentó, entre otras cosas, para corregir los problemas inherentes a las funciones del grupo ato....

18

De acuerdo con la página del manual atoi, ha sido obsoleta por 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 página del manual de strtol dicta la siguiente:

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

El siguiente código comprueba si hay errores de rango. (Código de Eli modificado un poco)

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