You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用fprintf和fscanf的C文件操作程序陷入无限循环且仅打印最后条目

解决fprintf/fscanf文件操作时的无限循环+重复打印最后一条数据问题

嘿,我来帮你搞定这个头疼的问题!这种用fprintf和fscanf操作文件时陷入无限循环、还一个劲重复打印最后一条输入的情况,我之前踩过好多次坑,大概率是文件指针没归位或者循环条件写错了,咱们一步步拆解问题、解决它。

常见错误原因及对应解决方法

1. 写入文件后未重置文件指针到起始位置

当你用fprintf写完数据后,文件指针会停在文件的末尾位置。这时候直接调用fscanf读取,根本读不到新内容,但如果你的循环没做正确的退出判断,就会一直打印变量里存着的最后一次输入值,看起来就像无限循环了。

解决办法:写完数据后,用rewind(fp)或者fseek(fp, 0, SEEK_SET)把文件指针移回文件开头,这样读取操作才能从第一条数据开始。

2. 错误使用feof()作为循环条件

很多新手会用while(!feof(fp))来控制读取循环,但这是个典型的误区!feof()只有在尝试读取超出文件末尾之后才会返回真,也就是说,当你读到最后一条数据后,feof()还是假,循环会再执行一次——这时候fscanf读取失败,但变量里还保留着最后一次的有效值,就会重复打印这条内容,甚至因为没正确处理读取失败的情况,陷入无限循环。

正确做法:检查fscanf()的返回值。fscanf会返回成功读取的参数个数,比如你要读int和char[]两个参数,就判断返回值是否等于2,等于就继续循环,否则退出。

错误代码示例 vs 修正后的代码

错误代码(会触发无限循环+重复打印)

#include <stdio.h>

typedef struct {
    int id;
    char name[20];
} Student;

int main() {
    FILE *fp = fopen("students.txt", "w+");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    Student s;
    // 输入2条学生数据
    for (int i = 0; i < 2; i++) {
        printf("Enter id and name: ");
        scanf("%d %s", &s.id, s.name);
        fprintf(fp, "%d %s\n", s.id, s.name);
    }

    // 错误1:文件指针在末尾,直接读取无数据
    // 错误2:用feof()做循环条件,导致多执行一次循环
    while (!feof(fp)) {
        fscanf(fp, "%d %s", &s.id, s.name);
        printf("ID: %d, Name: %s\n", s.id, s.name);
    }

    fclose(fp);
    return 0;
}

修正后的代码(正常读取所有数据,无循环问题)

#include <stdio.h>

typedef struct {
    int id;
    char name[20];
} Student;

int main() {
    FILE *fp = fopen("students.txt", "w+");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    Student s;
    // 输入2条学生数据,同时处理输入错误
    for (int i = 0; i < 2; i++) {
        printf("Enter id and name: ");
        // 检查scanf是否成功读取2个参数
        if (scanf("%d %s", &s.id, s.name) != 2) {
            printf("Invalid input! Please try again.\n");
            // 清空输入缓冲区,避免错误输入影响后续读取
            while (getchar() != '\n');
            i--; // 重新输入当前条目
            continue;
        }
        fprintf(fp, "%d %s\n", s.id, s.name);
    }

    // 关键:将文件指针移回文件起始位置
    rewind(fp);
    // 等价写法:fseek(fp, 0, SEEK_SET);

    // 正确循环:通过fscanf返回值判断是否读取成功
    while (fscanf(fp, "%d %s", &s.id, s.name) == 2) {
        printf("ID: %d, Name: %s\n", s.id, s.name);
    }

    fclose(fp);
    return 0;
}

额外注意事项

  • 选择正确的文件打开模式:比如w+模式会清空原有文件内容,如果需要保留旧数据并追加新内容,应该用a+,但a+模式下写入始终在文件末尾,读取前同样需要移回指针。
  • 处理输入错误:如果用户输入了不符合格式的内容(比如输入字符串代替数字),scanf或fscanf会读取失败,这时候要清空输入缓冲区,避免后续读取一直出错。

内容的提问来源于stack exchange,提问作者SowmYa Ramesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:04:17