scanf 是否在读取输入数据后清空缓冲区(在 C 中)?

Does the scanf empty the buffer after reading the input data (in C)?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char buf[1024];
    int a,b;
    int i;
    
    setbuf(stdin, buf);
    scanf("%d %d", &a, &b);
    
    for(i=0; buf[i]!='\n'; i++){
        putchar(buf[i]);  
    }
    
    putchar('\n');

    return 0;
}

当我输入值1 2时,我使用setbuf来确定读取值后是否真的清除了缓冲区。
但是,当我打印出 buf 时,我输入的值在 buf 中保持不变。也就是说,输出是 1 2

为什么会这样?
如果你能回答我将不胜感激。

整理评论中的内容,不能保证 libc 实现会清除 stdin 缓冲区。 FILE 结构可以只保留一个指向它在缓冲区中的当前位置的指针。

此外,您需要将缓冲区的大小更改为 BUFSIZ 并使其生命周期适用于程序的其余部分。根据 C11 standard:

The buffer has to have a lifetime at least as great as the open stream, so the stream should be closed before a buffer that has automatic storage duration is deallocated upon block exit.

这可以通过使缓冲区成为全局缓冲区或将其声明为 static:

来实现
static char buf[BUFSIZ];

这是 C 标准关于函数的说法 setbuf:

7.21.5.5 The setbuf function

Synopsis

#include <stdio.h>
void setbuf(FILE * restrict stream,
            char * restrict buf);

Description

Except that it returns no value, the setbuf function is equivalent to the setvbuf function invoked with the values _IOFBF for mode and BUFSIZ for size, or (if buf is a null pointer), with the value _IONBF for mode.

Returns
The setbuf function returns no value.

7.21.5.6 The setvbuf function

Synopsis

#include <stdio.h>
int setvbuf(FILE * restrict stream,
            char * restrict buf,
            int mode, size_t size);

Description

The setvbuf function may be used only after the stream pointed to by stream has been associated with an open file and before any other operation (other than an unsuccessful call to setvbuf) is performed on the stream. The argument mode determines how stream will be buffered, as follows: _IOFBF causes input/output to be fully buffered; _IOLBF causes input/output to be line buffered; _IONBF causes input/output to be unbuffered. If buf is not a null pointer, the array it points to may be used instead of a buffer allocated by the setvbuf function277) and the argument size specifies the size of the array; otherwise, size may determine the size of a buffer allocated by the setvbuf function. The contents of the array at any time are indeterminate.

Returns

The setvbuf function returns zero on success, or nonzero if an invalid value is given for mode or if the request cannot be honored.


277) 缓冲区的生命周期必须至少与打开的流一样长,因此在块退出时释放具有自动存储持续时间的缓冲区之前应关闭流。

由此可见:

  • 您代码中的数组 buf 的长度应为 BUFSIZ,可以不同于 1024
  • 这个数组不应该有自动存储class因为stdin在函数mainreturns之前没有关闭。应该定义为static char buf[BUFSIZ];
  • 流处理函数可能使用也可能不使用缓冲区。
  • 数组的内容在任何时候都是不确定的,因此不能对缓冲区内容有任何期望:您观察到用户输入存在,但这不能保证.大多数实现在 FILE 结构中都有指针或偏移量,以跟踪缓冲区的已用和可用部分。
  • 流处理函数 清除 读取字节后的缓冲区内容的可能性很小,因为如果要查找以前的内容,则需要从文件重新加载缓冲区, 但同样也不能保证这一点。

setbuf 是一个用途有限的遗留函数,setvbuf 优于 select 缓冲模式和缓冲区大小,在极少数情况下它可能有用。