una strtoint stoi entero ejemplos convertir conversion cadena c scanf atoi

strtoint - ¿Cuál es la diferencia entre sscanf o atoi para convertir una cadena en un número entero?



strtoint c++ (6)

Combinando respuestas R .. y PickBoy para abreviar

long strtol (const char *String, char **EndPointer, int Base) // examples strtol(s, NULL, 10); strtol(s, &s, 10);

gcc 4.4.4 c89

¿Qué es mejor convertir una cadena en un valor entero?

He intentado 2 métodos diferentes atoi y sscanf. Ambos funcionan como se esperaba.

char digits[3] = "34"; int device_num = 0; if(sscanf(digits, "%d", &device_num) == EOF) { fprintf(stderr, "WARNING: Incorrect value for device/n"); return FALSE; }

o usando atoi

device_num = atoi(digits);

Estaba pensando que el sscanf sería mejor ya que puedes verificar si hay errores. Sin embargo, atoi no hace ninguna comprobación.


Cuando no hay preocupación acerca de la entrada de cadena no válida o problemas de rango, use la más simple: atoi()

De lo contrario, el método con mejor detección de error / rango no es ni atoi() ni sscanf() . Esta buena respuesta todo listo detalla la falta de comprobación de errores con atoi() y algunos errores al verificar con sscanf() .

strtol() es la función más estricta al convertir una cadena a int . Sin embargo, es solo un comienzo. A continuación se muestran ejemplos detallados para mostrar el uso adecuado y, por lo tanto, el motivo de esta respuesta después del aceptado .

// Over-simplified use int strtoi(const char *nptr) { int i = (int) strtol(nptr, (char **)NULL, 10); return i; }

Esto es como atoi() y deja de utilizar las características de detección de errores de strtol() .

Para usar completamente strtol() , hay varias características a considerar:

  1. Detección de no conversión : ejemplos: "xyz" , o "" o "--0" ? En estos casos, endptr coincidirá con nptr .

    char *endptr; int i = (int)strtol(nptr, &endptr, 10); if (nptr == endptr) return FAIL_NO_CONVERT;

  2. ¿Debería convertir toda la cadena o solo la parte principal? ¿Está "123xyz" OK?

    char *endptr; int i = (int)strtol(nptr, &endptr, 10); if (*endptr != ''/0'') return FAIL_EXTRA_JUNK;

  3. Detecta si el valor era tan grande, el resultado no es representable como "999999999999999999999999999999" .

    errno = 0; long L = strtol(nptr, &endptr, 10); if (errno == ERANGE) return FAIL_OVERFLOW;

  4. Detecta si el valor estaba fuera del rango de int , pero no long . Si int y long tienen el mismo rango, esta prueba no es necesaria.

    long L = strtol(nptr, &endptr, 10); if (L < INT_MIN || L > INT_MAX) return FAIL_INT_OVERFLOW;

  5. Algunas implementaciones van más allá del estándar C y configuran errno por razones adicionales, como errno a EINVAL en caso de que no se realice ninguna conversión o EINVAL El valor del parámetro Base no es válido. . El mejor momento para probar estos valores errno depende de la implementación.

Poniendo todo esto junto: (Ajústese a sus necesidades)

#include <errno.h> #include <stdlib.h> int strtoi(const char *nptr, int *error_code) { char *endptr; errno = 0; long i = strtol(nptr, &endptr, 10); #if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX if (errno == ERANGE || i > INT_MAX || i < INT_MIN) { errno = ERANGE; i = i > 0 : INT_MAX : INT_MIN; *error_code = FAIL_INT_OVERFLOW; } #else if (errno == ERANGE) { *error_code = FAIL_OVERFLOW; } #endif else if (endptr == nptr) { *error_code = FAIL_NO_CONVERT; } else if (*endptr != ''/0'') { *error_code = FAIL_EXTRA_JUNK; } else if (errno) { *error_code = FAIL_IMPLEMENTATION_REASON; } return (int) i; }

Nota: Todas las funciones mencionadas permiten espacios iniciales, un carácter de signo principal opcional y se ven afectados por el cambio de entorno local . Se requiere un código adicional para una conversión más restrictiva.

Nota: El título no OP cambia el énfasis sesgado. Esta respuesta se aplica mejor al título original "convertir cadena a entero sscanf o atoi"


Para @R .. Creo que no es suficiente comprobar errno para la detección de errores en la llamada strtol .

long strtol (const char *String, char **EndPointer, int Base)

También deberá verificar EndPointer para ver si hay errores.


Si el usuario ingresa 34abc y los pasa a atoi, devolverá 34. Si desea validar el valor ingresado, entonces debe usar isdigit en la cadena ingresada de forma iterativa.


Tienes 3 opciones:

  1. atoi

Probablemente sea el más rápido si lo usa en código de rendimiento crítico, pero no genera informes de errores. Si la cadena no comienza con un entero, devolverá 0. Si la cadena contiene basura después del entero, convertirá la parte inicial e ignorará el resto. Si el número es demasiado grande para caber en int , el comportamiento no está especificado.

  1. sscanf

Algunos informes de errores, y usted tiene mucha flexibilidad para qué tipo almacenar (versiones firmadas / sin firmar de char/short/int/long/long long/size_t/ptrdiff_t/intmax_t ).

El valor de retorno es la cantidad de conversiones que tienen éxito, por lo que al buscar "%d" se devolverá 0 si la cadena no comienza con un número entero. Puede usar "%d%n" para almacenar el índice del primer carácter después del entero que se lee en otra variable y, por lo tanto, comprobar para ver si se convirtió la cadena completa o si hay basura después. Sin embargo, como atoi , el comportamiento en el desbordamiento de enteros no está especificado.

  1. strtol y familia

Robusto informe de errores, siempre que establezca errno en 0 antes de realizar la llamada. Los valores de retorno se especifican en overflow y se establecerá errno . Puede elegir cualquier base numérica del 2 al 36, o especificar 0 como la base para auto interpretar los principales 0x y 0 como hexadecimal y octal, respectivamente. Las opciones de tipo para convertir a son versiones firmadas / sin firmar de long/long long/intmax_t .

Si necesita un tipo más pequeño, siempre puede almacenar el resultado en una variable unsigned long temporal o unsigned long y verificar el desbordamiento usted mismo.

Dado que estas funciones toman un puntero al argumento del puntero, también obtiene un puntero al primer carácter que sigue al entero convertido, de forma gratuita, para que pueda saber si toda la cadena fue un entero o analizar los datos posteriores en la cadena si es necesario.

Personalmente, recomendaría la familia strtol para la mayoría de los propósitos. Si estás haciendo algo rápido y sucio, atoi podría satisfacer tus necesidades.

Como comentario adicional, a veces encuentro que necesito analizar los números en los que no se supone que se acepten los espacios en blanco iniciales, el signo, etc. En este caso, es bastante fácil lanzar su propio ciclo, por ejemplo,

for (x=0; (unsigned)*s-''0''<10; s++) x=10*x+(*s-''0'');

O puede usar (para mayor robustez):

if (isdigit(*s)) x=strtol(s, &s, 10); else /* error */


*scanf() familia de funciones *scanf() devuelve el número de valores convertidos. Por lo tanto, debe verificar para asegurarse de que sscanf() devuelva 1 en su caso. EOF se devuelve por "error de entrada", lo que significa que ssacnf() nunca devolverá EOF .

Para sscanf() , la función tiene que analizar la cadena de formato y decodificar un entero. atoi() no tiene esa sobrecarga. Ambos sufren el problema de que los valores fuera de rango resultan en un comportamiento indefinido.

Debe usar las funciones strtol() o strtoul() , que proporcionan una detección y comprobación de errores mucho mejor. También te dejan saber si toda la cadena fue consumida.

Si desea una int , siempre puede usar strtol() y luego verificar el valor devuelto para ver si se encuentra entre INT_MIN e INT_MAX .