为什么scanf需要额外的参数?

scanf takes extra parameter why?

我是 c++ 及其开发的新手,我曾经扫描以获取输入参数。但是我给了两个输入参数。但是程序允许我输入额外的参数。请解释为什么会这样。请在下面找到我使用的代码。

#include <iostream>

int main(int argc, const char * argv[]) {

    int a,b;


    scanf("%i %i ",&a,&b);

    printf("a-> %i",a);
    printf("b-> %i",b);

    return 0;
}

输出(允许40作为额外参数)

20
    30
    40
    a-> 20b-> 30Program ended with exit code: 0

您的格式在第二个 %i 之后有一个 space。 scanf 将读取额外数据以匹配 space。删除 space,它应该会按预期工作。

scanf takes extra parameter why?

这不是一个准确的结论。额外的输入留在输入流中。它没有被 scanf 消耗。它在程序结束时被丢弃。

如果你有另一个 scanf 行,

scanf("%d", &c);

40 将被读入 c

在与 Benjamin Lindley 的评论中讨论后,我想我最初可能误解了问题的意图。

也许问题不在于为什么允许输入第三个输入,而在于为什么需要输入scanf 满足之前的第三个输入。

在那种情况下,我认为@Dale Wilson 的回答基本上是正确的(尽管解释有点短)。

scanf 格式字符串中的 space 意味着 scanf 将跳过 所有 个连续的白色 space。按键盘上的回车键通常被解释为在输入流中输入一个换行符,这被认为是白色 space.

由于格式字符串中的尾部 space,他需要输入一些不是白色的字符space 得到 scanf 到 return,所以即使他不需要或不希望程序读取第三个参数,他也需要输入 一些东西 scanf can/will 识别为输入中 whitespace 的结尾,与格式字符串中的尾随 space 匹配。 "something" 是什么并不重要,除了它不能是 white-space (space, new-line, tab, vertical tab, 可能其他取决于语言环境)。


下面的文字是我最初的回答,但经过讨论和重读,我认为它没有抓住 OP 可能想问的重点,所以虽然它说的是真的,但我怀疑它有多大实际用处.

C 和 C++ 基本上都将标准输入视为一个文件。他们不能(也不会尝试)控制您输入标准输入的数据。他们所能做的就是在阅读数据后决定如何处理这些数据。

在这种情况下,您根本没有要求读取该数据,因此它被忽略了。

程序的标准输入有点像程序是一个人站在繁忙的街道上,周围有数百人。该程序可以听他们说什么或不听他们说什么——但实际上不能做任何事情来阻止他们所有人说话。同样,程序可以读取或不读取某些输入,但无法阻止您输入它不需要或不关心的额外输入。

你写的方式 scanf 是完全错误的,应该避免。

而不是你的scanf

scanf("%i %i ",&a,&b);

你应该使用这个:

scanf("%i%i", &a, &b);

避免在 scanf.

中使用空格或除 %datatype 之外的任何其他内容

您想要的工作代码:

#include <iostream>
using namespace std;
#include <stdio.h>

int main(int argc, const char *argv[]) {
    int a, b;

    scanf("%i%i", &a, &b);

    printf("a-> %i", a);
    printf("b-> %i", b);

    return 0;
}

在 C 中,调用者和被调用者必须就在调用之前压入堆栈的参数数量达成一致。

scanf 也不例外,它采用可变数量的参数,基本上由提供的格式字符串决定。 scanf 扫描格式说明符并期望每个指定格式都有一个对应的变量地址。

在您编写的测试程序中

scanf("%i %i ",&a,&b);

表示从输入缓冲区stdin中取出两个整数,放在a和b的地址上。然而,没有什么可以阻止您在 stdin 中写入更多字符,这些可以通过随后调用 scanf 来读取。

对于键盘输入,通常应避免使用 scanf,而是使用 fgets(),它允许您指定输入的最大大小,然后使用 sscanf() 从缓冲区读取。

char buffer[128];
if (fgets(buffer,sizeof(buffer),stdin) != NULL)
{
  if (sscanf( buffer, "%i %i", &a, &b) == 2)
  {
    printf( "the numbers are %i and %i\n", a,b );
  }
}

请注意,您包含了 C++ header 但根本没有使用它,您可能想要删除该包含或完全更改代码并改用 cin/cout。

虽然 scanf 方便易用,但请注意它

  • 不会为您检查输入参数(因此,您有责任检查用户的输入参数)

因此,当你做

scanf("%i %i ",&a,&b);

scanf 只会 'scan' 进行输入,直到它认为完成为止。

因此,您应该像这样检查输入

if (scanf("%i %i", &a, &b) != 2) {
    /* throw error and exit */
}