2011-05-30 12 views
45

Me he acostumbrado a strtod y variantes. Me pregunto por qué no se envía strtoi con stdlib.h. ¿Por qué el número entero queda fuera de esta parte?¿Por qué no hay strtoi en stdlib.h?

Específicamente, estoy preguntando por qué no hay una versión de atoi con las características de seguridad de strtod.

+0

Alguien por favor etiquetar strtoi – Eli

+0

En implementar, glibc, por ejemplo, es también con características de seguridad 'int atoi (const char * nptr) {return (int) strtol (nptr, (char **) NULL, 10);} ' – yuan

Respuesta

43

strtol() convierte una cadena en un entero, un entero largo pero un entero sin embargo. Hay atoi(), pero se debe evitar en la mayoría de los casos debido a que carece de un mecanismo para informar errores de entradas no válidas.

+1

Cuando el rango de 'long' excede el rango de' int', 'strtol()' no establece 'errno' ni devuelve' INT_MIN/MAX' en 'int' solo desbordamiento anulando el valor de esa característica de seguridad. – chux

+3

@chux no estoy seguro de lo que está tratando de decir. Por supuesto, no es un error si el valor pasado excede el rango de int. – Wiz

+0

Como la respuesta no detalla cómo usar 'strtol()' al intentar convertir a 'int', señalando que las cadenas que representan un valor fuera del rango' int', (pero no 'long') no se configuran 'errno' ni obtener un valor limitado. Este es un comportamiento diferente de las cadenas que representan un valor fuera del rango 'largo ': que establece' errno' y obtiene un valor limitado. – chux

-2

Es llamada atoi. Consulte también Wikipedia para obtener detalles, incluido su sucesor strol.

+7

' atoi' no debe usarse. –

+2

@James McNellis _atoi no debe usarse_ - ha hecho esta afirmación como si su razón fuera obvia, pero como varias respuestas parecen estar de acuerdo en que atoi() es la solución correcta, no debe ser tan obvio. ¿Te gustaría informar a todos sobre por qué sientes que no se debe usar o es mejor dejar un misterio? – mah

+0

@mah: si 'atoi' devuelve' 0', 'INT_MIN', o' INT_MAX', no tiene forma de saber si la conversión tuvo éxito. –

5

El entero no se deja fuera del grupo: hay strtol, que convierte una cadena en long, que es un tipo entero.

0

No pase por alto la sección SEE ALSO de sus páginas de manual :)

SEE ALSO 
     atof(3), atoi(3), atol(3), strtol(3), strtoul(3) 

Usted está buscando atoi(3). :)

+1

En realidad, no lo soy. Lo siento, aclararé mi pregunta. – Eli

+0

@itsmyown, +1 a la pregunta con aclaración :) gracias – sarnold

+0

Bueno, sé que esto es viejo, pero - 'strto [u] l (3)' se menciona en ese 'VER TAMBIEN'! –

2

Esto es lo que he estado usando.

long long_val; 
int int_value; 

errno = 0; 
long_val = strtol (theString, NULL, 10); 
if (errno) 
    handle_error; 
if ((long) someIntMin < long_val || long_val > (long) someIntMax) 
    handle_invalid; 
int_value = (int) long_val; 
+0

'if ((long) someIntMin chux

13

Por qué no hay strtoi en stdlib.h?

A principios de C, no había firmado un tipo estándar más ancha que long y todas las conversiones más estrechos se podría hacer de strtol() - como se hace a continuación.

IMO, estas y sus contrapartes unsigned ahora faltan funciones C y un defecto de diseño en la biblioteca C estándar actual.


En muchos sistemas, long y int tienen el mismo rango y por lo tanto hay una necesidad reducida de un strtoi() separada. Además, el atoi() satisface la necesidad de un código rápido y sucio, pero puede carecer de detección de errores. Tampoco hay un strto_short() ni strto_signchar(), etc.

Es bastante fácil crear un sustituto strtoi(). Simplificaciones existen

#include <errno.h> 
#include <limits.h> 
#include <stdlib.h> 

static long strto_subrange(const char *s, char **endptr, int base, 
    long min, long max) { 
    long y = strtol(s, endptr, base); 
    if (y > max) { 
    errno = ERANGE; 
    return max; 
    } 
    if (y < min) { 
    errno = ERANGE; 
    return min; 
    } 
    return y; 
} 

// OP's goal 
int strtoi(const char *s, char **endptr, int base) { 
    #if INT_MAX == LONG_MAX && INT_MIN == LONG_MIN 
    return (int) strtol(s, endptr, base); 
    #else 
    return (int) strto_subrange(s, endptr, base, INT_MIN, INT_MAX); 
    #endif 
} 

short strtoshort(const char *s, char **endptr, int base) { 
    return (short) strto_subrange(s, endptr, base, SHRT_MIN, SHRT_MAX); 
} 

signed char strtoschar(const char *s, char **endptr, int base) { 
    return (signed char) strto_subrange(s, endptr, base, SCHAR_MIN, SCHAR_MAX); 
} 

Mejora inspirado por @chqrlie

+0

También debe incluir '' – chqrlie

+0

@chqrlie De acuerdo, editado. – chux

Cuestiones relacionadas