Question

En utilisant uniquement le 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 (i.e float / double)?

Était-ce utile?

La solution

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 nombre entier valide et un nombre à virgule flottant, aucune utilisation pour déterminer le type.

utilisez les fonctions strto {l, ul, ull, ll, d}, car celles-ci définissent 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 <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)

Merci à Jonathan Leffler pour avoir signalé que j'ai oublié de définir errno sur 0 en premier.

Autres conseils

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

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 convertiront ou renverront un 0 s'il ne le peut pas.

Je suis d’accord avec Patrick_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 de groupe ouvert liée (à laquelle je suis allé avant de remarquer que Patrick 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 peut pas ne pas définir ) à 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 bâclé 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 en fonction du contexte.

Je suppose que vous pouvez parcourir la chaîne et vérifier si elle contient des caractères . . C’est pourtant la première chose qui m’est venue à l’esprit, alors je suis sûr qu’il existe d’autres (meilleurs) moyens d’être plus sûr.

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 précisent pas s’ils ont utilisé ou non toute 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 de retour pour le dépassement 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 posez la question.

Si vous souhaitez simplement analyser un nombre et ne savez pas s'il s'agit d'un nombre à virgule flottante ou d'un nombre entier, il suffit d'analyser un nombre à virgule flottante. Un nombre entier sera également correctement analysé.

Si vous souhaitez réellement connaître le type, peut-être pour le triage, envisagez de tester les types dans l'ordre que vous jugez le plus pertinent. Par exemple, essayez d'analyser un entier et si vous ne pouvez pas, essayez d'analyser un float. (L’inverse produira 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 reste est un espace.

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

c'est-à-dire

if(atof(token) != NULL || strcmp(token, "0") == 0)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top