C语言哈希表存储CSV结构体数据指针问题导致无输出求解
开散列哈希表实现问题修复
核心错误点
- 插入后立即释放节点:你将新创建的链表节点赋值给哈希表对应下标后,立刻调用
free_linkedlist(d)释放了节点,导致哈希表中存储的是野指针,数据自然无法留存。 - 未处理哈希冲突:你没有调用已实现的
linkedlist_insert函数处理冲突,而是直接将新节点覆盖到哈希表对应下标,相同哈希值的旧数据会直接丢失。 - 内存释放逻辑错误:
free_linkedlist函数存在两个问题:一是循环中没有移动链表指针,会导致无限循环;二是尝试释放栈上的Pokemon结构体(temp->item指向栈数组pArray的元素,不是堆内存,不能手动释放)。 - 哈希表打印逻辑不完整:现有
print_table函数仅打印链表的头节点,无法展示冲突后插入的后续节点;且你在main函数中注释了print_table调用,自然看不到哈希表的预期输出。 - 文件名配置问题:
fopen打开的文件名为.csv,需确保你的CSV文件路径和名称匹配,否则程序会直接因打开文件失败退出。
修复后的核心代码修改
1. 修正内存释放函数
void free_linkedlist(LinkedList* list) { LinkedList* temp; while (list) { temp = list; list = list->next; // item指向栈数组,不需要释放 free(temp); } }
2. 修正哈希表插入逻辑(main函数循环内)
while(!feof(f) && nbPokemons < MAX_NB_POKEMON) { // 新增数组越界判断 fetch_pokemon( f, &pArray[nbPokemons] ); a=hash_function(pArray[nbPokemons].surname); // 调用链表插入函数处理冲突,不要手动分配节点、不要立即释放 hashTable[a] = linkedlist_insert(hashTable[a], &pArray[nbPokemons]); printf("%d\n",a); print_pokemon( &pArray[nbPokemons] ); nbPokemons++; } // 打开哈希表打印调用 print_table(); // 程序退出前统一释放哈希表内存 for(int i=0; i<ARRAY_SIZE; i++) { free_linkedlist(hashTable[i]); }
3. 修正哈希表打印函数
void print_table(void){ printf("Start\n"); int i; for(i=0;i<ARRAY_SIZE;i++){ if(hashTable[i] == NULL){ printf("\t%i\t---\n",i); }else{ printf("\t%i\t",i); LinkedList* curr = hashTable[i]; while(curr) { printf("%d\t%s\t%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\n", curr->item->id, curr->item->depid, curr->item->surname, curr->item->forename, curr->item->age, curr->item->type, curr->item->gender, curr->item->nationality, curr->item->rel, curr->item->occ); curr = curr->next; } } } printf("End\n"); }
额外优化建议
- 现有哈希函数为简单加法哈希,冲突率较高,可以优化为
hash = (hash * 31 + *s) % ARRAY_SIZE降低冲突概率。 - 可以在
fetch_pokemon函数中添加字段读取合法性判断,避免CSV格式错误导致程序异常。
内容的提问来源于stack exchange,提问作者Kartik Mann
相关产品推荐
相关产品推荐

