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; }
关键修改说明
- 修正了
sscanf的写入目标,按当前索引*count写入对应的结构体元素 - 新增了读取结果判断逻辑,不足3个单词时显式将未匹配的字段置为空字符串,彻底解决残留旧值的问题
- 调整了
count自增的位置,每处理完一行就自增,不受扩容逻辑影响 - 修正了扩容逻辑,先判断是否需要扩容再写入元素,避免数组越界
- 新增了入参校验、文件关闭、内存释放逻辑,修复了内存泄漏和野指针风险
- 移除了未使用的
struct parola2定义和冗余变量
内容的提问来源于stack exchange,提问作者socrate23
相关产品推荐
相关产品推荐

