鱼C论坛

 找回密码
 立即注册
查看: 2106|回复: 11

[已解决]关于feof()函数的困惑

[复制链接]
发表于 2017-6-4 17:10:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. char c;
  2. while(!feof(fp))
  3. {
  4. c = fgetc(fp);
  5. printf("%X/n", c);
  6. }
复制代码

在运行这个程序时,会多输出一个FF,在这篇文章中,给出了这样的解释
只有当文件位置指针(fp->_ptr)到了文件末尾,然后再发生读/写操作时,标志位(fp->_flag)才会被置为含有_IOEOF。然后再调用feof(),才会得到文件结束的信息。

feof()的用法
为什么发生读/写操作时,标志位(fp->_flag)才会被置为含有_IOEOF。然后再调用feof(),才会得到文件结束的信息?
最佳答案
2017-6-4 19:38:35
本帖最后由 人造人 于 2017-6-4 19:42 编辑

这个问题和fgetc函数有关

这是 fgetc 函数的一部分,我找不到完整的^_^

  1. #define NOCCARGC  /* no argument count passing */
  2. #include stdio.h
  3. #include clib.def
  4. /*
  5. ** Character-stream input of one character from fd.
  6. ** Entry: fd = File descriptor of pertinent file.
  7. ** Returns the next character on success, else EOF.
  8. */
  9. fgetc(fd) int fd; {

  10.   int ch;
  11.   char buff;
  12.   if(Uread(&buff,fd,1)==EOF) {

  13.         Useteof(fd);
  14.         return(EOF);
  15.   
  16. }
  17.   ch=buff;
  18.   switch(ch) {

  19.       default:     return (ch);
  20.       case FILEOF:  /* switch(Uchrpos[fd]) {

  21.                      default: --Uchrpos[fd];
  22.                      case 0:
  23.                      case BUFSIZE:
  24.                      
  25. }  */
  26.                    Useteof(fd);
  27.                    return (EOF);
  28.       case CR:     return ('\n');
  29.       case LF:    /* NOTE: Uconin() maps LF -> CR */
  30.   
  31. }

  32. }
  33. #asm
  34. _getc EQU   _fgetc
  35.      PUBLIC _getc
  36. #endasm
复制代码


调用 Uread 读一个字符到 buff
如果已经到文件末尾,用 Useteof设置 eof,返回eof
只有用Useteof设置过eof,用feof才能获取到


在程序中
  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.         FILE *fp = fopen("C:\\workspace\\test.dat", "r");

  5.         char c;
  6.         while (!feof(fp))
  7.         {
  8.                 c = fgetc(fp);
  9.                 printf("%X/n", c);
  10.         }

  11.         return 0;
  12. }
复制代码


假设文件 C:\\workspace\\test.dat中只有1个字节

程序从main函数开始
首先打开文件
然后用feof判断文件,此时eof还没有被设置
然后调用fgetc 从test.dat中读1个字节,fgetc正常读取,返回test.dat中的那一个字节
然后输出
然后判断feof,因为上一次fgetc 正常读取,并没有设置eof,feof也就获取不到eof
然后执行fgetc ,这一次因为文件test.dat已经到末尾了,fgetc使用 Useteof设置 eof,返回eof

然后输出,这次printf输出的是eof
然后调用feof判断 ,因为fgetc 使用Useteof设置了 eof,所以while循环退出,
然后return 0;

弄明白这个问题的关键是,这个问题中有2个eof,一个是操作系统返回给库函数的eof,另一个是库函数返回给应用程序的eof
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2017-6-4 17:10:44 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-4 19:13:50 | 显示全部楼层
本帖最后由 qq1242009750 于 2017-6-4 19:16 编辑

假如有一个文件  内容如下:

1EOF

1为文件的内容
EOF为文件的结尾

当fgetc执行的时候会把fp当前的内容给读取,并指向当前内容的下一个字符;

分析:
当文件指针指向了EOF的时候,fgetc获取了EOF并复制给了变量c,接着printf就直接输出了这个EOF,
到了while判断的时候 因为里面有eof所以判断一下是否到了文件结尾,到了就退出循环。

不要FF的循环:
  1. while(1)
  2. {
  3. char c = fgetc(fp);

  4. if(feof(fp))
  5. {
  6.     break;
  7. }
  8.    printf("%c\n",c);
  9. }
复制代码



评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +2 收起 理由
超凡天赐 + 5 + 5 + 2 热爱鱼C^_^

查看全部评分

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-4 19:38:35 | 显示全部楼层    本楼为最佳答案   
本帖最后由 人造人 于 2017-6-4 19:42 编辑

这个问题和fgetc函数有关

这是 fgetc 函数的一部分,我找不到完整的^_^

  1. #define NOCCARGC  /* no argument count passing */
  2. #include stdio.h
  3. #include clib.def
  4. /*
  5. ** Character-stream input of one character from fd.
  6. ** Entry: fd = File descriptor of pertinent file.
  7. ** Returns the next character on success, else EOF.
  8. */
  9. fgetc(fd) int fd; {

  10.   int ch;
  11.   char buff;
  12.   if(Uread(&amp;buff,fd,1)==EOF) {

  13.         Useteof(fd);
  14.         return(EOF);
  15.   
  16. }
  17.   ch=buff;
  18.   switch(ch) {

  19.       default:     return (ch);
  20.       case FILEOF:  /* switch(Uchrpos[fd]) {

  21.                      default: --Uchrpos[fd];
  22.                      case 0:
  23.                      case BUFSIZE:
  24.                      
  25. }  */
  26.                    Useteof(fd);
  27.                    return (EOF);
  28.       case CR:     return ('\n');
  29.       case LF:    /* NOTE: Uconin() maps LF -&gt; CR */
  30.   
  31. }

  32. }
  33. #asm
  34. _getc EQU   _fgetc
  35.      PUBLIC _getc
  36. #endasm
复制代码


调用 Uread 读一个字符到 buff
如果已经到文件末尾,用 Useteof设置 eof,返回eof
只有用Useteof设置过eof,用feof才能获取到


在程序中
  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.         FILE *fp = fopen("C:\\workspace\\test.dat", "r");

  5.         char c;
  6.         while (!feof(fp))
  7.         {
  8.                 c = fgetc(fp);
  9.                 printf("%X/n", c);
  10.         }

  11.         return 0;
  12. }
复制代码


假设文件 C:\\workspace\\test.dat中只有1个字节

程序从main函数开始
首先打开文件
然后用feof判断文件,此时eof还没有被设置
然后调用fgetc 从test.dat中读1个字节,fgetc正常读取,返回test.dat中的那一个字节
然后输出
然后判断feof,因为上一次fgetc 正常读取,并没有设置eof,feof也就获取不到eof
然后执行fgetc ,这一次因为文件test.dat已经到末尾了,fgetc使用 Useteof设置 eof,返回eof

然后输出,这次printf输出的是eof
然后调用feof判断 ,因为fgetc 使用Useteof设置了 eof,所以while循环退出,
然后return 0;

弄明白这个问题的关键是,这个问题中有2个eof,一个是操作系统返回给库函数的eof,另一个是库函数返回给应用程序的eof
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-4 22:44:04 | 显示全部楼层
人造人 发表于 2017-6-4 19:38
这个问题和fgetc函数有关

这是 fgetc 函数的一部分,我找不到完整的^_^

你这个从哪里找的?fgetc源码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-4 22:58:21 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-5 19:35:25 | 显示全部楼层
本帖最后由 超凡天赐 于 2017-6-5 19:41 编辑


你能不能从GitHub是的glibc上找到fgetc源码,我找不到fgetc在glibc源码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-5 20:03:02 | 显示全部楼层
超凡天赐 发表于 2017-6-5 19:35
你能不能从GitHub是的glibc上找到fgetc源码,我找不到fgetc在glibc源码

我已经在glibc找过了,没有找到
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-5 20:04:46 | 显示全部楼层
人造人 发表于 2017-6-5 20:03
我已经在glibc找过了,没有找到

我在91年的版本中找到了。
  1. /* Copyright (C) 1991 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.

  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public License as
  5. published by the Free Software Foundation; either version 2 of the
  6. License, or (at your option) any later version.

  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  10. Library General Public License for more details.

  11. You should have received a copy of the GNU Library General Public
  12. License along with the GNU C Library; see the file COPYING.LIB.  If
  13. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  14. Cambridge, MA 02139, USA.  */

  15. #include <ansidecl.h>
  16. #include <errno.h>
  17. #include <stdio.h>


  18. /* Read a character from STREAM.  */
  19. int
  20. DEFUN(fgetc, (stream), FILE *stream)
  21. {
  22.   if (!__validfp(stream) || !stream->__mode.__read)
  23.     {
  24.       errno = EINVAL;
  25.       return EOF;
  26.     }

  27.   return __getc(stream);
  28. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-5 20:09:30 | 显示全部楼层
超凡天赐 发表于 2017-6-5 20:04
我在91年的版本中找到了。

在哪找到的?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-5 20:14:20 | 显示全部楼层

在这里glibc源码
屏幕快照 2017-06-05 下午8.11.10.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-5 21:31:33 | 显示全部楼层

哦,谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-9 19:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表