曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6592|回复: 0
打印 上一主题 下一主题

[文件I/O] feof() -- 文件结束检查

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-7-8 03:56:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
函数 feof() 用来检测流上的文件结束符。函数声明如下:
[C++] 纯文本查看 复制代码
#include <stdio.h>
int feof(FILE *stream);


feof(fp)有两个返回值:如果遇到文件结束,函数 feof() 就返回非零值,否则为0。

EOF 是文件结束标志的文件。在文本文件中,数据是以字符的 ASCII 代码值的形式存放,ASCII 代码的范围是 0 到 127,如下图所示:


ASCII 码并没有规定编号为 128~255 的字符,为了能表示更多字符,各厂商制定了很多种ASCII码的扩展规范。注意,虽然通常把这些规范称为扩展ASCII码(Extended ASCII),但其实它们并不属于ASCII码标准。例如以下这种扩展ASCII码由IBM制定,在字符终端下被广泛采用,其中包含了很多表格边线字符用来画界面,如下图所示:

由上图可见,255 时并没有定义什么字符,所以在对数据进行字符形式存取时,不可能回遇到 -1 这种情况,所以将 -1 当成是 EOF,也就是说,当读到 -1 时,就认为读取文件结束。

测试代码:
[C++] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    FILE *fp;    
    char combuf[512];
    char *pbuf = combuf;

    if (!(fp = fopen(argv[1], "r"))) {
        perror ("fopen error");
        exit (EXIT_FAILURE);
    }
    memset (combuf, 0, 512);
    while (!feof(fp)) {
        *pbuf++ = fgetc (fp);
    }
    fclose(fp);
    printf ("%s\n", combuf);
    return (0);
}

上面代码用以读取一个简短的普通文本文件(通过 echo "hello world" > test.txt 得到)到数组,然后输出。在读取文件中,我们一次读取一个字符,并且用 feof() 函数判断是否读取到末位。下面运行该程序查看会有什么问题:
$ ./readtest test.txt
hello world
我们看到最后最后输出了一个乱码符。这个乱码字符串实际就是 EOF,十六进制表示为 0xff,八进制即 o377,十进制 -1 。如果用 gdb 调试时可以看到数组内存中 EOF 被读入的值为 \377 。

feof() 函数的停止条件是通过判断文件流指针是否到达 EOF 来决定的。

先来看 fgetc() 函数,根据对上面程序的调试观察与 man 手册中的说明, fgetc()  并不是如一些人所说一次读取一个字节,并在读完之后将文件流指针自动移动到下一个字节处。实际情况是,fgetc() 读取当前文件流指针所指字符的下一个字符,然后文件流指针再移动到该被读取的字符上。

另外,使用 echo "hello world" 这种方式到一个普通文本时,会在 "hello world" 的末位自动添加上一个换行符 '\n' 以及结束符 EOF。所以,当 fgetc() 将换行符 '\n' 读入数组时,文件流指针是指向 '\n' 的,因此这时 feof() 函数会判断还没到达文件尾,所以当下一次读取时,fgetc() 会读入 EOF,同时 feof() 也会结束 while 循环。

从上面分析可以知道为什么会输出一个乱码符号。修正这种现象,可以在 fclose() 函数之前添加一句 *(pbuf - 1) = '\0'; 以显式的去掉 EOF 符号。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-4 20:20 , Processed in 0.077373 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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