行数、每行单词数未知的文件输入如何动态分配3D char数组
动态存储多行多单词输入的实现方案
以下提供两种可直接落地的实现,完全兼容你期望的arr[行下标][单词下标]访问形式。
方案1:贴合原三维数组思路的动态分配实现
核心逻辑
你最初的三维数组思路完全可行,只需要把静态分配改成堆上的动态逐级分配即可,需要额外配套两个变量记录行数、每行的单词数,避免越界访问:
- 用三级指针
char*** arr对应三维字符数组 - 用
int row_cnt记录总行数 - 用
int* word_cnt_per_row记录每行的单词数量
核心代码示例
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_WORD_LEN 30 // 单词最大长度,和你预设的一致 int main() { char*** arr = NULL; int* word_cnt_per_row = NULL; int row_cnt = 0; char line_buf[1024]; // 单行最大长度,可按需调整 FILE* fp = fopen("input.txt", "r"); if (!fp) { perror("文件打开失败"); return 1; } // 逐行读取文件 while (fgets(line_buf, sizeof(line_buf), fp)) { // 扩容行维度的数组 arr = realloc(arr, (row_cnt + 1) * sizeof(char**)); word_cnt_per_row = realloc(word_cnt_per_row, (row_cnt + 1) * sizeof(int)); // 统计当前行的单词数 int word_cnt = 0; char* tmp = strdup(line_buf); char* p = strtok(tmp, " \t\n\r"); while (p) { word_cnt++; p = strtok(NULL, " \t\n\r"); } free(tmp); word_cnt_per_row[row_cnt] = word_cnt; // 分配当前行的单词指针数组 arr[row_cnt] = malloc(word_cnt * sizeof(char*)); // 逐个分配单词空间并写入内容 p = strtok(line_buf, " \t\n\r"); for (int i = 0; i < word_cnt; i++) { arr[row_cnt][i] = malloc(MAX_WORD_LEN * sizeof(char)); strncpy(arr[row_cnt][i], p, MAX_WORD_LEN - 1); arr[row_cnt][i][MAX_WORD_LEN - 1] = '\0'; // 强制字符串结束,避免溢出 p = strtok(NULL, " \t\n\r"); } row_cnt++; } fclose(fp); // 访问示例:和你预想的静态数组用法完全一致 // printf("%s", arr[1][2]); 直接取第2行第3个单词 // 内存释放逻辑,避免泄漏 for (int i = 0; i < row_cnt; i++) { for (int j = 0; j < word_cnt_per_row[i]; j++) { free(arr[i][j]); } free(arr[i]); } free(arr); free(word_cnt_per_row); return 0; }
方案2:优化内存效率的改进方案
优化点
因为你预设了单词最大长度固定为30,可以把每行所有单词的存储空间合并为一块连续内存,减少malloc次数、降低内存碎片,访问速度也更快:
仅需要修改分配和释放的部分逻辑:
// 分配单词部分替换为: arr[row_cnt] = malloc(word_cnt * sizeof(char*)); char* whole_line_buf = malloc(word_cnt * MAX_WORD_LEN * sizeof(char)); // 一次性分配整行单词空间 p = strtok(line_buf, " \t\n\r"); for (int i = 0; i < word_cnt; i++) { arr[row_cnt][i] = whole_line_buf + i * MAX_WORD_LEN; // 每个单词指针指向对应偏移位置 strncpy(arr[row_cnt][i], p, MAX_WORD_LEN - 1); arr[row_cnt][i][MAX_WORD_LEN - 1] = '\0'; p = strtok(NULL, " \t\n\r"); } // 释放部分替换为: for (int i = 0; i < row_cnt; i++) { free(arr[i][0]); // 释放整行的连续单词缓冲区 free(arr[i]); } free(arr); free(word_cnt_per_row);
内容的提问来源于stack exchange,提问作者Tomba
相关产品推荐
相关产品推荐

