zoukankan      html  css  js  c++  java
  • 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标志的是试图进行数据读取的操作

      示例:

     1 #include<stdio.h>
     2 
     3 int main(void)
     4 {
     5     FILE *ptr = fopen("a.txt","r");
     6 
     7     if(!ptr)
     8     {
     9         printf("打开文件失败!
    ");
    10         return -1;
    11     }
    12 
    13     char ch;
    14     int count = 0 ;
    15 
    16     while(!feof(ptr))                //检测到EOF标志则停止
    17     {
    18         count++;
    19         ch = fgetc(ptr);
    20         printf("%c",ch);
    21     }
    22     printf("%5d",count);
    23     printf("
    ");
    24 
    25     fclose(ptr);
    26     return 0;
    27 }

      示例代码读取的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用来表示文件读取至末尾或发生错误。

     

  • 相关阅读:
    程序员找工作必备 PHP 基础面试题 (四)
    Laravel 教程:使用Fast Excel解决导出超大 XLSX 文件(千万级)带来的内存问题
    ThinkPHP无限分类的使用
    PHP 的 interface 有什么用处?
    编写可读代码:通过提前返回来减少缩进
    调试事件的派发
    调试对象的构建
    [反汇编分析] 局部变量复用
    [IDA]批量载入结构体
    [反汇编分析]调用函数传入参数不一致时可能寄存器传入参数
  • 原文地址:https://www.cnblogs.com/yhjoker/p/7787103.html
Copyright © 2011-2022 走看看