【转载】关于K&R中的getchar和EOF

大师级经典的著作,要字斟句酌的去读,去理解。以前在看 KR 的 The C ProgrammingLanguageSecondEdition第 1.5 节的字符输入/输出,被 getchar和 EOF 所迷惑了。可能主要还是由于没有搞 清楚getchar的工作原理和 EOF 的用法。因此感觉很有必要总结一下,不然,很多琐碎的知识点长时间过后就会淡忘的,只有写下来才是最好的方法。其实,getchar最典型的程序也就几行代码而已。
本人所用的环境是 DebianGNU/Linux,在其他系统下也一样。
一、getchar 的两点总结:
1.getchar 是以行为单位进行存取的。当用 getchar 进行输入时,如果输入的第一个字符为有效字符,那么只有当最后一个输入字符为换行符\n,也可以是文件结束符 EOF时, getchar 才会停止执行,整个程序将会往下执行。譬如书中的例子,输入:abc,然后回车。则程序就会去执行 puchar,然后输出 abc,这个地方不要忘了,系统输出的还有一个回车。然后可以继续输入,再次遇到换行符的时候,程序又会把那一行的输入的字符输出在终端上。对于 getchar,肯定很多初学的 朋友会问,getchar 不是以字符为单位读取的吗?那么,既然我输入了第一个字符 a,肯定满足 while 循环的条件阿,那么应该执行putcharc在终端输出一个字符 a。不错,我在用 getchar 的时候也是一直这么想的,但是程序就偏偏不着样执行,而是必需读到一个换行符或者文件结束符 EOF 才进行一次输出。
对这个问题的一个解释是,在大师编写 C 的时候,当时并没有所谓终端输入的概念,所有的输入实际上都是按照文件进行读取的,文件中一般都是以行为单位的。因此,只有遇到换行符,那么程序会认为输入结束,然后采取执行程序的其他部分。同时,输入是按照文件的方式存取的,那么要结束一个文件的输入就需用到 EOF. 这也就是为什么getchar 结束输入退出时要用 EOF 的原因 。
2.getchar的返回值一般情况下是字符,但也可能是负值,即返回 EOF。这里要强调的一点就是,getchar 函数通常返回终端所输入的字符,这些字符系统中对应的ASCII 值都是非负的。因此,很多时 候,我们会写这样的两行代码:

char c;

c=getchar();

这样就很有可能出现问题。因为getchar函数除了返回终端输入的字符外,在遇到文件结束符 EOF 时,getchar的返回 EOF,这个 EOF 在函数库里一般定义为-1。因此,在这种情况下,getchar 函数返回一个负值,把一个负值赋给一个 char 型的变量是不正确的。为了能够让所定义的变量能够包含 getchar 函数返回的所有可能的值,正确的定义方法如下:

int c;

c=getchar();

 

二、EOF 的两点总结(主要指普通终端中的 EOF)

文件结束符 EOF,Windows 下为组合键 Ctrl+Z, Unix/Linux 下为组合键 Ctrl+D,

1.EOF 作为文件结束符时的情况:EOF 虽然是文件结束符, 但并不是在任何情况下输入CtrlD都能够实现文件结束的功能,只有在下列的条件下,才作为文件结束符。

(1)遇到 getchar 函数执行时,要输入第一个字符时就直接输入 CtrlD,就可以跳出 getchar去执行程序的其他部分;
(2)在前面输入的字符为换行符时,接着输入 CtrlD;
(3)在前面有字符输入且不为换行符时,要连着输入两次 CtrlD,这时第二次输入的 CtrlD起到文件结束符的功能,至于第一次的 CtrlD 的作用将在下面介绍。

其实,这三种情况都可以总结为只有在 getchar提示新的一次输入时,直接输入 CtrlD 才相当于文件结束符。


2.EOF 作为行结束符时的情况, 这时候输入 CtrlD 并不能结束 getchar而只能引发 getchar提示下一轮的输入。这种情况主要是在进行 getchar新的一行输入时, 当输入了若干字符(不能包含换行符)之后,直接输入 CtrlD,此时的 CtrlD 并不是文件结束符,而只是相当于换行符的功能,即结束当前的输入。以上面的代码段为例,如果执行时输入abc,然后 CtrlD,程序输出结果为:abcabc

注意:第一组 abc 为从终端输入的,然后输入 CtrlD,就输出第二组 abc,同时光标停在第二组字符的 c 后面然后可以进行新一次的输入。这时如果再次输入 CtrlD,则起到了文件结束符的作用,结束 getchar。如果输入 abc 之后,然后回车,输入换行符的话,则终端显示为:

abc //第一行,带回车

abc //第二行

     //第三行

其中第一行为终端输入, 第二行为终端输出, 光标停在了第三行处,等待新一次的终端输入。从这里也可以看出 CtrlD 和换行符分别作为行结束符时,输出的不同结果。EOF 的作用也可以总结为:当终端有字符输入时,CtrlD 产生的 EOF 相当于结束本行的输入,将引起 getchar新一轮的输入;当终端没有字符输入或者可以说当 getchar读取新的一次输入时,输入 CtrlD,此时产生的 EOF 相当于文件结束符,程序将结束 getchar的执行。

posted @ 2012-05-08 14:14  cian  阅读(202)  评论(0编辑  收藏  举报