You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,请问问题原因是什么,该如何修复?


问题原因

  1. 局部栈变量复用问题:char word[20];是内层循环的局部栈变量,每次进入循环都会复用同一块栈内存。你把st->word = word;只是将这块栈内存的地址赋值给结构体指针,所有结构体最终都指向同一块内存,最后一次写入的Philips会覆盖之前的内容。
  2. 字符串无终止符:读取字符时未给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 04:40:29