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

如何用C语言低级I/O函数实现文件内容输出并统计行数?

问题分析与修正方案

核心问题拆解

  • 统计时机完全错误:你在文件读取完成后才遍历缓冲区,但每次read(fd, buffer, 1)仅读取1个字符到buffer[0],之前的字符已被覆盖,循环结束后缓冲区里只有最后一次读取的字符(甚至可能是无效值),根本无法统计所有换行。
  • 命令行参数索引错误:argv[3]不符合常规参数逻辑,程序启动时argv[0]是程序名,第一个输入的文件名参数应为argv[1]。
  • 错误处理不完整:open失败后仅调用perror却不退出程序,后续代码会继续使用无效的文件描述符,引发更多错误。
  • 边界场景遗漏:若文件最后一行未以\n结尾,按照常规统计规则应计入行数,但你的代码不会处理这种情况。

修正后的代码

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>

#define BUFFSIZE 1024  // 定义合理缓冲区大小,提升IO效率

int main(int argc, char *argv[]) {
    // 检查参数数量
    if (argc < 2) {
        write(STDERR_FILENO, "用法: ./程序名 <文件名>\n", 22);
        exit(EXIT_FAILURE);
    }

    int lineCounter = 0;
    int hasContent = 0;  // 标记文件是否有内容,处理最后一行无换行的情况
    char *filename = argv[1];
    int fd = open(filename, O_RDONLY);
    
    // 打开文件失败直接退出
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    int n;
    char buffer[BUFFSIZE];

    // 批量读取文件内容,同时统计换行
    while ((n = read(fd, buffer, BUFFSIZE)) > 0) {
        write(STDOUT_FILENO, buffer, n);
        hasContent = 1;
        
        // 遍历当前读取的n个字符,统计换行
        for (int i = 0; i < n; i++) {
            if (buffer[i] == '\n') {
                lineCounter++;
            }
        }
    }

    // 处理最后一行无换行的情况
    if (hasContent) {
        // 回退一个字符检查最后一个字符是否为换行
        if (lseek(fd, -1, SEEK_CUR) != -1) {
            char lastChar;
            if (read(fd, &lastChar, 1) == 1 && lastChar != '\n') {
                lineCounter++;
            }
        }
    }

    // 输出行数(若需纯低级IO实现数字转字符串,可自行编写转换逻辑)
    printf("\n总行数: %d\n", lineCounter);

    close(fd);
    return 0;
}

关键优化点说明

  • 高效IO处理:改为批量读取BUFFSIZE字节,既提升效率,又能在每次读取后立即处理当前缓冲区的字符,实时统计换行。
  • 参数与错误修正:修复命令行参数索引,补充参数数量检查,文件打开失败后直接退出程序。
  • 边界场景处理:通过lseek回查最后一个字符,确保无换行的最后一行被正确统计。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:20:44