小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本篇主要参考自EOF是什么?。没有原封不动的转载的原因,在最后的说明部分,也就是其中多文本中 EOF(-1) 的介绍并不是特别准确,因此进行了一些删减【也可能自己的理解并不准确,后续有机会再深入研究】。
但大部分内容的介绍对理解EOF很有帮助。
感谢阮一峰老师!
即使看了这篇文章,本质上对理解 EOF 还是不是特别到位,可能需要多读几遍
在linux中进行输入或读取时,经常会看到EOF的标识。因此不禁好奇,EOF到底是什么?
先说一下结论:
在Linux系统之中,EOF不是一个字符,而是当系统读取到文件结尾时,所返回的一个信号值(也就是-1)。也是C语言中读取文件到结尾时返回的信号量。
系统通过比较文件的长度,确定是否是文件的结尾。
介绍
EOF是end of file的缩写,表示的是“文字流”(character stream)的结尾。这里的文字流可以是文本文件(file),也可以是标准输入(stdin)。
文件读取
下面是C语言中, 读取文件,判断是否是文件结尾,如果不是,就把文件的内容复制到屏幕上。
int c;
while ((c = fgetc(fp)) != EOF) {
putchar (c);
}
C语言中,EOF是一个定义在头文件stdio.h
中的常量,值为-1。
#define EOF (-1)
fgetc()
的处理和linux中对文件结尾的处理一样,会返回-1(即:EOF),但是,此外,当发生错误时,也会返回EOF。
因此,C语言提供了feof()函数,用于准确判断当前位置是否是文件结尾。
使用 feof() 函数读取处理文件的写法,可以如下:
int c;
while (!feof(fp)) {
c = fgetc(fp);
do something;
}
但是这样写是有问题的。fgetc()读取最后一个字符以后,位置还是最后一个,feof()返回的仍然是0(未读取到结尾),也就是fgetc()仍会再读取一次,才会读取到文件的结尾,返回EOF。feof()的判断失去了意义。
所以,正确的写法是:
int c = fgetc(fp);
while (c != EOF) {
do something;
c = fgetc(fp);
}
if (feof(fp)) {
printf("\n End of file reached.");
} else {
printf("\n Something went wrong.");
}
标准输入
此外,EOF还可以表示标准输入的结尾。
int c;
while ((c = getchar()) != EOF) {
putchar(c);
}
标准输入与文件不一样,无法事先知道输入的长度,必须手动输入一个字符,表示到达EOF。
在linux shell中重定向的使用中,就常常使用EOF字符作为定界符,输入的结束,还是由 Ctrl+D 快捷键发出信号。
Linux中,在新的一行的开头,按下 Ctrl+D,就代表 EOF(如果在一行的中间按下 Ctrl+D,则表示输出"标准输入"的缓存区,所以这时必须按两次 Ctrl+D);
Windows中,Ctrl+Z 表示 EOF。
(但要注意,Linux中按下Ctrl+Z,表示将该进程中断,在后台挂起,用 fg 命令可以重新切回到前台;按下 Ctrl+C 表示终止该进程。)
如果想输入 Ctrl+D 怎么办?这时必须先按下 Ctrl+V,然后就可以输入 Ctrl+D,系统就不会认为这是EOF信号。
Ctrl+V 表示按"字面含义"解读下一个输入,要是想按"字面含义"输入 Ctrl+V,连续输入两次就行了。
说明
关于原文中,对文本中 -1
(信号值) 的介绍,看到其下的评论,有说明文本视图和二进制视图的区别。
文本中,-1实际上是‘-’ ‘1’,除非使用二进制读写函数读写文件,那就不存在EOF而是按字节块读写,fgetc 是按文本型处理文件的,不存在读二进制的-1,一次只处理一个字节。
这里有个重要概念,文件分为:文本视图,二进制视图。打开文件分文本模式打开,二进制打开。处理也分文本模式和二进制模式处理。
评论区也是一个宝藏!