Scanf需要额外的参数

scanf takes extra parameter why?

本文关键字:参数 Scanf      更新时间:2023-10-16

我是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

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

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

如果你有另一个scanf行,

scanf("%d", &c);

40将被读入c

在第二个%i之后有一个空格。scanf将读取额外的数据来匹配空间。删除空格,它应该像你期望的那样工作。

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

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

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

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

对于格式字符串中的尾随空格,他需要输入一些而不是空白的字符来让scanf返回,所以即使他不需要或不希望程序读取第三个参数,他需要输入一些, scanf可以/将识别为与格式字符串中的尾随空格匹配的输入中的空白的结束。"某些东西"是什么并不重要,重要的是它不能是空白(空格、新行、制表符、垂直制表符,根据语言环境可能还有其他)。


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

C和c++基本上都将标准输入视为文件。它们不能(也不会试图)控制您在标准输入中输入的数据。他们所能做的就是在读取数据后决定如何处理(如果有的话)。

在本例中,您根本没有请求读取该数据,因此它被忽略了。

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

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

代替你的scanf:

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

你应该这样写:

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

避免使用空格或scanf中%数据类型以外的任何其他内容。

您想要的工作代码:

#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 %in", a,b );
  }
}

请注意,您包含了一个c++头文件,但根本没有使用它,您可能想要删除该包含或完全更改代码,并使用cin/cout来代替。

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

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

因此,当你执行

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

scanf将只'扫描'输入,直到它认为它已经完成。

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

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