atol() v/s. strtol()

4 minutos de lectura

¿Cuál es la diferencia entre atol() y strtol()?

De acuerdo con sus páginas de manual, parecen tener el mismo efecto y argumentos coincidentes:

long atol(const char *nptr);

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

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

avatar de usuario
Eli Bendersky

strtol le brinda más flexibilidad, ya que en realidad puede decirle si la cadena completa se convirtió en un número entero o no. atolcuando no puede 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á, utilizando su endptr argumento, 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, definitivamente recomiendo usar strtol. Es un poco más complicado de usar, pero esto tiene una buena razón, como expliqué anteriormente.

atol puede ser adecuado sólo para casos muy simples y controlados.

  • Creo en tu ejemplo, la condición debería ser if (!*end). Apuntará al terminador nulo de la cadena (si se convirtió todo) pero no se establecerá en NULL.

    –Jeff Mercado

    25 de septiembre de 2010 a las 6:14

  • ¿Se aplica esta misma lógica a la función del kernel de Linux? simple_strtol? no puedo conseguir el if (!*end) condición para evaluar como verdadero, usando su modelo exacto.

    – boltup_im_codificación

    21 de noviembre de 2012 a las 17:01

  • Esto no maneja errores relacionados con números fuera de rango. ¡Para ese errno hay que comprobarlo!

    – Shriram V

    5 de diciembre de 2012 a las 17:32

  • Muchas gracias. Probé atol con la cadena “123ABC” y me dio el valor 123. Así que tienes razón “para cualquier programación seria, definitivamente recomiendo usar strtol”. 🙂

    – alguien_ sonriente

    1 de agosto de 2014 a las 5:18

  • Tenga en cuenta que POSIX1003.1 lo hace no garantizar que 0 es devuelto por atol() en caso de error. Cita: Si el valor no se puede representar, el comportamiento no está definido.

    – patryk.beza

    30 de diciembre de 2015 a las 16:14


avatar de usuario
Hormiga

atol La funcionalidad es un subconjunto de strtol funcionalidad, excepto que atol no le proporciona capacidades utilizables de manejo de errores. El problema más destacado con ato... funciones es que conducen a un comportamiento indefinido en caso de desbordamiento. Nota: esto no es solo una falta de comentarios informativos en caso de un error, esto es comportamiento indefinidoes decir, generalmente un fallo irrecuperable.

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

De acuerdo con la atoi página de manual, 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.

atol(str) es equivalente a

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

Use strtol si desea el puntero final (para verificar si hay más caracteres para leer o si, de hecho, ha leído alguno) o una base distinta de 10. De lo contrario, atol está bien.

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

El estándar C99 establece sobre la ato* funciones:

Excepto por el comportamiento en caso de error, equivalen a

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

avatar de usuario
jeff mercado

Si la memoria no me falla, strtol() tiene el beneficio adicional de establecer el (opcional) endptr para señalar el 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, podría 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" */

avatar de usuario
Shriram V

La página man de strtol da lo 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 código siguiente comprueba si hay errores de rango. (Modificado un poco el código de 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;
}

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad