stdin流、缓冲区

转载 2016年05月30日 14:57:49

简介
简单来说,是一个专用的文件句柄。解释下句柄(句柄是操作系统在生成对象时分配给对象的唯一标识,句柄不同于指针。如果你得到一个对象的指针,那你就可以对此对象做一切操作!于是系统不给你指针,而是给用户一个加了限制的,用于跟踪对象的指针的标识——句柄!系统使用句柄对外提供服务就相对安全了,操作系统是通过API提供服务的,对于用户来说,句柄等同于对象指针,但实际上句柄和指针不是一回事!)
(stdin)就是标准输入的意思。就是以终端(计算机)为对象;即从键盘输入数据,运行结果到显示器屏幕上(就叫标准输入输出);再来解释下流的概念(流这个概念也解释不通,各种说法都有,反正我就暂理解为数据传输的字节序列吧)实际上,在内存中为每个数据流开辟一个内存缓冲区,用来存放流中的数据。当你向显示器输出数据时比如用(cout<<),现将这些数据送到程序中的输出缓冲区保存,直到缓冲区满了或遇到endl,就将缓冲区的全部数据送到显示器显示出来。在输入时,从键盘输入的数据先放在键盘缓冲区中,当按回车键时,键盘缓冲区中的数据输入到程序的输入缓冲区里。形成cin流。然后用提取预算符提取数据送给程序的有关变量。总之流是与内存缓冲区相对应的,或者说,缓冲区中的数据就是流。

接下来举几个例子说明:

#include<stdio.h>

int main()
{
    char a;
    char b;
    scanf("%c",&a);
    scanf("%c",&b);
    printf("%d %d",a,b);
    return 0;
}

当你在键盘按下q之后,就会打印出结果:
113 10 ( q 的ASCII码是130,换行键的ASCII码是10 )

出现这个原因就是scanf( ) 函数(你要是换成getchar()结果也一样)是从输入流缓冲区里读取值的,而并非是从键盘(也就是终端)缓冲区里读取,当按下q, q先放在键盘缓冲区里,当按下回车后,q以及“\n”进入到输入缓冲区里面,所以第一次q被取走后,第二次读入函数直接从缓冲区里把“\n”取走了。所以在读取成功后,就不会再从终端(键盘)读取,要解决这个的办法就是在第二次读取之前,清空缓冲区的残留数据。

使用fflush(stdin)或者rewind(stdio);都可以起到清空缓冲区的作用,这俩个函数都包含在stdio.h这个头文件中

修改后如下:

#include<stdio.h>

int main()
{
    char a;
    char b;
    scanf("%c",&a);
    fflush(stdin);

    scanf("%c",&b);
    printf("%c %c",a,b);
    return 0;
}

这时候你输入a回车,b回车;就能输出a b;这个结果。
(声明下,是在windows 平台下的vc++测试的程序;)

缓冲区
首先我们知道缓冲区的存在就是为了提高计算机的运算速度的(具体原因就是计算机对缓冲区的操作快于对磁盘的操作)

要知道缓冲区的类型有三个:全缓冲,行缓冲和不带缓冲:
1)全缓冲
在这种情况下,当填满标准I/O缓存后才进行实际I/O操作,全缓冲的典型代表是对磁盘文件的读写。

2)行缓冲
在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键时才进行实际的I/O操作。典型代表就是我在讲的(stdin)和标准输出(sdout)。

3)不带缓冲
也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

大部分系统默认使用以下缓存类型:
1.标准出错是不带缓存的。
2.如果是涉及终端设备的流,则它们是行缓存的,否则是全缓存的。
由于ANSI C对stdin,stdout和stderr的缓存特征没有强行的规定,以至于不同的系统可能有不同的缓存特征。只能说目前主要的缓存特征是:stdin和stdout是行缓存;而stderr是无缓存的。

关于缓冲区的大小问题:
如果我们没有自己设置缓冲区的话,系统会默认为标准输入输出设置一个缓冲区,通常是4096个字节的大小。(这和计算机的分页机制有关,因为进程在计算机中分配内存使用的就是分页与分段机制,并且每个页的大小是4096个字节,因此通常情况下缓冲区的大小为4096个字节。)

最后一点就是关于缓冲区的刷新(就是清空):
下列情况会引起缓冲区的刷新:
1.缓冲区满时;
2.行缓冲区遇到回车时;
3.关闭文件;
4.使用特定函数刷新缓冲区。

参考资料:关于stdin流以及缓冲区浅谈

由getchar()浅谈stdin缓冲区

相信各位使用vs的都遇到过此类状况,当使用getchar()来要使程序暂停运行的时没有达到效果,而程序似乎忽略了getchar()一般直接走完了(黑色运行窗口运行完直接消失) 对于此类函数程序前面都有...

关于stdin流以及缓冲区浅谈

突然觉得

stdin标准输入流

stdin是C中的标准输入流,它是缓冲输入方式。 在程序中,当用户调用stdin相关函数从键盘中获取字符时,函数会先去缓冲区中查看当前是否存在字符。如果存在,则会取出字符;如果不存在,则会中断,...

Linux中带缓冲IO和不带缓冲IO的详细说明

在系统调用的函数中有STDIN_FILENO,和STDOUT_FILENO,STDERR_FILENO,分别对应标准输入(一般使键盘),标准输出(一般使显示器),标准错误,(他们都是非负整数,属于文件...

关于C/C++ stdin缓冲区以及对字符输入的一些经验和心得

关于C/C++ stdin缓冲区以及对字符输入的一些经验和心得在使用C/C++编写控制台应用或acm竞赛的时候,I/O方式无非是标准输入输出,特别是acm竞赛,就本人来说,由C语言入门,输入方式还只会...

C 清空输入缓冲区,以及fflush(stdin)的使用误区和解决方法

对C 语言初学者来说,fflush(stdin)函数被解释为会清空输入缓冲区的一个系统函数,这是一个曾经几乎对过一半的说法,随着计算机科学的进步,在学习的过程中的逐步完善,将fflush(stdin)...
  • hjtcn
  • hjtcn
  • 2017年12月04日 11:23
  • 10

C 清空输入缓冲区,以及fflush(stdin)的使用误区和解决方法

对C 语言初学者来说,fflush(stdin)函数被解释为会清空输入缓冲区的一个系统函数,这是一个曾经几乎对过一半的说法,随着计算机科学的进步,在学习的过程中的逐步完善,将fflush(stdin)...

fflush(stdin) 清除Scanf输入缓冲区

scanf循环输入带来的问题:#include #includeint main(int argc, char* argv[]) { int ival; float fval; ...

验证stderr stdout stdin 缓冲类型和缓冲区大小 以及在重定向后缓冲类型的改变

stdin 和stdout在重定向后缓冲类型有line buffered变为full buffered。 大小因os而已。在SunOs上为1024. R*_*G:uname -a SunOS b...

C 清空输入缓冲区,以及fflush(stdin)的使用误区和解决方法

对C 语言初学者来说,fflush(stdin)函数被解释为会清空输入缓冲区的一个系统函数,这是一个曾经几乎对过一半的说法,随着计算机科学的进步,在学习的过程中的逐步完善,将fflush(stdin)...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:stdin流、缓冲区
举报原因:
原因补充:

(最多只允许输入30个字)