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
相关产品推荐
相关产品推荐

