正文

(转)标准流猜想2005-08-13 00:12:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/billgacsli/3718.html

分享到:

标准流猜想 http://www.programfan.com/club/showbbs.asp?id=93427作者:ccpp网上的cFAQ总说使用fflush(stdin)要谨慎,或者说不应使用。我个人认为只要了解了stdin流的原理,在使用起来应该没有问题。在整理了这些资料的过程中,我发现其中很多理论问题并没有想象的那样难于理解,只是那些“高人”在表述的过程中隐藏了很多的理论细节,或者他们根本自己就不太明白。一下是个人的见解!两大流:标准库的流分为两类:文本流(或称为字符流)和二进制流。正文流把文件看作行的序列,每行包含0 个或多个字符,一行的最后有换行符号'\n'。正文流适合一般输出和输入,包括与人有关的输入输出。二进制流用于把内存数据按内部形式直接存储入文件。二进制流操作保证,在写入文件后再以同样方式读回,信息的形式和内容都不改变。二进制流主要用于程序内部数据的保存和重新装入使用,其操作过程中不做信息转换,在保存或装入大批数据时有速度优势,但这种保存形式不适合人阅读。 进入正题,main()            {            char c1, c2;            scanf("%c", &c1);            scanf("%c", &c2);            printf("c1 is %c, c2 is %c", c2\1, c2);            }运行该程序, 输入AB后回车, 那么输出结果为: c1 is A, c2 is B。如果输入一个字符A后回车 (要完成输入必须回车), 而后就如上直接结束了输出结果为: c1 is A, c2 is   ,变量c2输出的是1个回车符(因为字符A后的回车符赋给了c2)。要解决以上问题, 可以在输入函数前加入清除函数fflush()修改以上程序变成:            #include            main()            {            char c1, c2;            scanf("%c", &c1);            fflush(stdin);/*也可以写成getchar();*/            scanf("%c", &c2);            printf("c1 is %c, c2 is %c", c1, c2);            }此时如果输入一个字符A后回车, 会等待输入下一个字符。fflush(stdin);的作用是清除掉字符A后回车。若使用 getchar();能读掉字符A后回车,达到同样的效果!下面深入说明一下:在程序启动时,会预先定义三个文本流(建立三个文件指针并指定值,但它们不需要显式地打开):  标准输入流(指针名为stdin)、标准输出流(stdout)和标准错误流(stderr)。stdin 通常与操作系统的标准输入连接,stdout 与操作系统的标准输出连接,stderr 通常直接与显示器连接,这说明stderr 不能重新定向(用于输出诊断信息)。在打开时,标准错误流不会完全缓冲;当且仅当流与交互的设备无联系时,标准输入和标准输出流才被完全缓冲(一种常见的方式,与输入设备联系时,比如需要键盘输入数据时,不等输出缓冲区写满就会刷新,此时,就不是完全缓冲)。要把外存文件作为输入输出对象,一个可能方式是通过标准输入输出的重新定向,把标准流转接到指定文件。这样做能解决一些问题。但这种做法有很大局限性,因为这样形成的定向在程序执行期间不能改变。为能在程序中方便地根据需要使用各种文件,就必须利用标准库的文件操作函数,通过为有关文件建立特定输入输出流的方式使用它们。下面我们只研究stdin:1 我们敲击键盘得到的是扫描码,而不是ASCⅡ码。然后按键扫描码进入键盘的缓冲区,接着键入“回车”,连带着回车符一块把数据(扫描码转换ASCⅡ码)送到输入缓冲区(stdin),程序才能开始接收数据,并把未处理的数据留在输入缓冲区(stdin)这样的后果是随后的输入函数继续读入。如果在入缓冲区(stdin)中的内容无用,如上面例子的回车就需要要处理掉。可用 getchar()循环处理,或直接用fflush(stdin)清除。重要结论:在这个过程中必须注意,当程序执行到标准输入函数时,键盘的缓冲区中回车键的扫描码 之前 的其它键扫描码 ,才会被转换ASC Ⅱ码送到输入缓冲区(stdin)而形成文本流。2  而非标准输入函数getche() ,getch()还有bioskey(0).这样的函数在使用时是不需要按“回车”键,也就是说他们直接读取键盘缓冲区的扫描码,这他们的特别之处。如果在使用getch()之前,键盘缓冲区有不需要的扫描码,也得需要清除!(偶编小游戏时会遇到过) void Clear_Key_Buffer(void)//清除键盘缓冲区函数{int offset;offset=peek(0x40,0x1a);pokeb(0x40,0x1c,offset);}3 测试函数,其中注释掉的函数可取出来研究以上的理论。程序运行后,快速连续输入: 1234回车5结果确是:c1= 1, c2= 2, c3= 5, c4= 3#include#include#includevoid Delay(int clicks)/*延迟函数*/{    unsigned int far *clock=(unsigned int far *)0x0000046CL;    unsigned int now;    now=*clock;    while(abs(*clock-now)

阅读(2115) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册