tags:

views:

180

answers:

3

Hi,

Is there a function in C to check if the input is an int, long int, or float? I know C has an isdigit() function, and I can create an isnumeric function as follows:

<blink>
  int isnumeric( char *str )
  {
    while(*str){
       if(!isdigit(*str))
        return 0;   
        str++;
}
    return 1;
}

But I was wondering how to create a function that would take an a floating pt number (as a string) and output a TRUE/FALSE value.

Thanks, Marcus

A: 
int isnumeric( char *str )
{
    double d;
    return sscanf(str, "%lf", &d);
}
Marcelo Cantos
warning: format ‘%g’ expects type ‘float *’, but argument 3 has type ‘double *’
Alfred
@Alfred, thanks for pointing that out.
Marcelo Cantos
+10  A: 

This should do it. It converts the string to floating point using strtod and checks to see if there is any more input after it.

int isfloat (const char *s)
{
     char *ep = NULL;
     double f = strtod (s, &ep);

     if (!ep  ||  *ep)
         return false;  // has non-floating digits after number, if any

     return true;
}

To distinguish between floats and ints is trickier. A regex is one way to go, but we could just check for floating chars:

int isfloat (const char *s)
{
     char *ep = NULL;
     long i = strtol (s, &ep);

     if (!*ep)
         return false;  // it's an int

     if (*ep == 'e'  ||
         *ep == 'E'  ||
         *ep == '.')
         return true;

     return false;  // it not a float, but there's more stuff after it
}

Of course, a more streamlined way to do this is to return the type of the value and the value together.

wallyk
+1 for detecting 'e' and 'E' as well
Xinus
Or implement isint() in similar fashion and then, at the end of isfloat, use `return !isint(s)` instead of `return true`.
Marcelo Cantos
A: 

If your goal is to find the data type a given string can fit in, you can do something like this:

#include <stdlib.h>
#include <stdio.h>
#include <float.h>
#include <limits.h>
#include <errno.h>
#include <math.h>

/* If a floating-point number is +/- F_EPS from an integer,
   consider it to be an integer */
#define F_EPS 1e-7

enum datatype {
    TYPE_INT,
    TYPE_LONG,
    TYPE_FLOAT,
    TYPE_DOUBLE,
    TYPE_INVALID
};

enum datatype findtype(const char *s)
{
    char *eptr;
    double d;
    double diff;

    errno = 0;

    d = strtod(s, &eptr);
    if ((d == 0 && eptr == s) || errno == ERANGE)
        return TYPE_INVALID;

    diff = d - floor(d+0.5);
    if (d <= INT_MAX && d >= INT_MIN && diff <= F_EPS)
        return TYPE_INT;

    if (d <= LONG_MAX && d >= LONG_MIN && diff <= F_EPS)
        return TYPE_LONG;

    if ((d > 0 && (d > FLT_MAX || d < FLT_MIN))
                || (d < 0 && (d < -FLT_MAX || d > -FLT_MIN)))
        return TYPE_FLOAT;

    return TYPE_DOUBLE;
}

The idea is that you read the number as a double, and then check to see if it is in the range for different types. You can change F_EPS above to control the tolerance.

Alok