C语言结构体数组存文件单词时均显示最后一个值的问题与解决
问题:读取文件单词存入结构体数组后,所有元素显示最后一个单词
使用VSCode作为IDE,mingw64-gcc-g++作为编译器,从文件中读取单词并存入结构体数组,但所有结构体元素的word字段都显示文件最后一个单词。
文件内容:
{Sam} {Patrick} {Philips}
现有代码:
struct Sentence { char *word; }; struct Sentence *words[20]; void readFile(const char *path, char *fileName) { int wordpointer = 0; int len = strlen(fileName); FILE *fp; if ((fp = fopen((path), "r")) != NULL) { char ch = fgetc(fp); while (ch != EOF) { if (ch == '{') { int counter = 0; while (ch != EOF) { char word[20]; ch = fgetc(fp); if (ch == '}') { //printf("%s\n",word); struct Sentence *st = malloc(sizeof(struct Sentence)); st->word = word; words[wordpointer] = st; wordpointer++; break; } word[counter++] = ch; } } ch = fgetc(fp); } fclose(fp); } for (int i = 0; i < wordpointer; i++) printf("%s\n", words[i]->word); }
注释中的printf能正确输出读取的单词,但遍历结构体数组时输出全为Philips,请问问题原因是什么,该如何修复?
问题原因
- 局部栈变量复用问题:
char word[20];是内层循环的局部栈变量,每次进入循环都会复用同一块栈内存。你把st->word = word;只是将这块栈内存的地址赋值给结构体指针,所有结构体最终都指向同一块内存,最后一次写入的Philips会覆盖之前的内容。 - 字符串无终止符:读取字符时未给
word数组添加'\0',注释里的printf能输出只是栈内存恰好有符合终止条件的字节,属于未定义行为。
修复方法
为每个单词分配独立的堆内存,避免共用栈内存,同时补全字符串终止符:
修复后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct Sentence { char *word; }; struct Sentence *words[20]; void readFile(const char *path, char *fileName) { int wordpointer = 0; FILE *fp; if ((fp = fopen(path, "r")) != NULL) { char ch = fgetc(fp); while (ch != EOF) { if (ch == '{') { int counter = 0; char word[20]; while (ch != EOF) { ch = fgetc(fp); if (ch == '}') { // 添加字符串终止符 word[counter] = '\0'; // 为单词分配独立堆内存并复制内容 struct Sentence *st = malloc(sizeof(struct Sentence)); st->word = malloc(strlen(word) + 1); // +1 存储终止符 strcpy(st->word, word); words[wordpointer] = st; wordpointer++; break; } // 防止数组越界 if (counter < 19) { word[counter++] = ch; } } } ch = fgetc(fp); } fclose(fp); } for (int i = 0; i < wordpointer; i++) { printf("%s\n", words[i]->word); // 释放内存避免泄漏 free(words[i]->word); free(words[i]); } }
关键修改点
- 为每个
st->word分配堆内存,用strcpy复制单词内容,而非直接赋值栈内存地址。 - 读取完单词后添加
word[counter] = '\0';,保证是合法C字符串。 - 添加数组越界检查,防止
word数组溢出。 - 补充内存释放代码,避免内存泄漏。
内容的提问来源于stack exchange,提问作者kernel
相关产品推荐
相关产品推荐

