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

C语言:使用strcmp比较文本文件相邻行时末尾行异常问题

这个问题我太熟了——fgets的换行符陷阱几乎是每个C新手都会踩的坑!咱们一步步拆解:

首先,你看到的额外字符十有八九是换行符('\n'),甚至可能是Windows系统下的回车符('\r')。fgets的特性是:它会把输入中的换行符一起读进缓冲区,直到遇到换行或EOF才停止,而且会自动在末尾加'\0'。

比如你的例子里,倒数第二行"four"后面跟着换行符,所以fgets读出来的是"four\n",strlen算出来是5('f'+'o'+'u'+'r'+'\n');而最后一行如果是Windows格式的结尾,会带有\r\n,读出来就是"four\r\n",长度直接变成6。这时候两个字符串一个是"four\n"一个是"four\r\n",strcmp自然会返回非0,因为底层内容根本不一样。

那怎么解决?核心就是读取每行后,把末尾的换行/回车符去掉,统一格式再比较。

我给你写个实用的处理函数,能同时兼容Unix('\n')和Windows('\r\n')的换行格式:

void trim_trailing_newline(char *str) {
    if (!str) return;
    
    size_t len = strlen(str);
    // 先去掉换行符
    if (len > 0 && str[len - 1] == '\n') {
        str[--len] = '\0';
        // 如果去掉换行后末尾是回车,再去掉回车
        if (len > 0 && str[len - 1] == '\r') {
            str[--len] = '\0';
        }
    }
}

然后修改你的读取逻辑,每次用fgets读行后,先调用这个函数处理:

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

void trim_trailing_newline(char *str) {
    if (!str) return;
    
    size_t len = strlen(str);
    if (len > 0 && str[len - 1] == '\n') {
        str[--len] = '\0';
        if (len > 0 && str[len - 1] == '\r') {
            str[--len] = '\0';
        }
    }
}

int main() {
    char prev_line[256], curr_line[256];
    
    // 读取第一行,处理空文件或读取错误的边界情况
    if (!fgets(prev_line, sizeof(prev_line), stdin)) {
        fprintf(stderr, "空文件或读取错误\n");
        return 1;
    }
    trim_trailing_newline(prev_line);
    
    while (fgets(curr_line, sizeof(curr_line), stdin)) {
        trim_trailing_newline(curr_line);
        
        // 现在比较就没问题了
        int cmp_result = strcmp(prev_line, curr_line);
        if (cmp_result == 0) {
            printf("相邻行相等:%s\n", prev_line);
        } else {
            printf("相邻行不等:%s vs %s(strcmp返回值:%d)\n", prev_line, curr_line, cmp_result);
        }
        
        // 把当前行复制到前一行,准备下一次循环
        strcpy(prev_line, curr_line);
    }
    
    return 0;
}

另外还要注意两个小细节:

  • 确保你的缓冲区大小足够容纳最长的行,如果行长度超过缓冲区,fgets会截断,导致读取不完整,这时候也会出现奇怪的比较结果。如果不确定行长度,可以用动态分配的缓冲区(比如用malloc配合realloc)。
  • 检查fgets的返回值,如果返回NULL,要么是到了EOF,要么是读取错误,要正确处理这种情况,避免访问无效的内存。

这样修改后,不管每行末尾有没有换行,也不管是Unix还是Windows格式的换行,都能统一成没有换行符的纯内容,strcmp就能正确比较了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:47:04