rewind清空缓存的原理

    我在网上找了不少资料,但对于rewind(stdin)为什么能够清空缓冲区似乎都没有比较详细的介绍。此贴就本人已知的知识对此过程进行探讨。

    首先说一下rewind的定义:rewind 函数将与流 关联的文件指针 重新定位到文件的开头。  (该定义来自微软文档)

那么rewind(stdin)就是将stdin(标准输入流)的指针指向该流文件的开头。

  在进行接下来的讨论前,为了更好地理解,我们需要先了解一下缓冲区的部分知识:

系统缓冲区是一个 buffer,用指针维护着这个buffer数据,当你读走一个数据时候,指针肯定后移了一个位置,但是数据还是在的,除非再有数据进入缓冲区覆盖掉这个位置上的数据。但是,这些维护buffer的指针值我们肯定访问不到,因此,计算机读走一个数据后,即使数据是还存在的,我们也无法再访问了,等同于数据被读走后就不在了。

如此,一些问题就解释得通了,例如执行一下代码

#include<stdio.h>

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输出呢?这是因为stdin标准输入流中并非只有一个指针,而是双指针控制输入输出,为了更好地说明问题,用图示进行说明(P start代表起始指针,P end代表结束指针):

输入:123

缓冲区中的结果:

 

    当我们print输入流中的数据时,计算机就会将开始指针到结束指针间的数据进行输出。

    在输出结束后两个指针将会在下一内存单元“汇合”

 

    当我们再次输入数据时,起始指针不动,结束指针后移

例如:输入 45678

 

    注意到缓冲区无法再存储数据,两个指针将再次回到起点

 

而此时再输入数据abc时,将会覆盖先前的数据:

 

    这是在一般情况下缓冲区的处理情况,而我们一旦使用了rewind(stdin)则不管后面是否填满缓冲区,直接将两个指针置至起始处:

输入123 后调用 rewind(stdin)

 

以上就是rewind(stdin)能清空缓存的原因啦~

    但是这种方法并非对所有情况都适用,例如在PTA或者其他刷题平台做题的时候,会发现这样的操作会导致你的数据无法按预期输出,这是因为输出涉及到输出文件,而使用rewind将把文件指针置到起始处,再次输入数据时将会覆盖先前的数据。

所以最好还是使用“笨”办法进行缓冲区的清理:

while ((ch = getchar()) != '\n' && ch != EOF);

    最后提一句,fflush方法在许多环境下已经不支持清空缓存咯,详情可以查阅相关博文,这里就不多做赘述了。

     小叨叨:其实这篇文章在一年前就发表过,不过因为当时本人学识尚浅,有不足之处,如今再次发表,添加了一些解释与补充,希望对你的理解能有帮助!如果文章有其他疏漏,请不吝赐教!

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值