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

C语言读取单词存入struct parola数组出现旧值残留如何修复

C语言读取文本残留旧值问题修复方案

问题根因

经过排查,你的代码存在以下几处核心逻辑错误,直接导致了字段残留、计数错误的问题:

  • 写入目标错误:sscanf 始终向动态数组首元素 v[0] 写入数据,没有按索引写入当前待填充的 v[*count] 元素
  • 读取结果未处理:sscanf 会返回成功匹配的字段数量,当一行不足3个单词时,未匹配的字段不会被覆写,就会残留上一个元素的内容
  • 计数逻辑错位:*count 自增逻辑被误写在扩容判断的分支内,只有触发数组扩容时才会更新索引,正常写入时索引一直停留在0
  • 错误处理冗余:malloc 申请失败时v为NULL,无需调用free,直接返回即可,同时代码中存在大量未使用的变量和结构体定义

修复后完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX (10)

struct parola{
   char parola1[MAX+1];
   char parola2[MAX+1];
   char parola3[MAX+1];
};

struct parola *leggi_file(FILE *fp, int *count){
   int dim = 16;
   struct parola *v;
   int conv = 0;
   char buf[1024];

   // 初始化动态数组
   if(!(v = malloc(dim * sizeof(*v)))){
       puts("non va");
       return NULL;
   }
   *count = 0;

   while(fgets(buf, sizeof(buf), fp) != NULL){
       // 先判断是否需要扩容,避免越界
       if(*count >= dim){
           dim *= 2;
           struct parola *tmp = realloc(v, sizeof(*v)*dim);
           if(!tmp){
               free(v);
               return NULL;
           }
           v = tmp;
       }

       // 写入当前索引对应的结构体元素
       conv = sscanf(buf, "%s %s %s", 
                    v[*count].parola1, 
                    v[*count].parola2, 
                    v[*count].parola3);
       
       // 根据读取成功的字段数,将未读取的字段置为空
       switch(conv) {
           case 0: 
               v[*count].parola1[0] = '\0';
               //  fall through
           case 1:
               v[*count].parola2[0] = '\0';
               // fall through
           case 2:
               v[*count].parola3[0] = '\0';
               break;
           default: break;
       }

       // 计数自增,和扩容逻辑 decouple
       (*count)++;
   }
   return v;
}

void visual(struct parola *v, int count){
   int i;
   for(i=0; i<count; i++){
       printf("%s %s %s\n", v[i].parola1,v[i].parola2,v[i].parola3);
   }
}

int main(int argc, char *argv[]){
   if(argc < 2) {
       printf("用法:%s <文件名>\n", argv[0]);
       return 1;
   }

   int count = 0;
   struct parola *v;
   
   FILE *fp = fopen(argv[1], "r");
   if (fp == NULL){
       perror("打开文件失败");
       return 1;
   }
   
   v = leggi_file(fp, &count);
   fclose(fp); // 读取完成关闭文件

   if(v == NULL){
       return 1;
   }
   
   visual(v, count);
   free(v); // 释放动态数组内存
   return 0;
}

关键修改说明

  1. 修正了sscanf的写入目标,按当前索引*count写入对应的结构体元素
  2. 新增了读取结果判断逻辑,不足3个单词时显式将未匹配的字段置为空字符串,彻底解决残留旧值的问题
  3. 调整了count自增的位置,每处理完一行就自增,不受扩容逻辑影响
  4. 修正了扩容逻辑,先判断是否需要扩容再写入元素,避免数组越界
  5. 新增了入参校验、文件关闭、内存释放逻辑,修复了内存泄漏和野指针风险
  6. 移除了未使用的struct parola2定义和冗余变量

内容的提问来源于stack exchange,提问作者socrate23

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:36:05