C语言读取文件每行存入char*数组的代码问题排查
问题原因
1. test[0]最终输出linha10的问题
- 你定义的
singleLine是栈上的一块固定内存地址,每次调用fgets都会覆盖这块内存的内容 - 代码里
test[0] = singleLine只是把test[0]的指针指向了singleLine的内存地址,并没有存储字符串的副本,循环执行到最后时singleLine里存储的是最后一行内容linha10,因此最终访问test[0]得到的是最后一行的值 - 额外补充:
while (!feof(in_file))的写法是错误的,feof标记是在读取操作失败(读到文件末尾之后再读一次)才会被置为真,你的写法会导致最后一行被重复读取一次
2. 无法得到实际元素个数的问题
sizeof是编译期运算符,计算的是数组占用的总字节数,char* test[30]的总大小就是30个指针的长度,和你实际往里面存了多少元素完全无关,因此不可能通过sizeof得到实际存储的元素数
解决方案
- 每次读取一行后,单独为字符串分配堆内存,拷贝字符串内容后再把指针存入数组,避免所有指针都指向同一块栈内存
- 额外定义一个计数变量,每成功存入一个元素就将计数+1,用这个变量记录实际存储的元素个数
- 修正文件读取的循环逻辑,用
fgets的返回值作为循环判断条件
修正后示例代码
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(){ FILE *in_file = fopen("arq.txt", "r"); char singleLine[150]; char* test[30]; int actual_len = 0; // 记录实际存储的元素个数 if (!in_file) { printf("Error! Could not open file\n"); return 0; } // 修正循环判断条件,fgets返回NULL代表读取结束,同时限制不超出数组最大长度 while (fgets(singleLine, 150, in_file) != NULL && actual_len < 30) { // 去掉fgets读取到的末尾换行符(可选,根据需求决定是否保留) singleLine[strcspn(singleLine, "\n")] = '\0'; // 为字符串分配内存并拷贝内容 test[actual_len] = strdup(singleLine); // 若编译环境不支持strdup,替换为下面两行即可: // test[actual_len] = malloc(strlen(singleLine) + 1); // strcpy(test[actual_len], singleLine); actual_len++; } printf("数组总长度: 30\n"); printf("实际存储元素个数: %d\n", actual_len); // 遍历输出所有元素 for (int i = 0; i < actual_len; i++) { printf("test[%d] = %s\n", i, test[i]); } // 用完释放堆内存,避免内存泄漏 for (int i = 0; i < actual_len; i++) { free(test[i]); } fclose(in_file); return 0; }
内容的提问来源于stack exchange,提问作者Nilton Schumacher F
相关产品推荐
相关产品推荐

