#include <stdio.h> int main(int argc, char *argv[]){ int c; while((c = getchar()) != EOF){ printf("%d", c != EOF); putchar(c); } printf("\n%d\n", c != EOF); }getchar函数可以返回可以在系统上表示的任何可能的字符,再加上一个额外的,特殊的“带外”返回值,表示不再返回任何字符.该值由符号宏标识符EOF引用.在< stdio.h>后面的某处通常有一个定义
#define EOF (-1)
该值不一定是-1,但这符合我们的目的. (我们不必知道或关心实际值是什么,因为我们总是参考EOF,使我们与实际价值隔离开来.)
无论EOF有什么价值,它都保证不会与任何实际角色相同.因此,如果getchar返回EOF以外的值,则它是已读取的实际字符.但是如果它返回EOF,那表明输入流已经到达文件结尾,那么就没有更多的字符需要读取.
所以EOF绝对不是一个角色.它是一个整数,其值不同于任何char.我不会称之为“条件”,尽管你使用类似的代码测试它
if(c == EOF)
要么
if(c != EOF)
我会说那些表达式c == EOF和c!= EOF是条件.
它特别令人困惑,因为通常会有一个特殊字符,您可以在键盘上键入以生成文件结束指示.在Windows上它是control-Z;在Unix和其他系统上它是控制-D.但这并不意味着EOF在Windows系统上是control-Z,或者在Unix系统上是控制-D.这些字符由终端驱动程序处理并转换为指示,在几个额外的处理和解释级别之后,使得getchar返回EOF.但是证明EOF不是control-Z或control-D的一种方法是观察当你使用getchar或getc从文件中读取时,即使没有人,你也会在文件末尾得到一个EOF指示.在这种情况下在键盘上键入控制字符.
最后,本讨论提醒我们使用int变量来携带getchar返回的值的重要性.您引用的代码正确声明
int c;
然后使用变量c来保存getchar返回的值.为什么在这里使用int?因为getchar返回字符,并且因为c是一个字符,所以声明它不会更有意义
char c;
这似乎有道理,但实际上是非常错误的.类型char可以包含系统可以表示的任何字符.但请记住,getchar可以返回任何字符值,加上EOF值.如果将getchar的返回值赋给char类型的变量,则最终会“无意中”将其映射到实际字符值,从而“刮掉”EOF指示.接下来发生的事情是你将一个真实的角色(通常是ÿ)映射到EOF并在你读一个时错误地停止阅读,或者你将EOF映射到一个真实的角色,所以永远不会检测到它然后进入无限循环而不是停止在文件结尾.