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

自制cat函数时首字符丢失及末尾字符异常问题求助

实现Linux cat命令的两个问题修复方案

问题1:第二行开始首字符丢失的原因及修复

原代码中,每次用fgets读取一行后,额外调用了fgetc(file)读取下一个字符。fgets会把当前行(包括末尾的换行符)完整读入缓冲区,之后fgetc会读取下一行的第一个字符,这个字符被读取后没有输出,直接被丢弃,导致后续行首字符缺失。

修复方式:完全移除多余的fgetc判断逻辑,fgets已经能正确读取每行内容(含换行符),直接输出缓冲区内容即可。

问题2:最后一行末尾字符丢失的原因及修复

修改后的代码中,强行将line[strlen(line)-1]设为'\0',这会破坏原有内容:

  • 如果行末尾有换行符,会把换行符删掉,之后手动加\n输出看似正常,但属于多余操作
  • 如果文件最后一行没有换行符,strlen(line)得到的是该行有效字符长度,line[strlen(line)-1]就是最后一个有效字符,被替换为'\0'后直接丢失,导致输出少了末尾字符

修复方式:直接输出fgets读取的内容,不要修改缓冲区的末尾字符,保留文件原有换行格式。

正确的实现代码

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

int main(int argc, char *argv[]) {
    FILE *file = NULL;
    char line[4096];
    int cur_file = 1;

    // 处理标准输入(无参数或参数为"-")
    if (argc == 1 || (strcmp(argv[1], "-") == 0)) {
        while (fgets(line, sizeof(line), stdin)) {
            printf("%s", line);
        }
        return 0;
    }

    // 遍历处理所有文件参数
    while (cur_file < argc) {
        file = fopen(argv[cur_file], "r");
        if (file == NULL) {
            fprintf(stderr, "%s: no such file or directory\n", argv[cur_file]);
            cur_file++;
            continue;
        }

        // 逐行读取并输出
        while (fgets(line, sizeof(line), file)) {
            printf("%s", line);
        }

        fclose(file);
        cur_file++;
    }

    return 0;
}

代码改进说明

  • 移除了冗余的字符读取逻辑,保证每行内容完整输出
  • 修复标准输入处理:原scanf写法存在格式错误和缓冲区残留问题,改用fgets读取标准输入更可靠
  • 优化错误处理:遇到不存在的文件时,输出错误信息后继续处理后续文件,符合cat命令的原生行为
  • 简化变量结构,去掉无用的临时数组,提升代码简洁性

测试验证

使用你的测试文件b.txt执行./mycat b.txt b.txt,输出将与原文件内容完全一致:

Hello world!
Great, one more file.
Just what we need.
Hello world!
Great, one more file.
Just what we need.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 17:35:14