2012-03-17 15 views
18

Necesito comprobar si una cadena C es un entero válido.Determinar si una cadena C es una int válida en C

He intentado tanto

int num=atoi(str); 

y

int res=sscanf(str, "%d", &num); 

Pero el envío de la cadena "8 -9 10" en las dos líneas de regresar simplemente 8, sin indicar la invalidez de esta cadena.

¿Alguien puede sugerir una alternativa?

+0

'atoi' no verifica errores; su comportamiento si 'str' no contiene una representación de un valor' int' no está definido. (Las implementaciones típicas devuelven '0'.)' Sscanf' es mejor, pero su comportamiento no está definido si el valor de la cadena no es representable como 'int'. Además, su título dice que quiere verificar si hay una int válida, pero el cuerpo de su pregunta dice "entero válido"; ellos no son lo mismo 'int' es uno de varios tipos * enteros *. –

Respuesta

29

Eche un vistazo a strtol(), le puede informar acerca de las partes no válidas de la cadena mediante el retorno del puntero.

Y tenga cuidado con el código de ejemplo entusiasta .. consulte la página del manual para la gestión integral de errores.

+0

strtol() simplemente establece el puntero al siguiente "objeto" en la cadena. No valida nada. –

+1

@ g24l Si ese puntero termina apuntando a NULL, entonces sabrá que la cadena completa es válida. Si no, no. Tadaa! – blueshift

+0

Si es una cadena terminada nula. –

8

Tal vez usted increpado por no usar strtol o similares libc funciones, pero el razonamiento sobre este problema no es tan difícil:

#include <stdbool.h> // if using C99... for C++ leave this out. 
#include <ctype.h> 

bool is_valid_int(const char *str) 
{ 
    // Handle negative numbers. 
    // 
    if (*str == '-') 
     ++str; 

    // Handle empty string or just "-". 
    // 
    if (!*str) 
     return false; 

    // Check for non-digit chars in the rest of the stirng. 
    // 
    while (*str) 
    { 
     if (!isdigit(*str)) 
     return false; 
     else 
     ++str; 
    } 

    return true; 
} 

[NB: Yo podría haber hecho otra cosa en lugar de la isdigit(*str++)else a mantenlo más corto pero mi recuerdo es que los estándares dicen que es posible que isdigit sea una macro.]

Supongo que una limitación es que esto no devuelve falso si el número de la cadena no cabe en un número entero. Eso puede o no importarle a usted.

+1

"no tan difícil", pero tenía que volver y cambiarlo;) – blueshift

+1

@blueshift Punto tomado, pero 1 edición en 5 minutos cuando escribir código en un formulario web no es tan malo para mí. :-) – asveikau

+0

En este caso, no sé si es más propenso a errores ejecutar el suyo o intentar obtener el manejo de errores para strtol() correcto ... Probablemente recomiendo strtol. – blueshift

2

Una forma sencilla de hacer esto con firmeza sería leer el int y asegurarse de que es representación de cadena es idéntica a la cadena de entrada, por ejemplo, la combinación de atoi y itoa:

int is_int(char const* p) 
{ 
    return strcmp(itoa(atoi(p)), p) == 0; 
} 
+0

Bonita idea :). Sin embargo, esto requerirá recortar los espacios iniciales y finales también, para que funcione. – sara

+3

Tenga en cuenta que esta solución no cumple con ANSI. –

0

Para comprobar si la cadena contiene una número válido, puede usar una expresión regular. Por ejemplo, para utilizar números enteros:

[- +] [0-9] +

y un caso general para los números de punto flotante:??

[+ -] [0-9] + [ .]? [0-9] * ([eE] [- +]? [0-9] +)?

En el caso de C++ 11 las funciones de expresión regular están disponibles en la biblioteca, p. "std :: regex_match (.....)" da la coincidencia exacta. El código debería tener este aspecto:

#include <regex> 
..... 
std::string strnumber("-1.234e+01"); 
float number; 
if(regex_match(strnumber,std::regex("[+-]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?")) 
number=std::stof(strnumber); 
else 
std::cout<<"error, string is not a valid number"; 
0

Lo siento por desenterrar el tema, pero en aras de la exhaustividad y porque este hilo es el primer partido cuando se hace una búsqueda en Google ...

Es posible usar algo como:

ret = sscanf(string, "%d%n", &number, &idx); 
if (ret == 0 || string[idx] != '\0') 
    /* handle the error */ 

la directiva %n, que parece ser estándar C de acuerdo con la página de manual, que cuenta el número de caracteres procesados.

[Editar] sscanf no parece proporcionar una manera de detectar desbordamientos, por lo que la familia de funciones strtoX debe ser preferida en mi humilde opinión.

Cuestiones relacionadas