-3

Is there an elegant way in C to check if a given string is a "double"? Not if the type of the variable is double, but if the string contains a real number. For example:

char input[50];
printf("please enter a real number: \n");
scanf("%s", input);
if ( is_double(input) ) {
    //user entered "2"
    return true;
    //user entered "2.5"
    return true;
    //user entered "83.5321"
    return true;
    //user entered "w"
    return false;
    //user entered "hello world"
    return false;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Avishay28
  • 2,288
  • 4
  • 25
  • 47

2 Answers2

1

You need to define if 12 or 1e23 are doubles for you. And what about -4z or 12.3, ? So specify what are acceptable and forbidden inputs (hint: using EBNF on paper could be helpful).


Notice that strtod can be used and can give the pointer to the last parsed character.

So (after adding a #include <stdlib.h> near the beginning of your file ....)

char* endp=NULL;
double x = strtod(input, &endp);
if (*endp == 0) { // parsed a number

Also sscanf (you need to include <stdio.h>) returns the number of scanned items, and accepts %n to give current byte offset.

int pos= 0;
double x = 0.0;
if (sscanf(input, "%f%n", &x, &pos)>=1 && pos>0) { // parsed a number

You could also use regexp (regcomp(3) & regexec(3)...) or parse your string manually

Left as an exercise.

PS. Please read carefully the linked documentations.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Trying to use `strtod`, but for some reason I get `x=-var-create: unable to create variable object` in the debugger.. – Avishay28 May 27 '17 at 16:23
  • I don't understand the above comment. Is your *compiler* complaining ? And what is `var` or `create` ? – Basile Starynkevitch May 27 '17 at 16:24
  • The compiler is fine, the variable that get the results of `strtod` is not set properly. I get this message from the debugger. – Avishay28 May 27 '17 at 16:27
  • Then add a `printf` or read the documentation of your debugger or lower the optimization level. I still don't understand what is `var` or `create`. Your question (and my answer) don't mention it. – Basile Starynkevitch May 27 '17 at 16:27
  • Thank you, `strtod` seems like a good solution, I will check why the variable isn't set properly – Avishay28 May 27 '17 at 16:37
1

As long as you aren't allowing scientific notation:

#include <ctype.h>
#include <string.h>
#include <stdbool.h>

bool is_double(const char *input)
{
  unsigned long length = strlen(input);
  int num_periods = 0;
  int num_digits = 0;
  for (unsigned int i = 0; i < length; i++)
  {
    if ( i == 0 )
    {
       if ( input[i] == '-' || input[i] == '+' )
          continue;
    }
    if ( input[i] == '.' )
    {
       if ( ++num_periods > 1 ) return false;
    }
    else
    {
      if (isdigit(input[i]))
      {
         num_digits++;
      }
      else
        return false;
    }
  } /* end for loop */
  if ( num_digits == 0 ) 
      return false;
  else
      return true;
}
Scooter
  • 6,802
  • 8
  • 41
  • 64
  • Consider replacing `if ( num_periods == 0 ) { num_periods = 1; } else return false;` with `if (num_periods++ != 0) return false;`. It's more compact — but doesn't change the functionality. At the moment, the code doesn't handle signs before the number. You explicitly say you don't handle exponents. – Jonathan Leffler May 27 '17 at 17:02