¿Cómo puedo saber si la función c atoi falló o si fue una cadena de ceros?

StackOverflow https://stackoverflow.com/questions/1640720

  •  08-07-2019
  •  | 
  •  

Pregunta

Al usar la función atoi (o strtol o funciones similares para el caso), ¿cómo puede saber si la conversión de enteros falló o si la cadena C fue ser convertido fue un 0 ?

Por lo que estoy haciendo, 0 es un valor aceptable y la cadena C que se está convirtiendo puede contener cualquier número de 0 s. También puede tener espacios en blanco principales.

¿Fue útil?

Solución

Para C ++ 11 y posterior:

La función go-to para la conversión de cadena a entero ahora es stoi , que toma una cadena y devuelve un int , o arroja una excepción en caso de error.

Ya no es necesario el truco detallado istringstream mencionado en la respuesta aceptada.

(También hay stol / stoll / stof / stod / stold para long / long long / float / double / long double , respectivamente .)

Otros consejos

La función adecuada (siempre y cuando insista en usar funciones de estilo C) es strtol y el código de conversión puede verse de la siguiente manera

const char *number = "10"; /* for example */

char *end;
long value = strtol(number, &end, 10); 
if (end == number || *end != '\0' || errno == ERANGE)
  /* ERROR, abort */;

/* Success */
/* Add whatever range checks you want to have on the value of `value` */

Algunas observaciones:

strtol permite (es decir: salta silenciosamente) espacios en blanco delante del número real. Si desea tratar ese espacio en blanco principal como un error, debe verificarlo usted mismo.

La comprobación de * end! = '\ 0' asegura que no haya nada después de los dígitos. Si desea permitir otros caracteres después del número real (espacio en blanco?), Esta verificación debe modificarse en consecuencia.

P.S. Agregué la verificación end == number más tarde para capturar secuencias de entrada vacías. " Todos los espacios en blanco " y "ningún número en absoluto" las entradas habrían sido capturadas por * end! = '\ 0' solo. Sin embargo, podría tener sentido captar entradas vacías de antemano. En ese caso, la verificación end == number será / podría ser innecesaria.

Dado que esto está etiquetado :

template< typename T >
inline T convert(const std::string& str)
{
    std::istringstream iss(str);
    T obj;

    iss >> std::ws >> obj >> std::ws;

    if(!iss.eof())
        throw "dammit!";

    return obj; 
}

Desde la página del manual para strtol ():

  

Si endptr no es NULL, strtol () almacena la dirección del primer inválido        carácter en * endptr. Sin embargo, si no hubiera dígitos, strtol ()        almacena el valor original de nptr en * endptr. (Por lo tanto, si * nptr no es         '\ 0' pero ** endptr es '\ 0' en la devolución, toda la cadena era válida.)

Una alternativa a strtol es sscanf , aunque es un poco pesado:

const char *numStr = "12345";  // input string
int value;
if(sscanf(numStr, "%d", &value) == 1)
    ;  // parsing succeeded, use value
else
    ;  // error

Sin embargo, esto permite espacios en blanco iniciales en su cadena (lo que puede o no ser deseable), y permite que cualquier cosa rastree el número, por lo que "123abc" sería aceptado y devolvería 123. Si desea tener un control más estricto, vaya con strtol () , como AndreyT demuestra .

Ha pasado un tiempo desde que lo hice y C / C ++, pero me parece que la solución (demasiado) simple sería verificar solo la cadena para "0".

int value = atoi(string_number.c_str());

if ( !value && string_number != "0" ) {
  // error
} else {
  // great success!
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top