如何从指定行开始读取文件?文件对比程序技术问询
嘿,我看了你写的文件对比代码,这里有几个需要调整的地方,同时我会帮你实现从特定行开始读取的功能,还满足你要求的「命令行传入文件名」的需求:
先说说原代码里的几个小问题
- 硬编码了文件名,不符合命令行传参的要求,得用
argc和argv来获取输入的文件名 - 逐字符对比的方式不仅低效,处理换行的逻辑也容易出错,换成逐行读取(用
fgets)会更清晰,也方便定位行号 - 代码里有语法错误:
pos变量没定义、error++后面缺分号,而且fopen最好显式指定只读模式"r",另外exit和perror需要对应的头文件支持
改进后的完整代码
我重新写了一个版本,包含了你需要的所有功能,还加了一些实用的细节(比如处理不同换行符、文件长度不一致的情况):
#include <stdio.h> #include <stdlib.h> #include <string.h> // 跳过文件的前n行,返回0表示成功,非0表示出错或文件提前结束 int skip_lines(FILE *fp, int n) { char buf[1024]; for (int i = 0; i < n; i++) { if (fgets(buf, sizeof(buf), fp) == NULL) { // 要么到了文件末尾,要么读取错误 return 1; } } return 0; } int main(int argc, char *argv[]) { // 检查命令行参数:程序名 + 文件1 + 文件2 + 起始行号(可选,默认从第1行开始) if (argc < 3 || argc > 4) { fprintf(stderr, "用法: %s <文件1> <文件2> [起始行号]\n", argv[0]); return EXIT_FAILURE; } int start_line = 1; if (argc == 4) { // 把字符串转成整数,检查合法性 char *endptr; start_line = strtol(argv[3], &endptr, 10); if (*endptr != '\0' || start_line < 1) { fprintf(stderr, "起始行号必须是大于等于1的整数\n"); return EXIT_FAILURE; } } // 打开两个文件,用只读模式 FILE *fp1 = fopen(argv[1], "r"); FILE *fp2 = fopen(argv[2], "r"); if (fp1 == NULL || fp2 == NULL) { perror("打开文件失败"); // 关闭已经打开的文件,避免资源泄漏 if (fp1 != NULL) fclose(fp1); if (fp2 != NULL) fclose(fp2); return EXIT_FAILURE; } // 跳过起始行之前的行(比如要从第5行开始,就跳过前4行) if (skip_lines(fp1, start_line - 1) != 0) { fprintf(stderr, "文件%s没有足够的行,无法跳转到第%d行\n", argv[1], start_line); fclose(fp1); fclose(fp2); return EXIT_FAILURE; } if (skip_lines(fp2, start_line - 1) != 0) { fprintf(stderr, "文件%s没有足够的行,无法跳转到第%d行\n", argv[2], start_line); fclose(fp1); fclose(fp2); return EXIT_FAILURE; } char line1[1024], line2[1024]; int current_line = start_line; int diff_count = 0; // 逐行读取并对比 while (fgets(line1, sizeof(line1), fp1) != NULL && fgets(line2, sizeof(line2), fp2) != NULL) { // 处理不同的换行符(Windows的\r\n和Linux的\n),避免误判 size_t len1 = strlen(line1); if (len1 > 0 && line1[len1 - 1] == '\n') { line1[len1 - 1] = '\0'; // 再检查是否有\r if (len1 > 1 && line1[len1 - 2] == '\r') { line1[len1 - 2] = '\0'; } } size_t len2 = strlen(line2); if (len2 > 0 && line2[len2 - 1] == '\n') { line2[len2 - 1] = '\0'; if (len2 > 1 && line2[len2 - 2] == '\r') { line2[len2 - 2] = '\0'; } } if (strcmp(line1, line2) != 0) { diff_count++; printf("第%d行内容不同:\n", current_line); printf(" %s: %s\n", argv[1], line1); printf(" %s: %s\n", argv[2], line2); } current_line++; } // 处理其中一个文件先读完的情况 if (fgets(line1, sizeof(line1), fp1) != NULL) { printf("第%d行开始,文件%s还有多余内容:\n", current_line, argv[1]); do { // 同样处理换行符 size_t len = strlen(line1); if (len > 0 && line1[len - 1] == '\n') line1[len - 1] = '\0'; if (len > 1 && line1[len - 2] == '\r') line1[len - 2] = '\0'; printf(" %s\n", line1); current_line++; } while (fgets(line1, sizeof(line1), fp1) != NULL); diff_count++; } else if (fgets(line2, sizeof(line2), fp2) != NULL) { printf("第%d行开始,文件%s还有多余内容:\n", current_line, argv[2]); do { size_t len = strlen(line2); if (len > 0 && line2[len - 1] == '\n') line2[len - 1] = '\0'; if (len > 1 && line2[len - 2] == '\r') line2[len - 2] = '\0'; printf(" %s\n", line2); current_line++; } while (fgets(line2, sizeof(line2), fp2) != NULL); diff_count++; } if (diff_count == 0) { printf("从第%d行开始,两个文件内容完全相同\n", start_line); } else { printf("共发现%d处不同\n", diff_count); } // 关闭文件 fclose(fp1); fclose(fp2); return EXIT_SUCCESS; }
关键功能说明
- 命令行参数支持:
- 基础用法:
./your_program file1.txt file2.txt(从第1行开始对比) - 指定起始行:
./your_program file1.txt file2.txt 5(从第5行开始对比)
- 基础用法:
- 跳过指定行:
用skip_lines函数逐行读取跳过,比逐字符处理换行更可靠,还能提前判断文件是否有足够的行数 - 换行符兼容:
自动处理Windows的\r\n和Linux的\n,避免因为换行格式不同误判为内容不同 - 完整的错误处理:
包含文件打开失败、行数不足、参数错误等情况的提示,还会关闭已打开的文件避免资源泄漏
内容的提问来源于stack exchange,提问作者Aimin
相关产品推荐
相关产品推荐

