C语言读取TXT文件单词存入结构体及后续操作实现问题
C语言读取文本单词到结构体修复方案
原代码核心问题
- 结构体赋值位置错误:
sscanf始终写入第一个结构体元素,没有按行写入w[*count]对应的位置 - 计数变量
count递增逻辑错误:仅在数组扩容时才执行count++,正常读取行时不会移动下标 - 内存分配失败后缺少返回逻辑:
calloc分配失败时未直接返回NULL,会后续触发空指针访问 - 多余未使用变量
i,无实际作用 - 缺少文件关闭、内存释放逻辑,存在资源泄漏
修复后完整代码
#include <string.h> #include <stdio.h> #include <stdlib.h> #define MAX (10) // 单单词最大字母数小于10 struct word{ char word1[MAX+1]; // 存储每行第一个单词,缺省为空 char word2[MAX+1]; // 存储每行第二个单词,缺省为空 }; struct word *file_read(FILE *fp, int *count){ int dim = 2; // 结构体数组初始容量 char buf[1024]; // 行读取缓冲区 struct word *w; int conv = 0; // sscanf匹配成功的字段数 // 初始化结构体数组,calloc默认0初始化,刚好满足缺省字段留空的需求 if(!(w = calloc(dim , sizeof(*w)))){ return NULL; } *count = 0; // 初始化计数为0 while(fgets(buf, sizeof(buf), fp) != NULL){ // 先检查是否需要扩容,避免下标越界 if(*count >= dim){ dim *= 2; struct word* temp = realloc(w, sizeof(*w)*dim); if(temp == NULL){ free(w); return NULL; } w = temp; // 新扩容的空间清零,保证缺省字段为空 memset(w + *count, 0, (dim - *count) * sizeof(*w)); } // 向当前下标对应的结构体写入数据 conv = sscanf(buf, "%s %s", w[*count].word1, w[*count].word2); // 测试打印,可删除 if(conv >= 1){ printf("\n第%d行:%s ", *count + 1, w[*count].word1); } if(conv == 2){ printf("%s", w[*count].word2); } // 每读完一行,计数+1 (*count)++; } return w; } // 示例:冒泡排序,按word1字典序排序 void bubble_sort(struct word *w, int count){ for(int i = 0; i < count - 1; i++){ for(int j = 0; j < count - i - 1; j++){ if(strcmp(w[j].word1, w[j+1].word1) > 0){ struct word temp = w[j]; w[j] = w[j+1]; w[j+1] = temp; } } } } // 示例:修改指定行的单词 int modify_word(struct word *w, int count, int line, int word_idx, char *new_val){ if(line < 0 || line >= count || word_idx < 1 || word_idx > 2){ return -1; // 参数非法 } if(word_idx == 1){ strncpy(w[line].word1, new_val, MAX); w[line].word1[MAX] = '\0'; // 防止溢出 }else{ strncpy(w[line].word2, new_val, MAX); w[line].word2[MAX] = '\0'; } return 0; } int main(int argc, char *argv[]){ if(argc < 2){ printf("请传入文件路径参数\n"); return 1; } FILE *fp = fopen(argv[1], "r"); if(fp == NULL){ perror("文件打开失败"); return 1; } struct word *w; int count = 0; w = file_read(fp, &count); fclose(fp); // 读取完成关闭文件 if(w == NULL){ printf("文件读取失败\n"); return 1; } // 以下为功能测试示例 printf("\n\n读取完成,共%d行数据\n", count); // 测试冒泡排序 bubble_sort(w, count); printf("\n排序后结果:\n"); for(int i = 0; i < count; i++){ printf("第%d行:%s %s\n", i+1, w[i].word1, w[i].word2); } // 测试修改第2行第1个单词为new_word3 modify_word(w, count, 1, 1, "new_word3"); printf("\n修改后结果:\n"); for(int i = 0; i < count; i++){ printf("第%d行:%s %s\n", i+1, w[i].word1, w[i].word2); } // 释放内存 free(w); return 0; }
关键修改说明
- 赋值逻辑修正:
sscanf直接写入当前下标对应的结构体w[*count],保证每行数据对应一个结构体元素 - 计数逻辑修正:每成功读取一行就执行
(*count)++,扩容逻辑提前判断,避免下标越界 - 初始化逻辑优化:
calloc默认将所有结构体字段初始化为0,缺省的单词字段自动为空字符串,符合需求 - 补充了扩容后内存清零逻辑,保证新分配的结构体字段默认是空
- 新增了冒泡排序、单词修改的示例实现,可直接扩展其他操作
- 补充了参数校验、资源释放逻辑,避免内存泄漏和非法访问
内容的提问来源于stack exchange,提问作者socrate23
相关产品推荐
相关产品推荐

