Pregunta

Usando solo ANSI C, ¿cuál es la mejor manera de, con bastante certeza, determinar si una cadena de estilo C es un número entero o real (es decir, flotante/doble)?

¿Fue útil?

Solución

No utilice atoi y atof ya que estas funciones devuelven 0 en caso de falla.La última vez que verifiqué, 0 es un número entero válido y flotante, por lo tanto, no sirve para determinar el tipo.

use las funciones strto{l,ul,ull,ll,d}, ya que configuran errno en caso de falla y también informan dónde terminaron los datos convertidos.

strtoul: http://www.opengroup.org/onlinepubs/007908799/xsh/strtoul.html

este ejemplo supone que la cadena contiene un único valor que se va a convertir.

#include <errno.h>

char* to_convert = "some string";
char* p = to_convert;
errno = 0;
unsigned long val = strtoul(to_convert, &p, 10);
if (errno != 0)
    // conversion failed (EINVAL, ERANGE)
if (to_convert == p)
    // conversion failed (no characters consumed)
if (*p != 0)
    // conversion failed (trailing data)

Gracias a Jonathan Leffler por señalar que primero olvidé establecer errno en 0.

Otros consejos

Usando sscanf, puede estar seguro de si la cadena es flotante o int o lo que sea sin tener que utilizar el caso especial 0, como es el caso de la solución atoi y atof.

Aquí hay un código de ejemplo:

int i;
float f;
if(sscanf(str, "%d", &i) != 0) //It's an int.
  ...
if(sscanf(str "%f", &f) != 0)  //It's a float.
  ...

atoi y atof convertirán o devolverán un 0 si no pueden.

Estoy de acuerdo con Patrick_O en que las funciones strto{l,ul,ull,ll,d} son la mejor manera de hacerlo.Sin embargo, hay un par de puntos a tener en cuenta.

  1. Establezca errno en cero antes de llamar a las funciones;ninguna función hace eso por ti.
  2. La página de Open Group vinculada (a la que fui antes de darme cuenta de que Patrick también la había vinculado) señala que es posible que no se haya configurado errno.Se establece en ERANGE si el valor está fuera de rango;él puede establecerse (pero igualmente, puede no establecerse) a EINVAL si el argumento no es válido.

Dependiendo del trabajo en cuestión, a veces hago arreglos para omitir el espacio en blanco final desde el final del puntero de conversión devuelto y luego me quejo (rechazo) si el último carácter no es el nulo final '\0'.O puedo ser descuidado y dejar que aparezca basura al final, o puedo aceptar multiplicadores opcionales como 'K', 'M', 'G', 'T' para kilobytes, megabytes, gigabytes, terabytes,...o cualquier otro requisito basado en el contexto.

Supongo que podrías recorrer la cadena y comprobar si hay alguna. . personajes en él.Eso es sólo lo primero que me vino a la cabeza, así que estoy seguro de que hay otras (mejores) formas de estar más seguro.

Utilice strtol/strtoll (no atoi) para comprobar los números enteros.Utilice strtof/strtod (no atof) para comprobar los dobles.

atoi y atof convierten la parte inicial de la cadena, pero no le dicen si usaron toda la cadena o no.strtol/strtod le indica si hubo basura adicional después de la conversión de los personajes.

Entonces, en ambos casos, recuerde pasar un parámetro TAIL no nulo y verifique que apunte al final de la cadena (es decir, **TAIL == 0).También verifique el valor de retorno para desbordamiento y desbordamiento (consulte las páginas de manual o el estándar ANSI para obtener más detalles).

Tenga en cuenta también que strod/strtol omite los espacios en blanco iniciales, por lo que si desea tratar las cadenas con espacios en blanco iniciales como mal formateadas, también debe verificar el primer carácter.

Realmente depende de por qué preguntas en primer lugar.

Si solo desea analizar un número y no sabe si es un número flotante o un número entero, simplemente analice un número flotante y también analizará correctamente un número entero.

Si realmente desea conocer el tipo, tal vez para realizar una clasificación, entonces debería considerar probar los tipos en el orden que considere más relevante.Por ejemplo, intente analizar un número entero y, si no puede, intente analizar un flotante.(Al revés solo se producirán un poco más de flotadores...)

atoi y atof convertirán el número incluso si hay caracteres no numéricos al final.Sin embargo, si usa strtol y strtod, no solo omitirá los espacios en blanco iniciales y un signo opcional, sino que también lo dejará con un puntero al primer carácter que no esté en el número.Luego puedes comprobar que el resto son espacios en blanco.

Bueno, si no tiene ganas de usar una nueva función como strtoul, puede simplemente agregar otra instrucción strcmp para ver si la cadena es 0.

es decir.

if(atof(token) != NULL || strcmp(token, "0") == 0)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top