鱼C论坛

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

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

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

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

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

x
char c;
while(!feof(fp))
{
c = fgetc(fp);
printf("%X/n", c); 
}
在运行这个程序时,会多输出一个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 函数的一部分,我找不到完整的^_^
#define NOCCARGC  /* no argument count passing */
#include stdio.h
#include clib.def
/*
** Character-stream input of one character from fd.
** Entry: fd = File descriptor of pertinent file.
** Returns the next character on success, else EOF.
*/
fgetc(fd) int fd; {

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

        Useteof(fd);
        return(EOF);
  
}
  ch=buff;
  switch(ch) {

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

                     default: --Uchrpos[fd];
                     case 0:
                     case BUFSIZE:
                     
}  */
                   Useteof(fd);
                   return (EOF);
      case CR:     return ('\n');
      case LF:    /* NOTE: Uconin() maps LF -> CR */
  
}
 
}
#asm
_getc EQU   _fgetc
     PUBLIC _getc
#endasm

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


在程序中
#include <stdio.h>

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

        char c;
        while (!feof(fp))
        {
                c = fgetc(fp);
                printf("%X/n", c);
        }

        return 0;
}

假设文件 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
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2017-6-4 17:10:44 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> 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的循环:
while(1)
{
char c = fgetc(fp);

if(feof(fp))
{
    break;
}
   printf("%c\n",c);
}


评分

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

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

这个问题和fgetc函数有关

这是 fgetc 函数的一部分,我找不到完整的^_^
#define NOCCARGC  /* no argument count passing */
#include stdio.h
#include clib.def
/*
** Character-stream input of one character from fd.
** Entry: fd = File descriptor of pertinent file.
** Returns the next character on success, else EOF.
*/
fgetc(fd) int fd; {

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

        Useteof(fd);
        return(EOF);
  
}
  ch=buff;
  switch(ch) {

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

                     default: --Uchrpos[fd];
                     case 0:
                     case BUFSIZE:
                     
}  */
                   Useteof(fd);
                   return (EOF);
      case CR:     return ('\n');
      case LF:    /* NOTE: Uconin() maps LF -> CR */
  
}
 
}
#asm
_getc EQU   _fgetc
     PUBLIC _getc
#endasm

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


在程序中
#include <stdio.h>

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

        char c;
        while (!feof(fp))
        {
                c = fgetc(fp);
                printf("%X/n", c);
        }

        return 0;
}

假设文件 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
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

你这个从哪里找的?fgetc源码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-4 22:58:21 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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


你能不能从GitHub是的glibc上找到fgetc源码,我找不到fgetc在glibc源码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

我已经在glibc找过了,没有找到
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

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

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

#include <ansidecl.h>
#include <errno.h>
#include <stdio.h>


/* Read a character from STREAM.  */
int
DEFUN(fgetc, (stream), FILE *stream)
{
  if (!__validfp(stream) || !stream->__mode.__read)
    {
      errno = EINVAL;
      return EOF;
    }

  return __getc(stream);
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

在哪找到的?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

在这里glibc源码
屏幕快照 2017-06-05 下午8.11.10.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

哦,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-9-28 05:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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