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

Linux下C语言用fgets比较文件:函数始终返回0问题求助

问题分析与解决方案

咱们先拆解下你的compare函数为啥一直返回0,以及存在的其他问题,再给出修复后的代码和更可靠的替代实现:

你的代码核心问题

  • 逻辑完全搞反了:你要的是「文件内容相同返回1,不同返回0」,但你的代码里只要发现某一行相等就立刻返回0,这和需求完全相反。正确逻辑应该是:只要发现任意一行不同,就返回0;只有所有内容匹配且两个文件都读完时,才返回1。
  • 没处理文件长度不一致的情况:比如一个文件比另一个多几行,循环会在短文件读完后直接返回1,但长文件还有内容没比较,这显然错误。
  • 缺少文件打开失败的检查:如果文件不存在或没有权限,fopen会返回NULL,后续调用fgets会导致程序崩溃或未定义行为。
  • 固定缓冲区有截断风险:如果文件里有一行超过999字节(fgets要留一个字节存终止符),会被截断,导致比较结果不准。

修复后的compare函数

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

int compare(char *file_1, char *file_2) {
    FILE *data_1 = fopen(file_1, "r");
    FILE *data_2 = fopen(file_2, "r");
    
    // 检查文件是否成功打开
    if (data_1 == NULL || data_2 == NULL) {
        // 避免内存泄漏,关闭已打开的文件
        if (data_1) fclose(data_1);
        if (data_2) fclose(data_2);
        return 0;
    }

    char line1[1000];
    char line2[1000];
    bool files_match = true;

    while (true) {
        bool got_line1 = (fgets(line1, sizeof(line1), data_1) != NULL);
        bool got_line2 = (fgets(line2, sizeof(line2), data_2) != NULL);

        // 一个文件读完,另一个没读完 → 内容不同
        if (got_line1 != got_line2) {
            files_match = false;
            break;
        }

        // 两个文件都读完了 → 跳出循环
        if (!got_line1 && !got_line2) {
            break;
        }

        // 当前行不相等 → 标记为不匹配并跳出
        if (strcmp(line1, line2) != 0) {
            files_match = false;
            break;
        }
    }

    fclose(data_1);
    fclose(data_2);

    // 匹配返回1,不匹配返回0
    return files_match ? 1 : 0;
}

更高效的替代实现

如果你的使用场景允许,这些方法会更可靠:

1. 先比文件大小,再逐字节比较

先通过stat获取文件大小,大小不同直接返回0;大小相同再逐字节比较,避免行截断问题,也更高效:

#include <stdio.h>
#include <sys/stat.h>
#include <stdbool.h>

int compare(char *file_1, char *file_2) {
    struct stat st1, st2;
    // 获取文件信息失败,或大小不同 → 直接返回0
    if (stat(file_1, &st1) != 0 || stat(file_2, &st2) != 0 || st1.st_size != st2.st_size) {
        return 0;
    }

    FILE *data_1 = fopen(file_1, "rb");
    FILE *data_2 = fopen(file_2, "rb");
    if (data_1 == NULL || data_2 == NULL) {
        if (data_1) fclose(data_1);
        if (data_2) fclose(data_2);
        return 0;
    }

    bool files_match = true;
    int c1, c2;
    while ((c1 = fgetc(data_1)) != EOF && (c2 = fgetc(data_2)) != EOF) {
        if (c1 != c2) {
            files_match = false;
            break;
        }
    }

    fclose(data_1);
    fclose(data_2);

    return files_match ? 1 : 0;
}

这里用"rb"二进制模式打开,避免Windows下换行符自动转换导致的差异(如果需要忽略换行符差异,可以额外处理)。

2. 读入内存用memcmp比较(适合小文件)

如果文件不大,可以把整个文件读入内存,用memcmp直接比较,速度更快:

#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>

int compare(char *file_1, char *file_2) {
    struct stat st1, st2;
    if (stat(file_1, &st1) != 0 || stat(file_2, &st2) != 0 || st1.st_size != st2.st_size) {
        return 0;
    }

    FILE *f1 = fopen(file_1, "rb");
    FILE *f2 = fopen(file_2, "rb");
    if (!f1 || !f2) {
        if (f1) fclose(f1);
        if (f2) fclose(f2);
        return 0;
    }

    char *buf1 = malloc(st1.st_size);
    char *buf2 = malloc(st2.st_size);
    if (!buf1 || !buf2) {
        free(buf1);
        free(buf2);
        fclose(f1);
        fclose(f2);
        return 0;
    }

    fread(buf1, 1, st1.st_size, f1);
    fread(buf2, 1, st2.st_size, f2);

    int result = (memcmp(buf1, buf2, st1.st_size) == 0) ? 1 : 0;

    free(buf1);
    free(buf2);
    fclose(f1);
    fclose(f2);

    return result;
}

注意:这种方法不适合超大文件,会占用过多内存。

内容的提问来源于stack exchange,提问作者Don Kielon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:56:42