如何在C编程语言中确保输入为双精度浮点数

3

我如何确保我得到的是double类型而不是其他类型?

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;
    }
}
3个回答

8

检查scanf()的返回值;它会告诉你成功转换了多少个。

在这种情况下,如果转换失败,你将得到0;如果成功,你将得到1。

需要考虑错误恢复。我通常使用fgets()读取一行数据(绝不使用gets()!),然后用sscanf()处理它。如果转换失败,很容易丢弃错误的数据。


我该如何检查scanf的返回值? - Chris_45
2
请使用以下代码检查scanf的返回值:if (scanf("%lf", &number) != 1) /* error: number is "invalid" */; - pmg

3
如果您想确保用户预期的值与将字符串传递给 atof ( str ) 返回的值相符,包括指数表示法,则以下代码可行。
您可以使用 fgets ( str, size, stdin ) 获取输入,甚至不必在将字符串传递给解析器之前删除尾随换行符。
此外,如果存在解析错误,则该函数会向传递作为附加参数的指针报告有罪字符的位置。
有一种长格式-易于阅读,和一种短格式-易于输入。
长格式:

/*
    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;
}

简短版:


/*
    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;
}


我希望这能对您有所帮助!

3
您可能更需要类似以下代码片段:

```

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

然而,正如Jonathan所指出的那样,更好的逐行解析可能会更好。直接从stdin扫描并不直观易懂。

这个scanf("%*c")是什么意思? - Chris_45
它读取下一个字符 - 可能是换行符,可能是其他字符 - 但实际上不将其分配给任何变量。 - Jonathan Leffler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接