C语言中读取文本文件内容并存入数组的实现指导咨询
文本单词存储到数组的C语言实现方案
原有代码的核心问题
- 缺少必要头文件:
fopen/fgets/printf等IO函数属于stdio.h,仅引入stdlib.h无法正常编译 - 没有独立的存储容器:代码中仅申请了一块固定大小的读缓冲区
word,每次循环读入的新内容会直接覆盖上一次的结果,没有单独空间留存每个单词 - 典型的指针误用误区:不少参考资料会直接把公共读缓冲区的地址存进数组,本质是数组里所有元素都指向同一块内存,每次读入新内容就会覆盖所有之前的结果,最终数组里全是最后读到的那个单词,这也是照着资料写却得不到正确结果的核心原因
fgets读入的内容会携带行尾换行符\n,需要手动清理后才是纯单词内容
具体实现逻辑
- 用二级字符指针做存储容器:即
char **word_storage,本质是一个指针数组,每个元素单独指向一块存放完整单词的堆内存,不同单词的内存互相独立,不会出现覆盖问题 - 动态适配容量:初始化时先分配一个基础容量,当存储的单词数超过当前容量时,自动扩容数组大小,不需要提前硬编码文件里的单词总数
- 逐行读取后做内容清洗:每次读到一行内容,先找到行尾的换行符替换成字符串结束符,得到纯单词文本
- 为每个单词独立分配内存:按单词的实际长度申请对应的堆内存,把清洗后的单词拷贝进去,再把这块内存的地址存到存储数组里
- 验证结果+内存释放:读取完成后遍历数组打印所有存好的单词,确认存储逻辑正确,最后逐块释放所有申请的堆内存,避免内存泄漏
可直接运行的参考代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { // 打开目标文本文件 FILE *fp = fopen("/classes/cs3304/cs330432/Programs/StringerTest/people.txt", "r"); // 单条内容读取缓冲区,大小足够容纳最长的单词 const size_t read_buf_size = 1000; char *read_buf = malloc(sizeof(char) * read_buf_size); // 初始化单词存储数组,先预分配可容纳16个单词的基础容量 size_t storage_capacity = 16; size_t word_count = 0; // 记录当前已经存储的单词总数 char **word_storage = malloc(sizeof(char*) * storage_capacity); // 文件打开失败判断 if (fp == NULL) { printf("file not found"); free(read_buf); free(word_storage); return 0; } // 逐行读取文件内容 while(fgets(read_buf, read_buf_size, fp) != NULL) { // 移除行尾的换行符,替换为字符串结束标记 char *newline_pos = strchr(read_buf, '\n'); if (newline_pos != NULL) { *newline_pos = '\0'; } // 存储容量不足时,自动扩容为原来的2倍 if (word_count >= storage_capacity) { storage_capacity *= 2; word_storage = realloc(word_storage, sizeof(char*) * storage_capacity); } // 为当前单词申请独立内存,长度匹配实际单词长度+1(预留字符串结束符位置) size_t word_len = strlen(read_buf); word_storage[word_count] = malloc(sizeof(char) * (word_len + 1)); // 把单词拷贝到独立的内存块中 strcpy(word_storage[word_count], read_buf); word_count++; } // 读取完成后关闭文件 fclose(fp); // 公共读缓冲区已经用完,直接释放 free(read_buf); // 遍历数组打印存储的单词,验证存储效果 printf("=== 已存储到数组的单词列表 ===\n"); for (size_t i = 0; i < word_count; i++) { printf("第%zu个单词:%s\n", i + 1, word_storage[i]); } // 逐块释放每个单词占用的内存 for (size_t i = 0; i < word_count; i++) { free(word_storage[i]); } // 释放存储数组本身占用的内存 free(word_storage); return 0; }
关键注意事项
- 绝对不要直接把公共读缓冲区
read_buf的地址赋值给word_storage的元素,否则所有数组元素会指向同一块内存,最终全部存储最后一次读到的单词 - 为单词申请内存时,一定要在实际单词长度基础上多留1个字节的位置放字符串结束符
\0,否则后续字符串操作会出现越界问题 - 所有通过
malloc/realloc申请的内存,最后都要对应调用free释放,否则会造成内存泄漏
内容的提问来源于stack exchange,提问作者Marshall McCurdy
相关产品推荐
相关产品推荐

