【问题标题】:How to stop reading a txt file at the end of it如何在它的末尾停止读取 txt 文件
【发布时间】:2020-03-21 13:37:47
【问题描述】:

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

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

我认为这是因为只有在您尝试 fscanf 某些东西但那里什么都没有时才会触发 eof 标志。我该如何解决这个问题?将最终的 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));

【问题讨论】:

  • 这能回答你的问题吗? Why is “while ( !feof (file) )” always wrong?
  • 您可以使用来自fscanf 的返回值来控制循环。 while(fscanf(...) == expectedNumberOfItems) {...}。不管怎样,你应该总是检查scanf函数族的返回值。
  • 投票支持重新打开,因为问题的主题是do-while 循环内的读取操作,而不是while-loop。这对提供的副本有所不同。
  • @exnihilo 对我来说,副本不相关,因为它即将使用 feof before 任何读取。同意正确的方法是检查任何读取的结果,如果可能的话,使用 while(fscanf(...) == ...) ... 如 WeatherVane 或类似 的建议for () { ... if (fscanf(...) != ...) 中断; ... } ofc
  • @exnihilo 我们不知道 OP 对该语句的含义以及问题本身的整个表达方式。这是一个大问题。我同意,这个问题应该因为“需要更多关注”而结束。

标签: c printf scanf


【解决方案1】:

由于您使用的是fscanf()

ISO/IEC 9899:2017

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

EOF是一个宏,其值为-1,它本身并不能区分它出现的原因。

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

示例 3stdin 重复接受数量、计量单位和项目名称:

#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 和错误输入的循环。

【讨论】:

    猜你喜欢
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 2011-12-15
    • 2020-11-17
    • 2021-11-13
    • 1970-01-01
    相关资源
    最近更新 更多