别再用"while (!feof(file))"来逐行读取txt文件了!

起因

执行一个C/C++程序出现segment fault。它逐行读取文本文件,每一行是一个图片名字,然后读图、处理图像,etc。
发现最后一次读取的文件名不存在(空的)。

正确的逐行读取txt文件

这是正确的写法:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

void read_txt(const char* path)
{
    FILE* fin = fopen(path, "r");
    if(fin==NULL) {
        fprintf(stderr, "failed to open %s\n", path);
        exit(-1);
    }
    char line[1024];
    void* ret;
    while (true) {
        memset(line, 0, sizeof(line));
        ret = fgets(line, sizeof(line), fin);
        if (ret == NULL) break;
        if(line[strlen(line)-1]=='\n' || line[strlen(line)-1]=='\r') {
            line[strlen(line) - 1] = '\0';
        }
        if(line[strlen(line)-1]=='\r' || line[strlen(line)-1]=='\n') {
            line[strlen(line) - 1] = '\0';
        }
        printf("%s\n", line);
    }
    fclose(fin);
}

int main() {
    read_txt("input.txt");
    return 0;
}

使用while (!feof(fp))来逐行读取txt是错误

简单说就是,如果用while (!feof(fp)),那么会比文件内容多一行。至于读取到什么,看你的buffer有没有每次做memset,如果有那么读取到空的;如果没有,读取到上一次的。

原理上,feof()操作是主动去查看文件流指针fp是否到达了EOF。执行这个判断时并没有“进行下一次读取”。因此,即便已经读取完了文件最后一行,因为feof()不会把文件流指针fp前移,因此得到的判断仍然是“现在不是EOF”。进而执行下一行的读取(不正确的读取)。

其实文件系统也好,并发也好,我们应该直接去读取,然后判断读取后的返回值是否为EOF或别的;而不是先去查询当前是否为EOF,然后再读取。

参考

Why is “while (!feof(file))” always wrong?

posted @ 2019-02-18 10:35  ChrisZZ  阅读(4898)  评论(0编辑  收藏  举报