主要在看K&R的The C Programming Language,对于1.5节“字符输入/输出”理解不透,getchar的原理没有搞清楚,EOF的值知道是-1,但是对于
int c;
while ((c = getchar()) != EOF)
putchar(c);
每输入一行,回车一下,会输出上一行内容,不知道什么时候才能结束。最傻的方法是,输入-1,当然程序还是没有结束。
后来查资料,才发现对于getchar(),一般都会有两点总结,先附上。
一、getchar()的两点总结
1. getchar()是以行为单位进行存取的。
当用getchar进行输入时,如果输入的第一个字符为有效字符(即输入不是文件结束符EOF,Windows下为组合键Ctrl+Z, Unix/Linux下为组合键Ctrl+D),那么只有当最后一个输入字符为换行符'/n'(也可以是文件结束符EOF,EOF将在后面讨论)时, getchar才会停止执行,整个程序将会往下执行。
例如,上面的代码,就是自己输入时出出现的情况,每输入一行,再按回车,就会输出相应的内容。
这里不能忘了,系统输出时,还有一个”回车符“,这也是为什么我们看到新的输入提示符出现在新的一行,这是回车符的效果。从另外一点也能反应这个问题,就是书上1.5.2讲的”计算字符的个数“,我们会发现总个数是加上回车符个数的。
例如,
int cha;
long nc = 0;
while ((cha = getchar()) != EOF)
{
putchar(cha);
++nc;
}
printf("%d\n", nc);
对于上面的程序,我们可以得到下面的结果:
可以看出,最后字符的总个数为9,和上面的分析是符合的。
2. getchar()的返回值一般情况下是字符,但也可能是负值,即返回EOF。
这里要强调的一点就是,getchar函数通常返回终端所输入的字符,这些字符系统中对应的ASCII值都是非负的。因此,很多时候,我们定义
char c;
c = getchar ( ) ;
这样就很容易出现问题, 因为getchar函数除了返回终端输入的字符外,在遇到Ctrl+D(Linux下)(Windows下Ctrl+Z)即文件结束符EOF时,getchar ()的返回EOF,这个EOF在函数库里一般定义为-1。因此,在这种情况下,getchar函数返回一个负值,把一个负值赋给一个char型的变量是不正确的。
为了解决这个问题,书中也提到了方法,就是定义为int类型。即为本文刚开始的程序。
二、EOF的两点总结(主要指普通终端中的EOF)
首先明确一下EOF的概念,EOF即End of File,是在stdio.h中定义的一个常量,为#define EOF (-1) 用来表示文件的结尾,当某些函数读取到文件尾时便返回EOF。另外,不是说每个文件的尾部都有一个专门的标志用来标示文件结尾,更不是说每个文件尾都有EOF,我们可以想象一下,如果我们每次读取一个字符都要判断是否到达文件尾,那样效率也太低了,那如何判断文件是否已经结束了呢?中断、异常。当我们用函数读入文件数据的时候,函数总会返回一个状态,是读取成功还是失败,那么这个状态怎么表示呢,所以就约定俗成定义一个标识符表示这个状态,就有了EOF,BOF等等。
1.EOF作为文件结束符时的情况
EOF虽然是文件结束符,但并不是在任何情况下输入Ctrl+D(Windows下Ctrl+Z)都能够实现文件结束的功能,只有在下列的条件下,才作为文件结束符。
(1)遇到 getcahr函数执行时,要输入第一个字符时就直接输入Ctrl+Z,就可以跳出getchar(),去执行程序的其他部分;
(2)在前面输入的字符为换行符时,接着输入Ctrl+Z;
(3)在前面有字符输入且不为换行符时,要连着输入两次Ctrl+Z,这时第二次输入的Ctrl+Z起到文件结束符的功能。
其实,这三种情况都可以总结为只有在getchar()提示新的一次输入时,直接输入Ctrl+Z才相当于文件结束符。
PS:对于第(3)点,是基于他人的总结,自己在windows下实践时,似乎并不能满足文件结束的功能,这点还需要研究一下。
2.EOF作为行结束符时的情况,这时候输入Ctrl+Z并不能结束getchar(),而只能引发getchar()提示下一轮的输入 。
即在进行getchar()新的一行输入时,当输入了若干字符(不能包含换行符)之后,直接输入Ctrl+Z,此时的Ctrl+Z并不是文件结束符,只是引发下一轮的输入。
EOF 的作用也可以总结为:
当终端有字符输入时,Ctrl+Z产生的EOF相当于结束本行的输入,将引起getchar()新一轮的输入;
当终端没有字符输入或者可以说当getchar()读取新的一次输入时,输入Ctrl+Z,此时的EOF相当于文件结束符,程序将结束getchar()的执行。
—— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— —— ——
经过上面的分析,大概已经了解了getchar()和EOF的使用方法。其实仔细再想想,我们为什么讨论这两个问题,因为他们总是结合起来用,对于getchar()必须要有一个结束符,来结束从键盘的输入。
其实,总结自己的编程经验,当需要从键盘输入字符时,发现有时候并没有用EOF这样的结束符,而是自己定义了一个结束符,例如‘#’,这个当然要在程序中说明。例如:
cout<<"请输入需要加密的明文,以#作为结束符:";
while(c != ‘#')
{
c = getchar();
inBuffer[i++] = c;
}
本文参考的文章地址:http://blog.csdn.net/lichaoandy/article/details/5525115