Question

How do I make sure I've got a double and not something else?

int main() {
    int flagOk = 0;
    double number;
    while(!flagOk) {
        printf("Put in a double");
        scanf("%lf", &number);
        if(number == "%lf"); //this want make sure
        flagOk = 1;
    }
}
Was it helpful?

Solution

You probably want a code fragment more like this:

double number;
do {
    printf("Enter a double: ");
    scanf("%*c"); // burn stdin so as not to buffer up responses
} while (1 != scanf("%lf", &number));

However as Jonathan has pointed out, some better line-by-line parsing may be better. Scanning directly from stdin this way isn't intuitive to the user.

OTHER TIPS

Check the return value from scanf(); it tells you how many conversions were successful.

In the context, if the conversion fails, you get 0; if it succeeds, you get 1.

Error recovery needs to be thought about. I usually find it easier to read a line of data using fgets() (and never gets()!) and then process it with sscanf(). It is easy to discard the erroneous data if the conversion fails.

If you want to be sure that the user-anticipated value coincides with the value returned by passing the string to atof ( str ) - including exponent notation - then the following code works.

You can get the input using fgets ( str, size, stdin ), and you don't even have to remove the trailing newline before passing the string to the parser.

Also, if there is a parsing error, the function reports the location of the culpable character to a pointer passed as an additional argument.

There is a long form - easier to read, and a short form - easier to type.

Long form:


/*
    Copyright (C) 2010  S. Randall Sawyer

This code is in the public domain.  It is intended to be usefully illustrative.
It is not intended to be used for any particular application. If this code is
used in any application - whether open source or proprietary, then please give
credit to the author.

*/

#include  <ctype.h>

#define FAILURE (0)
#define SUCCESS (!FAILURE)

enum {
  END_EXPRESSION        = 0x00,
  ALLOW_POINT           = 0x01,
  ALLOW_NEGATIVE        = 0x02,
  REQUIRE_DIGIT         = 0x04,
  ALLOW_EXPONENT        = 0x08,
  HAVE_EXPONENT         = 0x10,
  EXPECT_EXPRESSION     = ALLOW_POINT | ALLOW_NEGATIVE | REQUIRE_DIGIT,
  EXPECT_INTEGER        = ~ALLOW_POINT,
  EXPECT_POS_EXPRESSION = ~ALLOW_NEGATIVE,
  EXPECT_POS_INTEGER    = EXPECT_INTEGER & EXPECT_POS_EXPRESSION,
  EXPECT_EXPONENT       = EXPECT_INTEGER ^ HAVE_EXPONENT,
  EXPONENT_FLAGS        = REQUIRE_DIGIT | ALLOW_EXPONENT | HAVE_EXPONENT
} DoubleParseFlag;

int double_parse_long ( const char * str, const char ** err_ptr )
{
  int ret_val, flags;
  const char * ptr;

  flags = EXPECT_EXPRESSION;
  ptr   = str;

  do  {

    if ( isdigit ( *ptr ) ) {
      ret_val = SUCCESS;
      /*  The '+' here is the key:  It toggles 'ALLOW_EXPONENT' and
          'HAVE_EXPONENT' successively  */
      flags = ( flags + ( flags & REQUIRE_DIGIT ) ) & EXPECT_POS_EXPRESSION;
    }
    else if ( (*ptr & 0x5f) == 'E' )  {
      ret_val = ( ( flags & ( EXPONENT_FLAGS ) ) == ALLOW_EXPONENT );
      flags = EXPECT_EXPONENT;
    }
    else if ( *ptr == '.' ) {
      ret_val = ( flags & ALLOW_POINT );
      flags = ( flags & EXPECT_POS_INTEGER );
    }
    else if ( *ptr == '-' ) {
      ret_val = ( flags & ALLOW_NEGATIVE );
      flags = ( flags & EXPECT_POS_EXPRESSION );
    }
    else if ( iscntrl ( *ptr ) )  {
      ret_val = !( flags & REQUIRE_DIGIT );
      flags = END_EXPRESSION;
    }
    else  {
      ret_val = FAILURE;
      flags = END_EXPRESSION;
    }

    ptr++;

  } while (ret_val && flags);

  if (err_ptr != NULL)
    *err_ptr = ptr - 1;

  return ret_val;
}

Short form:


/*
    Copyright (C) 2010  S. Randall Sawyer

This code is in the public domain.  It is intended to be usefully illustrative.
It is not intended to be used for any particular application. If this code is
used in any application - whether open source or proprietary, then please give
credit to the author.

*/

#include  <ctype.h>

int double_parse_short ( const char * str, const char ** err_ptr )
{
  int ret_val, flags;
  const char * ptr;

  flags = 0x07;
  ptr   = str;

  do  {

    ret_val = ( iscntrl ( *ptr ) ) ? !(flags & 0x04) : (
              ( *ptr == '.' ) ? flags & 0x01 : (
              ( *ptr == '-' ) ? flags & 0x02 : (
              ( (*ptr & 0x5f) == 'E' ) ? ((flags & 0x1c) == 0x08) : (
              ( isdigit ( *ptr ) ) ? 1 : 0 ) ) ) );

    flags =   ( isdigit ( *ptr ) ) ?
                (flags + (flags & 0x04)) & 0x1d : (
              ( (*ptr & 0x5f) == 'E' ) ? 0x0e : (
              ( *ptr == '-' ) ? flags & 0x1d : (
              ( *ptr == '.' ) ? flags & 0x1c : 0 ) ) );

    ptr++;

  } while (ret_val && flags);

  if (err_ptr != NULL)
    *err_ptr = ptr - 1;

  return ret_val;
}

I hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top