理解scanf()函数

时间:2016-09-03 23:14:46

标签: c scanf

我试图弄清楚我的输入是否为数字,我找到了这个例子:

namespace a
{   
    class b<T>
    {
        struct MyStruct 
        {
            int value1;
            int value2;
        }

        unsafe void SomeMethod()
        {
            MyStruct* ptr; // gives a compiler error
        }
    }
}

我在网上搜索但我没有找到任何解释。为什么它不是一个整数(这是否意味着你的输入包含字母表?)如果你scanf()一个整数并且等于0?

5 个答案:

答案 0 :(得分:3)

可能没有任何关于代码的解释:

while ( (scanf ("%d", &number) ) == 0) {
     printf("Entered value is not integer");
}

因为没有一个很好的解释。这是多方面的不良代码,其中一些已被其他答案所涵盖,但其中一些尚未被提及。

新问题是:

  1. 如果scanf()报告为0,则程序进入无限循环。被拒绝的角色不属于数字&#39;在下一个周期中仍然不是数字的一部分,所以scanf()将一直返回0,直到程序以某种方式中断。

    你可以通过吃(至少)剩余输入的第一个字符来解决这个问题。在读取下一个换行符之前,最好吃掉所有字符。毕竟,如果用户输错了数字,那么该行上的任何其他内容都不是他们想要输入的内容。

  2. 诊断消息不以换行符结束,因此在生成足够的消息副本以填充标准输出缓冲区之前,它可能不会出现,因此会出现许多消息副本。您可能无法看到此行为,因为标准输入和标准输出流可能会同步,以便在输入操作之前刷新任何挂起的输出,但它不可靠。

    < / LI>

    然后是其他人提到的无聊的东西:

    1. scanf()函数可能返回EOF,或0或1(因为只有一个转换规范)。如果它返回EOF,你有另一个无限循环的原因:每次调用它都会返回EOF,但代码不会对信息作出反应。

      通常,检测scanf()工作的正确方法是检查返回值是否应返回预期值的数量(有效转换规范的数量 - 您不计算有效转换规范的数量中%*d%n%%有效可能不是最好的词,但现在就足够了)

    2. 将这些问题的修复程序放在一起,您可能会到达:

      int rc;
      while ((rc = scanf("%d", &number)) != 1)
      {
          if (rc == EOF)
          {
              printf("EOF detected without a number\n");
              break;  // return, exit, ...
          }
          printf("Entered value is not an integer: ");
          int c;
          while ((c = getchar()) != EOF && c != '\n')
              putchar(c);
          putchar('\n');
          // Optionally fflush(stdout);
      }
      

      请参阅Using fflush(stdin),了解为什么我没有使用fflush(stdin)代替循环。您可能不希望回显无效条目,在这种情况下,您可以仅使用分号替换putchar(c);(并在之前调整错误消息,以及之后调整putchar('\n');),但它通常可以帮助人们如果他们看到程序认为他们输入了什么,就能理解他们做错了什么。您可能想要考虑是否应将错误消息写入标准错误而不是标准输出。如果getchar()返回EOF,则scanf()的下一次迭代也将返回EOF,以便处理该案例。请注意,使用int c; - getchar()会返回int,而不是字符。

答案 1 :(得分:0)

正如man page中所述,如果匹配失败,scanf()会重新调整0.换句话说,scanf()会返回成功匹配的数量。

  

这些函数返回成功匹配和分配的输入项的数量,可以少于提供的数量,或者在早期匹配失败的情况下甚至为零。

如果是%d格式说明符,则输入的值为char,即不匹配int )匹配失败并且{ {1}}返回0.

因此,底线是,scanf()的返回值表示输入不正确且扫描失败。还提到,0的预期值的赋值失败了,留下了为所提供的参数使用不确定值的可能性。

答案 2 :(得分:0)

如果用户给出整数,则scanf将返回1 [成功扫描的变量的数量],否则返回0.

此处已有: Value returned by scanf function in c

顺便说一下代码是不正确的,好像EOF到达那么它也会显示“.. not inte ...”,因为scanf将返回-1 [also!= 0]。

答案 3 :(得分:0)

请参阅Value returned by scanf function in c

  

成功时,该函数会成功返回项目数   读。此计数可以匹配预期的读数或更少,   如果发生匹配故障,则均为零。在输入的情况下   在成功读取任何数据之前失败,返回EOF。

  • 如果成功读取数字,则返回1.循环结束。
  • 如果它无法读取任何内容(可能是由于EOF),则返回EOF,即-1。循环结束。
  • 如果它读取了某些内容,但无法将其转换为整数,则返回0,循环继续。

答案 4 :(得分:0)

来自man page for scanf

  

成功完成后,这些函数将返回成功匹配和分配的输入项的数量

  

输入项应定义为输入字节的最长序列(直到任何指定的最大字段宽度,可以用字符或字节来衡量,取决于转换说明符),它是匹配序列的初始子序列。输入项之后的第一个字节(如果有)将保持未读。如果输入项的长度为0,则转换规范的执行将失败;此条件是匹配失败,除非文件结束,编码错误或读取错误阻止了流的输入,在这种情况下它是输入失败。

在您的情况下,输入说明符是&#34;%d&#34;,Matches an optionally signed decimal integer...。因此,如果第一个字符(跳过任何空格后)是一个数字(或+/-符号),这将转换数字(一个或多个数字),当它看到任何非数字字符时停止。返回值是转换值的数量,如果找到有效的十进制数,则为1,如果没有,则为0。

请注意结果可能与您的预期不符,例如:

  

-4-羟基

将转换数字4并返回1,即使它看起来不是输入的意图。类似1337age,对于&#34; leetage&#34;,会转换数字1337.我经常使用如下代码片段来避免这种情况:

char dummy;
int conversions = scanf("%d%c", &number, &dummy);
if ((conversions != 1) && ((conversion != 2) || !isspace(dummy)))
    printf("Entered value is not an integer.\n");