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

C语言动态数组实现文件行反转+逆序输出及多文件处理问题求助

问题修复:动态数组扩容与多文件处理问题

原代码存在的核心问题

  • 动态数组初始化错误:指针数组的内存分配类型错误,且未实现扩容逻辑,行数超过初始长度时会触发越界访问
  • 变量名冲突:文件循环的外层i与内层初始化指针数组的i重复,导致多文件处理逻辑混乱
  • 内存泄漏:每个文件处理完毕后未释放动态分配的内存
  • 行长度参数未生效:未使用传入的MAX LINE LENGTH参数分配行内存,而是固定使用1025字节
  • 兼容性问题:strrev非标准C函数,部分编译器不支持
  • 错误处理不完善:单个文件打开失败直接终止程序,无法继续处理后续文件

修正后的完整代码

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

typedef enum Type {
    linenums,
    nolinenums
} Type;

struct Config {
    Type type;
    int max_line_len;
};

// 自定义字符串反转函数,替代非标准的strrev
void reverse_str(char *str) {
    if (!str) return;
    char *start = str;
    char *end = str + strlen(str) - 1;
    char temp;
    while (start < end) {
        temp = *start;
        *start = *end;
        *end = temp;
        start++;
        end--;
    }
}

int main(int argc, char *argv[]) {
    struct Config cfg;

    if (argc < 3) {
        fprintf(stderr, "Usage: %s [linenums|nolinenums] [MAX_LINE_LENGTH] files...\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    // 解析输出类型参数
    if (strcmp(argv[1], "linenums") == 0) {
        cfg.type = linenums;
    } else if (strcmp(argv[1], "nolinenums") == 0) {
        cfg.type = nolinenums;
    } else {
        fprintf(stderr, "Error: Invalid first argument. Use 'linenums' or 'nolinenums'\n");
        exit(EXIT_FAILURE);
    }

    // 解析最大行长度参数
    cfg.max_line_len = atoi(argv[2]);
    if (cfg.max_line_len <= 0) {
        fprintf(stderr, "Error: MAX_LINE_LENGTH must be a positive integer\n");
        exit(EXIT_FAILURE);
    }

    // 遍历处理所有文件
    for (int file_idx = 3; file_idx < argc; file_idx++) {
        FILE *fpin = fopen(argv[file_idx], "r");
        if (fpin == NULL) {
            fprintf(stderr, "Warning: Failed to open file '%s', skipping\n", argv[file_idx]);
            continue; // 跳过当前文件,继续处理下一个
        }

        // 动态数组初始化:初始容量8行
        int capacity = 8;
        char **lines_arr = malloc(capacity * sizeof(char *));
        if (!lines_arr) {
            fprintf(stderr, "Error: Memory allocation failed\n");
            fclose(fpin);
            exit(EXIT_FAILURE);
        }

        int line_count = 0;
        char *buffer = malloc((cfg.max_line_len + 1) * sizeof(char)); // +1存终止符
        if (!buffer) {
            fprintf(stderr, "Error: Memory allocation failed\n");
            free(lines_arr);
            fclose(fpin);
            exit(EXIT_FAILURE);
        }

        // 逐行读取文件
        while (fgets(buffer, cfg.max_line_len + 1, fpin) != NULL) {
            // 移除换行符
            buffer[strcspn(buffer, "\n")] = '\0';
            // 反转当前行
            reverse_str(buffer);

            // 动态扩容:当行数达到当前容量时,翻倍扩容
            if (line_count >= capacity) {
                capacity *= 2;
                char **temp = realloc(lines_arr, capacity * sizeof(char *));
                if (!temp) {
                    fprintf(stderr, "Error: Memory reallocation failed\n");
                    // 释放已分配的内存
                    for (int i = 0; i < line_count; i++) {
                        free(lines_arr[i]);
                    }
                    free(lines_arr);
                    free(buffer);
                    fclose(fpin);
                    exit(EXIT_FAILURE);
                }
                lines_arr = temp;
            }

            // 为当前行分配内存并复制内容
            lines_arr[line_count] = malloc((strlen(buffer) + 1) * sizeof(char));
            if (!lines_arr[line_count]) {
                fprintf(stderr, "Error: Memory allocation failed\n");
                // 清理已分配资源
                for (int i = 0; i < line_count; i++) {
                    free(lines_arr[i]);
                }
                free(lines_arr);
                free(buffer);
                fclose(fpin);
                exit(EXIT_FAILURE);
            }
            strcpy(lines_arr[line_count], buffer);
            line_count++;
        }

        // 输出处理后的内容:反转行顺序
        if (cfg.type == linenums) {
            for (int i = line_count - 1; i >= 0; i--) {
                printf("%d %s\n", line_count - i, lines_arr[i]);
            }
        } else {
            for (int i = line_count - 1; i >= 0; i--) {
                printf("%s\n", lines_arr[i]);
            }
        }
        printf("\n"); // 文件间分隔

        // 释放当前文件的动态内存
        for (int i = 0; i < line_count; i++) {
            free(lines_arr[i]);
        }
        free(lines_arr);
        free(buffer);
        fclose(fpin);
    }

    return EXIT_SUCCESS;
}

关键修复点说明

  1. 动态数组扩容逻辑
    • 初始容量设为8,当line_count达到当前capacity时,用realloc将容量翻倍
    • 扩容时检查realloc返回值,确保内存分配成功
  2. 多文件处理修复
    • 外层循环变量改为file_idx,避免与内层循环变量冲突
    • 文件打开失败时仅输出警告并跳过,不终止程序
  3. 内存管理优化
    • 每个文件处理完毕后,依次释放每行的内存、指针数组和缓冲区
    • 使用EXIT_SUCCESS/EXIT_FAILURE替代硬编码的0/1,符合标准规范
  4. 参数有效性检查
    • 验证MAX_LINE_LENGTH为正整数,避免非法值导致的问题
  5. 兼容性处理
    • 实现自定义reverse_str函数,替代非标准的strrev,保证跨编译器兼容
  6. 行内存分配优化
    • 根据实际反转后的字符串长度分配内存,而非固定大小,减少内存浪费

内容的提问来源于stack exchange,提问作者Tamás Veszelyi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 06:35:29