【问题标题】:Check if input is float else stop检查输入是否浮动,否则停止
【发布时间】:2013-08-13 13:26:32
【问题描述】:
scanf("%f", &num);

我必须检查这是否是一个有效的浮点变量,如果它有 @!% 等符号,则停止执行。

建议?

【问题讨论】:

  • man page for scanf 说明它的返回值表示它匹配的值的数量。在您的情况下,如果 num 已设置为有效的 float,则该值为 1
  • 标题中不需要写“In C”,标签已经写好了。
  • 您是否正在寻找一行上的有效浮点数?因为scanf 如果找到一个浮点数,但即使它后面有“东西”,它也会成功检索浮点数。例如,scanf("%f", &num) 将从3.2@#$$% 等输入返回1(读取的浮点数),将3.2 的值放入num。当它到达@ 时,它就会停止读取。如果您需要扫描“东西”以到达下一个浮点数,您将需要一种机制,因为scanf("%f"...) 只会坐在那里,在随后的调用中停留在@,返回0,除非你做别的事。
  • 您应该举例说明哪些输入将被接受和拒绝(如果有)。或者通常你希望你的程序在给定一堆输入的情况下做什么。 (“停止执行”是否意味着您的程序应该退出并显示错误消息?或者scanf() 应该停止扫描?)scanf()strtol() 都不执行“验证”,即它们将接受任何以 a 开头的字符串浮动。

标签: c


【解决方案1】:

scanf 不是你的朋友,在这里。即使您检查结果 确保您成功阅读了一个完整的论点,这不会 真正保证输入在有意义的意义上是有效的。

给定输入:

1!!!1!oneone!

%f 解析将在读取第一个 1 后停止(但成功), 并将读取指针留在以下!。这可能不是什么 您认为“有效输入”。

在这种情况下,请尝试:

if (scanf("%f%c", &f, &c) == 2 && isspace(c))
    /* success */

但是,这将接受以下内容:

1 oneoneonespace!bang

如果同一行中的任何内容都被视为垃圾,那么它会得到 困难,因为scanf 不区分空格和 换行符。也许尝试这样的事情:

char buffer[1024];
if (fgets(buffer, sizeof(buffer), stdin) != NULL)
{
    if (sscanf(buffer, "%f %c", &f, &c) == 1)
        /* success */
}

【讨论】:

    【解决方案2】:

    检查来自scanf() 的返回值。它将返回成功扫描输入的数量 - 在您的情况下,它应该是 1。如果不等于 1,则可能是 -1,表示“文件结束”或 0,表示“输入无效”。

    【讨论】:

      【解决方案3】:

      在 scanf 中使用 %f 说明符不会扫描任何其他内容,如果没有指定浮点数,则不会读取任何内容。你应该检查scanf的返回值。

      有几个定义的返回值:

      EOF = -1
      invalid input = 0
      valid = >0
      

      【讨论】:

        【解决方案4】:

        您无法在scanf 中检查您的两个条件。我建议将整个输入读入一个字符串,寻找特殊字符。一旦此测试通过,请尝试通过sscanf 将其重新处理为字符串。 要搜索特殊字符,在string.h 中定义了一个strpbrk

        char* specials = "%@!";
        char* buffer[SOME_SIZE];
        double value;
        int err;
        
        scanf("%s", buffer);
        if( strpbrk(buffer, specials) ) return SPECIAL_FOUND;
        err = sscanf(buffer, "%f", &value);
        if(err <= 0) return NOT_VALID_INPUT; //NOTE: there should probably be not EOF case
        
        // process your value
        

        注意:我没有检查代码,这是一个粗略的想法。

        【讨论】:

        • strtof() 更好,因为它会告诉它停止解析的位置,您可以使用它来检查 \0
        【解决方案5】:

        您可以检查来自scanf() 的返回值。如果你看this page

        返回值

        成功时,函数返回参数列表中成功填充的项目数。 由于匹配失败、读取错误或到达文件末尾,此计数可能与预期的项目数匹配或更少(甚至为零)

        类似:

        if ( scanf( "%f", &num ) <= 0 )
        {
            // Stop the execution
        }
        // Continue
        

        会做你想做的。

        【讨论】:

          【解决方案6】:

          将您的输入读取为文本,然后使用strtod 库函数将其转换;这允许您检查输入是否包含任何无效字符:

          #include <stdlib.h>
          #include <stdio.h>
          #include <ctype.h>
          ...
          char buf=[81];
          double result = 0.0;
          ...
          if ( fgets( buf, sizeof buf, stdin ) != NULL )
          {
            char *chk;
            double tmp = strtod( buf, &chk );
            if ( isspace( *chk ) || *chk == 0 )
              result = tmp;
            else
              fprintf( stderr, "%s is not a valid floating-point number\n", buf );
          }
          

          在调用strtod 之后,变量chk 将指向字符串中不属于有效浮点常量的第一个字符。如果这个字符是空格或 0,那么你很好;否则你有错误的输入。

          这种方法相对于scanf 的优势在于,如果您的输入仅以一个有效字符开头(例如"1blkjhsdf"),它将转换并分配"1" 并返回一个1,表示转换成功,即使您可能想要拒绝该输入。它还消耗整个输入字符串(假设输入缓冲区足够大),因此它不会在输入流中留下任何垃圾来破坏下一次读取。

          scanf 是一个很好的工具,当您知道您的输入格式正确时可以使用;否则,最好使用上述方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-03-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多