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

使用fgets与for循环查找相邻重复字符串时遇问题求助

相邻行比较程序的问题分析与修复

问题描述

需要编写程序读取文本文件,用fgets()依次将相邻两行存入不同数组,通过strcmp()比较;即先比较第1行和第2行,再比较第2行和第3行,以此类推直到文件末尾,要求用for循环实现。但运行后发现line1一直显示第一行的Hello?,无法读取后续行,寻求解决方法。

测试文件内容(a.txt)

Hello?
Hello?
Hello?


No answer? Let's try again:
Hello?
Tik
Tok
Tok
tok

运行异常结果

dup
 L1 Hello?
 L2 Hello?
dup
 L1 Hello?
 L2 Hello?
no dup
 L1 Hello?
 L2 
no dup
 L1 Hello?
 L2 
no dup
 L1 Hello?
 L2 No answer? Let's try again:
dup
 L1 Hello?
 L2 Hello?
no dup
 L1 Hello?
 L2 Tik
no dup
 L1 Hello?
 L2 Tok
no dup
 L1 Hello?
 L2 Tok
no dup
 L1 Hello?
 L2 tok-----
this is the file name:a.txt

问题代码片段

char * filename =  argv[argc-1];

FILE *f; 
f = fopen(filename, "r");
if(f == NULL) 
{
      fprintf(stderr, "unable to open file\n");
      return 1;
}

char  line1[MAX_CHAR_FOR_LINE_INPUT];
char  line2[MAX_CHAR_FOR_LINE_INPUT];
    


for (char * j = fgets(line1, MAX_CHAR_FOR_LINE_INPUT,f); j != NULL; j  = fgets(line1, MAX_CHAR_FOR_LINE_INPUT,f) ){
    for (char * n = fgets(line2, MAX_CHAR_FOR_LINE_INPUT,f); n != NULL; n = fgets(line2, MAX_CHAR_FOR_LINE_INPUT,f) ){
        int value = strcmp(line1,line2); 
        if ( value == 0 ){
            printf("dup\n");
        }  
        else{
            printf("no dup\n");
        }
        printf("%s",line1);
        printf("%s",line2);
    }
    printf("-----\n");
}

问题原因

你用了嵌套for循环,逻辑完全错误:

  1. 外层循环第一次执行时,line1读取了第一行Hello?;
  2. 内层循环会一次性把文件中剩下的所有行全部读取到line2中,直到文件指针移到末尾;
  3. 此时外层循环再次调用fgets(line1,...)时,因为文件已经读完,返回NULL,外层循环直接终止,所以line1永远停留在第一次读取的Hello?,不会更新。

另外,不需要手动清空数组,fgets()每次读取时会覆盖数组内的旧内容(只要行长度不超过数组容量)。

修正后的代码(for循环实现)

核心逻辑是:先读取第一行到line1,然后在for循环中持续读取下一行到line2,比较完成后,将line2的内容复制到line1,作为下一次比较的前一行,直到fgets()无法读取新行。

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

#define MAX_CHAR_FOR_LINE_INPUT 256

int main(int argc, char *argv[]) {
    if (argc < 2) {
        fprintf(stderr, "usage: %s <filename>\n", argv[0]);
        return 1;
    }

    char *filename = argv[argc-1];
    FILE *f = fopen(filename, "r");
    if (f == NULL) {
        fprintf(stderr, "unable to open file\n");
        return 1;
    }

    char line1[MAX_CHAR_FOR_LINE_INPUT];
    char line2[MAX_CHAR_FOR_LINE_INPUT];

    // 先读取第一行,作为初始的前一行
    if (fgets(line1, MAX_CHAR_FOR_LINE_INPUT, f) == NULL) {
        fclose(f);
        return 0; // 文件为空
    }

    // for循环实现:每次读取新行到line2,比较后更新line1
    for (char *n = fgets(line2, MAX_CHAR_FOR_LINE_INPUT, f); 
         n != NULL; 
         n = fgets(line2, MAX_CHAR_FOR_LINE_INPUT, f)) {
        
        int value = strcmp(line1, line2);
        if (value == 0) {
            printf("dup\n");
        } else {
            printf("no dup\n");
        }
        printf(" L1 %s", line1);
        printf(" L2 %s", line2);

        // 将当前line2的内容复制到line1,作为下一次比较的前一行
        strncpy(line1, line2, MAX_CHAR_FOR_LINE_INPUT - 1);
        line1[MAX_CHAR_FOR_LINE_INPUT - 1] = '\0'; // 确保字符串结束符
    }

    printf("-----\n");
    printf("this is the file name:%s\n", filename);
    fclose(f);
    return 0;
}

说明

  • 使用strncpy()复制行内容时,要手动添加字符串结束符,避免数组越界导致的未定义行为;
  • 增加了文件为空的判断,以及命令行参数检查,提升程序健壮性;
  • 循环逻辑改为顺序迭代相邻行,符合需求中“第1行和第2行、第2行和第3行…”的比较要求。

内容的提问来源于stack exchange,提问作者Josue Nunez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:20:43