我在网上找了不少资料,但对于rewind(stdin)为什么能够清空缓冲区似乎都没有比较详细的介绍。此贴就本人已搜查到的资料对此过程进行探讨。
首先说一下rewind的定义:rewind 函数将与流 关联的文件指针 重新定位到文件的开头。 (该定义来自微软文档)
那么rewind(stdin)就是将stdin(标准输入流)的指针指向该流文件的开头。
在进行接下来的讨论前,为了更好地理解,我们需要先了解一下缓冲区的部分知识:
系统缓冲区肯定是一个 buffer,用一个指针维护着这个buffer数据,当你读走一个数据时候,指针肯定后移了一个位置,但是数据还是在的,除非再有数据进入缓冲区覆盖掉这个位置上的数据。但是,这些维护buffer的指针值我们肯定访问不到,因此上说,读走一个数据后,即使是还存在的,我们也无法再访问了,等同于数据被读走后就不在了。(该观点来自网络上的资料)
如此,一些问题就解释得通了,例如执行以下代码
#include
int main()
{
char a,b,c;
scanf_s("%c", &a, 1);
rewind(stdin);
scanf_s("%c", &b,1);
printf("%c",b);
rewind(stdin);
while (scanf_s("%c", &c, 1)==1)
{
printf("%c", c);
}
}
如果输入
123456回车
789
程序只会输出789
这是因为将123456以及回车符’n’放进缓冲区后,scanf_s检索缓冲区,发现第一个数据符合格式%c后就将其读入,然后缓冲区的内部指针向后移一位,即将指针指向缓冲区中的2(注意,被读的字符‘1’并不会被删除或者清空,上文已经对此做出了解释)。如果没有rewind(stdin),那么下一个scanf就会读取2,并赋值给变量b,但如果有rewind(stdin),那么指针将被调向数据‘1’,再输入数据会将该数据覆盖掉,这也是为什么会输出7而不是2的原因。
但为什么代码后面的循环没有把未使用的23456输出呢?这里需要区分一个观点:没清除≠没废弃,即使rewind(stdin)把指针指向文件的开头后并没有主动地清除后面的数据,但编译环境可能会自动废弃后面的数据。
这里对此作出猜测:我们知道,缓冲区的刷新会让指针重新调向文件开头,如果这个“动作”没有伴随着数据的废弃,那么如果在第一次要求用户输入五个数据,用户也按要求输入5个数据1 2 3 4 5,第二次输入时就会自动读取上一次的数据,这显然是不合乎我们的认知的,因此,当指针指向文件开头时,编译环境会自动废弃后面的数据,这个规则使得上述问题得以解决。
以上仅仅是我本人在有限的资料上综合自己的看法得出的结论,如果有错误的地方,还望大佬不吝赐教!!



