Déterminer si une chaîne est un entier ou un float dans ANSI C

En utilisant uniquement ANSI C, quel est le meilleur moyen de déterminer, avec une certitude raisonnable, si une chaîne de style C est un entier ou un nombre réel (c’est-à-dire float / double)?

N’utilisez pas atoi et atof car ces fonctions renvoient 0 en cas d’échec. La dernière fois que j’ai vérifié, 0 est un entier valide et un flottant, donc aucune utilisation pour déterminer le type.

utilisez les fonctions strto {l, ul, ull, ll, d}, car celles-ci initialisent errno en cas d’échec et indiquent également où les données converties se sont terminées.

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

Cet exemple suppose que la chaîne contient une seule valeur à convertir.

#include  char* to_convert = "some ssortingng"; 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) 

Merci à Jonathan Leffler pour m’avoir signalé que j’avais oublié de mettre errno à 0 en premier.

Avec sscanf , vous pouvez être certain que la chaîne est un float, int ou autre, sans avoir à utiliser le cas spécial 0, comme c’est le cas avec atoi et atof.

Voici un exemple de code:

 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 et atof vont convertir ou renvoyer un 0 s’il ne le peut pas.

Je suis d’accord avec Pasortingck_O pour dire que les fonctions strto {l, ul, ull, ll, d} sont la meilleure voie à suivre. Il y a cependant quelques points à surveiller.

  1. Définissez errno sur zéro avant d’appeler les fonctions; aucune fonction ne le fait pour vous.
  2. La page Open Group liée à (à laquelle je suis allé avant de remarquer que Pasortingck y avait également un lien) indique que errno pourrait ne pas être défini. Il est défini sur ERANGE si la valeur est hors limites; il peut être défini (mais également ne pas l’ être) sur EINVAL si l’argument n’est pas valide.

En fonction du travail à effectuer, je vais parfois m’arrêter pour ignorer les espaces à la fin du pointeur de fin de conversion renvoyé, puis me plaindre (rejeter) si le dernier caractère n’est pas le caractère nul final ‘\ 0’. Ou je peux être négligé et laisser les ordures apparaître à la fin, ou je peux accepter des multiplicateurs optionnels tels que ‘K’, ‘M’, ‘G’, ‘T’ pour des kilo-octets, des mégaoctets, des gigaoctets, … ou tout autre exigence basée sur le contexte.

Je suppose que vous pouvez parcourir la chaîne et vérifier s’il en existe . personnages dedans. Ce n’est cependant que la première chose qui m’arrive à l’esprit, alors je suis sûr qu’il existe d’autres (meilleurs) moyens d’être plus certains.

Utilisez strtol / strtoll (not atoi) pour vérifier les entiers. Utilisez strtof / strtod (not atof) pour vérifier les doublons.

atoi et atof convertissent la partie initiale de la chaîne, mais ne vous disent pas s’ils ont utilisé ou non la totalité de la chaîne. strtol / strtod vous indique s’il y a eu des fichiers indésirables après la conversion des caractères.

Donc, dans les deux cas, n’oubliez pas de passer un paramètre TAIL non nul et de vérifier qu’il pointe vers la fin de la chaîne (c’est-à-dire, ** TAIL == 0). Vérifiez également la valeur renvoyée pour les dépassements supérieur et inférieur (voir les pages de manuel ou la norme ANSI pour plus de détails).

Notez également que strod / strtol ignore les espaces blancs initiaux. Par conséquent, si vous souhaitez traiter les chaînes dont les espaces blancs sont mal formatés, vous devez également vérifier le premier caractère.

Cela dépend vraiment de la raison pour laquelle vous demandez en premier lieu.

Si vous souhaitez simplement parsingr un nombre et ne savez pas s’il s’agit d’un entier ou d’un flottant, il suffit d’parsingr un flottant pour qu’il parsing correctement un entier.

Si vous voulez réellement connaître le type, peut-être pour le sorting, vous devriez alors envisager de tester les types dans l’ordre que vous jugez le plus pertinent. C’est comme essayer d’parsingr un entier et si vous ne pouvez pas, essayer d’parsingr un float. (À l’inverse, il ne restra qu’un peu plus de flotteurs …)

atoi et atof convertissent le nombre même s’il y a des caractères de fin non numériques. Cependant, si vous utilisez strtol et strtod, non seulement les espaces et le signe facultatif seront ignorés, mais un pointeur sur le premier caractère ne se trouvant pas dans le nombre. Ensuite, vous pouvez vérifier que le rest est un espace.

Eh bien, si vous ne souhaitez pas utiliser une nouvelle fonction telle que strtoul, vous pouvez simplement append une autre instruction strcmp pour voir si la chaîne est 0.

c’est à dire

 if(atof(token) != NULL || strcmp(token, "0") == 0)