谈一谈getchar()、EOF和Ctrl+D
2015-07-10 16:31
344 查看
getchar()
getchar从stdio流中读字符,getchar有一个int型的返回值.当程序调用getchar时.程序就等着用户按键.用户输入的字符被存放在键盘缓冲区中.直到用户按回车为止(回车字符也放在缓冲区中).当用户键入回车之后,getchar才开始从stdio流中每次读入一个字符.getchar函数的返回值是用户输入的第一个字符的ASCII码,如出错返回-1,且将用户输入的字符回显到屏幕.如用户在按回车之前输入了不止一个字符,其他字符会保留在键盘缓存区中,等待后续getchar调用读取.也就是说,后续的getchar调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完为后,才等待用户按键。[以上定义来自百度百科]EOF
计算机术语,缩写通常为EOF(End Of File),在操作系统中表示资料源无更多的资料可读取。资料源通常称为档案或串流。在C语言中,或更精确地说成C标准函数库中表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~255,不可能出现-1,因此可以用EOF作为文件结束标志。
在 UNIX中, EOF表示能从交互式 shell (终端) 送出 Ctrl+D (习惯性标准)。在微软的 DOS 与 Windows 中能送出 Ctrl+Z。在控制台要输入eof的话 按ALT+65535就可以了。[以上概念来自百度百科]
所以,EOF并不属于文件内容的一部分,它只是读不到更多内容时返回的结束标志。
看一个例子
1、#include<stdio.h> int main() { int a; while((a=getchar())!=EOF) { printf("a=%d\n",a); } printf("end:%d\n",a); return 0; }
下面是几种不同情况下的输出:
(1)直接按Ctrl+D后,getchar()返回-1,退出
(2)输入一串字符后,再按Ctrl+D
所有字符被从缓冲区读出,与按回车不同的是,回车也会被送入缓冲,但Ctrl+D没有在缓冲区中体现出来。本来想,如同(1)一样,Ctrl+D相当于EOF(-1),在输出所有字符后,getchar()会遇到EOF输出-1的。
(3)输入一串字符后,连续按两次Ctrl+D
最后会得到-1,退出循环。
既然getchar()是从缓冲区中读字符,而根据(2)Ctrl+D是没有放入缓冲区的,为什么按两次Ctrl+D就会输出-1呢?
在网上查到的解释如下:
输入缓冲是行缓冲。当从键盘上输入一串字符并按回车后,这些字符会首先被送到输入缓冲区中存储。每当按下回车键后,就会检测输入缓冲区中是否有了可读的数据。还会对键盘上是否有作为流结束标志的 Ctrl+Z(windows) 或者 Ctrl+D 键 按下作出检查,其检查的方式有两种:阻塞式以及非阻塞式。
阻塞式检查方式指的是只有在回车键按下之后才对此前是否有 Ctrl+Z 组合键按下进行检查,非阻塞式样指的是按下 Ctrl+ D 之后立即响应的方式。如果在按 Ctrl+D 之前已经从键盘输入了字符,则 Ctrl+D的作用就相当于回车(但是回车自己也会进入缓冲),即把这些字符送到输 入缓冲区供读取使用,此时Ctrl+D不再起流结束符的作用。如果按 Ctrl+D 之前没有任何键盘输入,则 Ctrl+D 就是流结束的信号。
Windows系统中一般采用阻塞式检查 Ctrl+Z、Unix/Linux系统下一般采用非阻塞式的检查 Ctrl+D。楼主是在Windows系统下,因此使用阻塞式的 Ctrl+Z 来标识流的结束。这种阻塞式的方式有一个特点:只有按下回车之后才有可能检测在此之前是否有Ctrl+Z按下。还有一个特点就是:如果输入缓冲区中有可读的数据则不会 检测Ctrl+Z(因为有要读的数据,还不能认为到了流的末尾)。还有一点需要知道:Ctrl+Z产生的不是一个普通的ASCII码值,也就是说它产生的 不是一个字符,所以不会跟其它从键盘上输入的字符一样能够存放在输入缓冲区。
[摘自:http://wenku.baidu.com/view/44e58e1d227916888486d744.html]
2、
#include<stdio.h> int main() { int a; while((a=getchar())!=EOF) { sleep(1); printf("%d\n",a); } printf("end:%d\n",a); return 0; }
在缓冲区字符没读完的时候按Ctrl+D
结果在输出所有字符后,getchar()返回了-1,说明只要没有键盘输入,直接Ctrl+D就会起作用。
我觉得可以这样理解,每按一次Ctrl+D就表示结束一轮输入,此时Ctrl+D就告诉getchar()你去读缓冲区吧。当Ctrl+D之前有字符输入时,getchar就会正常读到字符。当直接按Ctrl+D时,缓冲区没有任何字符送进去,getchar()去读的时候什么也没读到,就会出错返回-1。
3、
#include <stdio.h> #include <stdlib.h> int main(void) { int c; system("stty raw"); /* 现在的终端驱动处于一次一个字符模式 */ while(1) { c = getchar(); putchar(c); } /* 终端驱动处又回到一次一行模式 */ system("stty cooked"); return 0; }
stty raw 可以实现键入一个字符立即读出的效果。此时回车不再起换行作用,按回车后光标会定位到行开头。
相关文章推荐
- linux内核移植和跟文件系统制作
- 面向对象和面向过程的区别
- 建堆O(n)时间复杂度证明
- 【算法学习笔记】68.枚举 SJTU OJ 1272 写数游戏
- 浅谈.Net WebService开发
- oracle 表 主键自增
- C++学习 文件读写详解(ofstream,ifstream,fstream)
- iOS开发-UIWebView加载方式
- 卫生局应急指挥系统
- visio 转化成的pdf 在latex 中, 嵌入字体不显示
- python基础课程_学习笔记26:编程的乐趣
- checkbox全选和反选
- 表单序列化 js
- 使用DATEADD和DATEDIFF来计算SQL Server的DATETIME值
- Pivotal Gemfire gfsh shell的使用(1)
- C#基础学习第三天(.net菜鸟的成长之路-零基础到精通)
- php文件大小单位转换GB MB KB
- 6.2-5
- 设计模式读书笔记:Decorator(装饰)
- px、dp、dip、dpi、sp 等到底有什么联系区别?