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

