如何在文件末尾停止读取txt文件

时间:2020-03-21 13:37:47

标签: c printf scanf

我正在编写一个C程序,该程序逐行读取具有特定格式的文本文件。

我做了一个do { ... } while(!feof(file));循环,但它总是循环太多次。这是一个问题,因为我已经做到了,所以当我的程序希望读取某些内容但什么也没得到时,它会引发错误,所以现在每次都引发一个错误,因为它到达了循环顶部的文件末尾

我认为这是因为eof标志仅在您尝试fscanf某个东西时触发,但那里什么也没有。我该如何解决这个问题?将最后一个fscanf放在底部是行不通的,因为如果不在文件末尾,则它将使所有读数弄乱,并将所有内容移位一个。

do {
    read = fscanf(/*...*/);
    if (read != 1)
    {
        return -1;
    }
    // Read grades
    read = fscanf(/*...*/);
    if (read != 3)
    {
        return -1;
    }
    // Read student kind
    int student_kind = 0;
    read = fscanf(/*...*/);
    if (read != 1)
    {
        return -1;
    }
    if (student_kind < 0 | student_kind > 2)
    {
        printf("Invalid student kind");
        return -1;
    }

    SCIPER sciper_teammate = 0;
    read = fscanf(/*...*/);
    if (read != 1)
    {
        return -1;
    }
} while (!feof(file));

1 个答案:

答案 0 :(得分:0)

由于您使用的是fscanf()

ISO/IEC 9899:2017

§7.21.6.2-16 -如果在第一次转换(如果有)完成之前发生输入失败,则fscanf函数将返回宏EOF的值。否则,该函数将返回分配的输入项目数,如果早期匹配失败,该数目可能少于所提供的输入项数,甚至为零。

EOF是一个值为-1的宏,就其发生的原因而言,它本身是无法区分的。

出于这种区别,§7.21.6.2-19 建议对文件结尾使用feof(),对I / O错误使用ferror()

示例3 要从stdin反复接受数量,计量单位和商品名称:

#include<stdio.h> 

/*...*/

int count; floatquant; 
charunits[21],  item[21]; 

do { 
    count = fscanf(stdin, "%f%20sof%20s", &quant, units, item);
    fscanf(stdin,"%*[^\n]"); //here discarding unread characters in the buffer 
} while(!feof(stdin) && !ferror(stdin));

这应该适合您的情况,但个人而言。我不喜欢这种方法,因为如果您输入的值少于fscanf所期望的值,这将失败,通常会导致无限循环。

读取格式化输入时,我的方法是检查输入值。

对于2个整数的样本输入,您可以执行以下操作:

Live sample

#include <stdio.h>

int main()
{
    int a, b;
    FILE* file;
    if(!(file = fopen("file.txt", "r"))){
        return 1;
    }
    while(fscanf(file, "%d %d", &a, &b) == 2){ //read each 2 integers in the file, stop when condition fails, i.e. there are nothing else to read or the read input is not an integer
        printf("%d %d\n", a, b);
    }
}

这解决了所有输入故障,并且会因I / O错误,EOF和错误输入而终止循环。