转自http://www.ruanyifeng.com/blog/2011/11/eof.html

学习C语言的时候,遇到的一个问题就是EOF

它是end of file的缩写,表示"文字流"(stream)的结尾。这里的"文字流",可以是文件(file),也可以是标准输入(stdin)。

比如,下面这段代码就表示,如果不是文件结尾,就把文件的内容复制到屏幕上。

int c;
while ((c = fgetc(fp)) != EOF) { putchar (c); }

很自然地,我就以为,每个文件的结尾处,有一个叫做EOF的特殊字符,读取到这个字符,操作系统就认为文件结束了。

但是,后来我发现,EOF不是特殊字符,而是一个定义在头文件stdio.h的常量,一般等于-1。

#define EOF (-1)

于是,我就困惑了。

如果EOF是一个特殊字符,那么假定每个文本文件的结尾都有一个EOF(也就是-1),还是可以做到的,因为文本对应的ASCII码都是正值,不可能有负值。但是,二进制文件怎么办呢?怎么处理文件内部包含的-1呢?

这个问题让我想了很久,后来查了资料才知道,在Linux系统之中,EOF根本不是一个字符,而是当系统读取到文件结尾,所返回的一个信号值(也就是-1)。至于系统怎么知道文件的结尾,资料上说是通过比较文件的长度。

所以,处理文件可以写成下面这样:

 int c;

 while ((c = fgetc(fp)) != EOF) {

 do something

 }

这样写有一个问题。fgetc()不仅是遇到文件结尾时返回EOF,而且当发生错误时,也会返回EOF。因此,C语言又提供了feof()函数,用来保证确实是到了文件结尾。上面的代码feof()版本的写法就是:

 int c;

 while (!feof(fp)) {

 c = fgetc(fp);

 do something;

 }

但是,这样写也有问题。fgetc()读取文件的最后一个字符以后,C语言的feof()函数依然返回0,表明没有到达文件结尾;只有当fgetc()向后再读取一个字符(即越过最后一个字符),feof()才会返回一个非零值,表示到达文件结尾。

所以,按照上面这样写法,如果一个文件含有n个字符,那么while循环的内部操作会运行n+1次。所以,最保险的写法是像下面这样:

 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中,在新的一行的开头,按下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,连续输入两次就行了。

EOF是什么?的更多相关文章

  1. linux下EOF写法梳理

    在平时的运维工作中,我们经常会碰到这样一个场景:执行脚本的时候,需要往一个文件里自动输入N行内容.如果是少数的几行内容,还可以用echo追加方式,但如果是很多行,那么单纯用echo追加的方式就显得愚蠢 ...

  2. php定界符<<<EOF讲解(转)

    Heredoc技术.可用来输出大段的html和javascript脚本 1.PHP定界符的作用就是按照原样,包括换行格式什么的,输出在其内部的东西: 2.在PHP定界符中的任何特殊字符都不需要转义:  ...

  3. while(cin.eof)出错 poj

    zoj遇到c++如何判定输入流结尾的问题,一不小心就超时了 楼下的代码可以通过zoj #include<iostream> using namespace std; int main(){ ...

  4. c++ eof()函数

    C++ eof()函数可以帮助我们用来判断文件是否为空,抑或是判断其是否读到文件结尾.在这里我们将会对其进行详细的介绍. C++编程语言中的很多功能在我们的实际应用中起着非常大的作用.比如在对文件文本 ...

  5. 【转】 解读EOF

    解读EOF 标签: fplinuxc语言filestream 2012-01-31 22:05 439人阅读 评论(0) 收藏 举报  分类: C.C++_程序设计(20)  我学习C语言的时候,遇到 ...

  6. Linux C 字符函数 getchar()、putchar() 与 EOF 详解

    首先给出<The_C_Programming_Language>这本书中的例子: #include <stdio.h> int main() { int c; c = getc ...

  7. Ext3文件系统mount选项和文件属性介绍

    mount选项 设置方式 ext3 mount选项可以通过多个方式进行设置:1)内核编译时: 内核menuconfig通过CONFIG_EXT3_DEFAULTS_TO_ORDERED编译控制选项,来 ...

  8. .NET 串口通信中断接收,包含0X1A(作为EOF)

    .NET串口通信中将`0X1A`当做EOF处理,.NET接收到EOF会触发一次接收中断,此时事件形参`SerialDataReceivedEventArgs`值为枚举 `Eof`,其他为`Chars` ...

  9. 常见的getchar 与EOF的问题

    代码中常有类似的如下的输入循环 char  c; while((c=getchar())!=EOF).... 如果输入 字符+换行时,循环的代码会执行两次,主要是换行键作为字符存到了缓存队列中,第一次 ...

  10. PHP eof的使用

    PHP eof的使用 也就是heredoc技术,来部分实现界面与代码的分离 <?php $name = '张三'; print <<<EOT <html> < ...

随机推荐

  1. windows下virtualenv使用报错

    virtualenv为python提供了一个独立的虚拟环境,使各种python依赖库的安装相互独立.在家里ubuntu上安装一切正常,但在公司的win7上安装总是报以下错误: "D:\Pro ...

  2. PLSQL配置介绍

    PLSQL配置简介,优化   来自为知笔记(Wiz) 附件列表 s=selectf=FROMw=WHEREsf=SELECT * FROMdf=DELETE FROMsc=SELECT COUNT(* ...

  3. Installutil.exe 注册exe

    进入到C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe目录下,然后输入Installutil.exe 文件路径实现注册   I ...

  4. Dom4J对XML的创建、修改、删除等操作

    Dom4j也可以很方便完成XML文档的创建.元素的修改.文档的查询遍历等,但dom4j稍比jdom复杂一点,不过在大片文档的情况下dom4j的性能要不jdom好. # 准备 首先,提供相关的jar包 ...

  5. Repository模式介绍汇总

    1.Linq To Sql中Repository模式应用场景 http://www.cnblogs.com/zhijianliutang/archive/2012/02/24/2367305.html ...

  6. Android SimpleAdapter源码详解

    一直没认真看过android的源码,也不太敢看,稀里糊涂也敲了一年的代码,现在想好好学习了,就把常用的源码都看了一下,小伙伴们来涨姿势吧,有错误的地方,直接指出,我脸厚不怕丢人.来吧. 刚开始学and ...

  7. 【C语言】编写一个函数实现n^k,使用递归实现

    #include <stdio.h> int fuc(int x,int n) { if(n!=1) return x*fuc(x,n-1); return 1; } int main() ...

  8. IOS--- NavigationBar标题按钮

    A.NavigationBar标题按钮 1.需求 在“首页”的导航栏中部设置一个“首页”文字+箭头按钮 统一设置样式 根据实际文本长度调整宽度 消除系统自带的点击高亮效果 点击按钮,箭头上下颠倒 gi ...

  9. partition例子

    10.13 标准库定义了名为partition的算法,它接受一个谓词,对容器内容进行划分,使得谓词为true的值会排在容器的前半部分,而使谓词为false的值会排在后半部分.算法返回一个迭代器,指向最 ...

  10. 利用QT制作我们自己的一个计算器

    有了前面的经验就比较容易创建一个 属于我们自己的计算器了. 一些简单的拖拽就可以实现了. 界面设计部分: 转到槽之后的代码部分: #include "widget.h" #incl ...