EOF及相关函数
结论:EOF是在头文件stdio.h中预定义的一个宏,而eof(end of file)是一个与标准输入/输出流相关联的标志位。当文件指针已经指向文件尾且再次尝试读取时,eof标志会被设置。同时,某些函数会在读取到文件尾(即eof标志被设置)时返回EOF作为标识。
另注:
笔者经常会在C进行文件I/O操作时出现文件读取实际尚未结束(未读取至文件末尾),但系统显示已读取至文件尾的情况。具体原因如下。
在过去的操作系统中,文件以文件存储占用的扇区数作为文件大小的计数单位,故而如果文件的大小不能恰好填满存储文件的最后一个扇区,则需要对该扇区剩余的空间进行填充,过去填充使用的是值为26(0x1a)的字节,也就是某些系统中 Ctrl+Z 的对应码值,故而在读取文件过程中,读取到值26,则系统认为文件已经到达末尾,不再读取。在 windows 环境下,终端输入可以使用 Ctrl + z 作为输入的 EOF 标志,而 linux 环境下,则可使用 Ctrl + d 作为输入的结束标志。
现在的操作系统开始使用字节作为文件大小的计数单位,但古老的习惯还是被保留下来。为了避免文件读取过程中存在值为26的数据使得系统误认为文件结束而停止读取,可以将文件以二进制文件格式打开。
EOF
EOF常被在程序中用于判断(文件)缓冲区是否结束,实际在头文件 stdio.h 中定义。
可以看到EOF是一个头文件中预定义的宏,其值为 -1 。也就是说,在程序中使用的EOF实际为一个预定义的常数。而许多的函数会在读取至文件末尾或出现错误时,会返回EOF,作为处理状态的一种描述,如下文的getchar.
getchar(getchar C++ Reference)
函数声明:int getchar(void);
函数功能:当函数读取成功时,会返回成功读取的字符数据(转化为 int 类型),若失败,则返回值为EOF,也就是上文说的值为 -1 的宏定义。
可以从上面的介绍中看到,函数除返回EOF外,还会设置标准输入( stdin )的 eof 标志/error标志,可供feof或ferror函数使用。也就是说,EOF(宏定义)与eof标志并不是同一个东西。
getchar函数在头文件stdio.h中定义,具体实现如下:
显然,读取字符数据并指向下一个待读取的数据操作是由 *stdin->_ptr++ 来实现的,而返回 EOF 以及将上文提及的error标志和eof标志则是由函数_filbuf实现。
从上面资料可以得到结论:
(1)对一般的文件/输入流,存在一个指向待读取数据位置的内部的指针(如上面的stdin->_ptr),每次读取数据完成该内部指针会移动指向下一个待读取数据;
(2)文件/输入流还存在两个特殊的标志 eof 和 error ,它们可以分别被函数feof和ferror处理,当文件读取至文件末尾或出现错误时,相应的标志位eof/error会被设置;
(3)一些函数在发生错误或读取至文件末尾时,会返回EOF,其为值为 -1 的宏,同时设置文件/输入流的某些标志;
feof( feof C++ Reference)
函数声明:int feof(FILE *stream); //stream为对应的文件流的标志
函数功能:会检查与文件对应流的eof( end of file )标志是否被设置,如果被设置则返回非零值,如未被设置,则返回0.
注意:feof函数只检查eof标志是否被设置,其本身并不会设置eof标志,设置eof标志的是试图进行数据读取的操作。
示例:
#include<stdio.h> int main(void)
{
FILE *ptr = fopen("a.txt","r"); if(!ptr)
{
printf("打开文件失败!\n");
return -;
} char ch;
int count = ; while(!feof(ptr)) //检测到EOF标志则停止
{
count++;
ch = fgetc(ptr);
printf("%c",ch);
}
printf("%5d",count);
printf("\n"); fclose(ptr);
return ;
}
示例代码读取的a.txt的内容为"12".代码会逐字节显示文件的内容(19、20行),以及读取的次数(18、22行)。
执行结果下图所示:
(1)EOF标志未被设置时,feof函数会返回0,eof标志被设置后,feof返回非零值;
(2)每次读取成功后,指向文件流内部的指针会顺序移动读取的字数个字节(对文本来说),这样使得内部指针总是指向待读取的下一个字符;
(3)执行流程 : feof返回值为0,第一次循环,ch = ‘1’,count = 1,流内部的位置指针指向‘2’;feof返回值为0,第二次循环,ch = ‘2’,count = 2,流内部的位置指针指向文件末尾,但此时EOF并未被设置;feof返回值仍为0,第三次循环,会试图访问文件的末尾,count = 3,eof 标志被设置,下一次的feof返回值为非0值,故而结束循环;(笔者在CodeBlocks12.13中调试时,第三次循环时ch的值为-1,即为EOF,printf并没有将其显示至控制台)
文件流内部存在标志读取位置的内部指针,该位置指针指向文件尾并不会设置对应文件流的eof 标志,只有当该位置指针指向文件尾,并再次试图进行顺序读操作时,才会设置eof标志。
EOF为一个定义的宏常量,而eof标志为与文件/输入流相关的一个标志,当位置指针已指向文件末尾并再次试图读取输入时,会设置eof标志,同时为了表明发生的情况,函数一般会返回EOF用来表示文件读取至末尾或发生错误。
EOF及相关函数的更多相关文章
- fopen()及相关函数使用
函数简介 函数功能:打开一个文件 函数原型:FILE * fopen(const char * path,const char * mode); ],_wfopen 所需库:<stdio.h&g ...
- 学习PHP中的iconv扩展相关函数
想必 iconv 这个扩展的相关函数大家多少都接触过,做为 PHP 的默认扩展它已经存在了很久,也是我们在操作字符编码时经常会使用的函数.不过除了 iconv() 这个函数外,你还知道它的其它函数吗? ...
- linux下EOF写法梳理
在平时的运维工作中,我们经常会碰到这样一个场景:执行脚本的时候,需要往一个文件里自动输入N行内容.如果是少数的几行内容,还可以用echo追加方式,但如果是很多行,那么单纯用echo追加的方式就显得愚蠢 ...
- php定界符<<<EOF讲解(转)
Heredoc技术.可用来输出大段的html和javascript脚本 1.PHP定界符的作用就是按照原样,包括换行格式什么的,输出在其内部的东西: 2.在PHP定界符中的任何特殊字符都不需要转义: ...
- while(cin.eof)出错 poj
zoj遇到c++如何判定输入流结尾的问题,一不小心就超时了 楼下的代码可以通过zoj #include<iostream> using namespace std; int main(){ ...
- c++ eof()函数
C++ eof()函数可以帮助我们用来判断文件是否为空,抑或是判断其是否读到文件结尾.在这里我们将会对其进行详细的介绍. C++编程语言中的很多功能在我们的实际应用中起着非常大的作用.比如在对文件文本 ...
- 【转】 解读EOF
解读EOF 标签: fplinuxc语言filestream 2012-01-31 22:05 439人阅读 评论(0) 收藏 举报 分类: C.C++_程序设计(20) 我学习C语言的时候,遇到 ...
- Linux C 字符函数 getchar()、putchar() 与 EOF 详解
首先给出<The_C_Programming_Language>这本书中的例子: #include <stdio.h> int main() { int c; c = getc ...
- Ext3文件系统mount选项和文件属性介绍
mount选项 设置方式 ext3 mount选项可以通过多个方式进行设置:1)内核编译时: 内核menuconfig通过CONFIG_EXT3_DEFAULTS_TO_ORDERED编译控制选项,来 ...
随机推荐
- SQL Cookbook—字符串
1.遍历字符串2.计算字符在字符串中出现的次数3.从字符串中删除不需要的字符4.将字符和数字数据分离5.判别字符串是不是字母数字型的6.提取姓名的大写首字母缩写7.按字符串中的部分内容排序8.按字符串 ...
- MySQL使用全文索引(fulltext index)
1.创建全文索引(FullText index) 旧版的MySQL的全文索引只能用在MyISAM表格的char.varchar和text的字段上. 不过新版的MySQL5.6.24上InnoDB引擎也 ...
- ddddddeeeessssssttttrrrrrrooooooyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
我遥远的 POI 计划啊 https://loj.ac/problems/search?keyword=POI2011 atcoder 一套 动态 DP SAM 随便看 XSY 的题 UOJ Roun ...
- springboot定时任务,去掉指定日期
今天用springboot写到一个需求:每周定时发送任务,但是要避开法定节假日. 网上找了些博客看,主要参考了https://www.cnblogs.com/lic309/p/4089633.html ...
- mariadb sequence
MariaDB 10.3 正式版推出后,有了像 Oracle.PostgreSQL 里的序列特性. 同时表字段AUTO_INCREMENT原特性还保持,但是sequence特性在某些特定情境还是很有用 ...
- 兼容IE和Firefox获得keyBoardEvent对象
<input type="text" name="words" id="search_txt" class="seachIp ...
- Javascript与jQuery方法的隐藏与显示
如题,代码奉上. <html> <head> <title>denotoggle</title> <style> #box { width: ...
- [编程] C语言变量和数据类型总结练习题
练习题: 1) 如何用 printf() 输出 short.int.long 类型的整数,请举例说明. 2) 如何用 printf() 输出 float.double 类型的小数,请举例说明. 3) ...
- PAT 1028. List Sorting
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> ...
- 【转】Dom节点操作常用方法
1.访问/获取节点 document.getElementById(id); //返回对拥有指定id的第一个对象进行访问 document.getElementsByName(name); //返回带 ...