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
在函数main
returns之前没有关闭。应该定义为static char buf[BUFSIZ];
- 流处理函数可能使用也可能不使用缓冲区。
- 数组的内容在任何时候都是不确定的,因此不能对缓冲区内容有任何期望:您观察到用户输入存在,但这不能保证.大多数实现在
FILE
结构中都有指针或偏移量,以跟踪缓冲区的已用和可用部分。
- 流处理函数 清除 读取字节后的缓冲区内容的可能性很小,因为如果要查找以前的内容,则需要从文件重新加载缓冲区, 但同样也不能保证这一点。
setbuf
是一个用途有限的遗留函数,setvbuf
优于 select 缓冲模式和缓冲区大小,在极少数情况下它可能有用。
#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
functionSynopsis
#include <stdio.h> void setbuf(FILE * restrict stream, char * restrict buf);
Description
Except that it returns no value, the
setbuf
function is equivalent to thesetvbuf
function invoked with the values_IOFBF
formode
andBUFSIZ
forsize
, or (ifbuf
is a null pointer), with the value_IONBF
formode
.Returns
Thesetbuf
function returns no value.
7.21.5.6 The
setvbuf
functionSynopsis
#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 bystream
has been associated with an open file and before any other operation (other than an unsuccessful call tosetvbuf
) is performed on the stream. The argumentmode
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. Ifbuf
is not a null pointer, the array it points to may be used instead of a buffer allocated by thesetvbuf
function277) and the argumentsize
specifies the size of the array; otherwise,size
may determine the size of a buffer allocated by thesetvbuf
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 formode
or if the request cannot be honored.
277) 缓冲区的生命周期必须至少与打开的流一样长,因此在块退出时释放具有自动存储持续时间的缓冲区之前应关闭流。
由此可见:
- 您代码中的数组
buf
的长度应为BUFSIZ
,可以不同于1024
。 - 这个数组不应该有自动存储class因为
stdin
在函数main
returns之前没有关闭。应该定义为static char buf[BUFSIZ];
- 流处理函数可能使用也可能不使用缓冲区。
- 数组的内容在任何时候都是不确定的,因此不能对缓冲区内容有任何期望:您观察到用户输入存在,但这不能保证.大多数实现在
FILE
结构中都有指针或偏移量,以跟踪缓冲区的已用和可用部分。 - 流处理函数 清除 读取字节后的缓冲区内容的可能性很小,因为如果要查找以前的内容,则需要从文件重新加载缓冲区, 但同样也不能保证这一点。
setbuf
是一个用途有限的遗留函数,setvbuf
优于 select 缓冲模式和缓冲区大小,在极少数情况下它可能有用。