while循环中使用scanf导致哈希表原有值被覆盖的问题排查
问题分析与修复
你的代码出现“新输入值替换所有原有值”的问题,核心原因是哈希表中存储的都是同一个指针,且该指针指向的内存被重复覆盖,同时哈希函数也存在逻辑错误,具体问题和修复如下:
关键错误点
1. 未正确为输入字符串分配内存,scanf使用错误
add函数中char* input;仅声明了指针,未指向任何有效内存空间。你用scanf("%s", (char*)&input);直接将输入内容写入指针变量自身的地址,这会破坏指针的存储,且每次调用add时,input作为局部变量,其内存地址固定。哈希表中存储的都是这个固定地址的指针,后续输入会覆盖该地址的内容,导致所有指向该地址的哈希表项都显示新值。
2. 哈希函数计算错误
hash函数中sizeof(str)获取的是指针的字节长度(如32位系统是4,64位是8),而非输入字符串的实际长度。这会导致只计算字符串前几个字符的ASCII值,哈希结果不准确,出现多个输入映射到同一哈希桶的情况。
3. 未复制输入字符串到哈希表
即使修正了内存分配,直接将局部变量的指针存入哈希表也会导致函数结束后指针失效,必须复制输入的字符串到堆内存中,再将堆内存的指针存入哈希表。
修复后的代码
#include <stdio.h> #include <string.h> #include <stdlib.h> #define T_LEN 10 // 初始化哈希表,将每个元素置为NULL void init(char* table[]) { for (int i = 0; i < T_LEN; i++) { table[i] = NULL; } } // 修正后的哈希函数:使用strlen获取字符串长度 int hash(char* str) { int result = 0; for (int i = 0; i < strlen(str); i++) { result += str[i]; } return result % T_LEN; } // 修正后的添加函数:分配内存存储输入字符串 void add(char* table[]) { char input[100]; // 用栈数组临时存储输入,避免内存泄漏风险 printf("> "); scanf("%99s", input); // 限制输入长度,防止缓冲区溢出 int index = hash(input); // 先释放原有内存(如果存在),避免内存泄漏 if (table[index] != NULL) { free(table[index]); } // 复制字符串到堆内存,存入哈希表 table[index] = strdup(input); if (table[index] == NULL) { printf("内存分配失败\n"); exit(1); } } // 打印哈希表的实现(补充原代码缺失部分) void print_table(char* table[]) { for (int i = 0; i < T_LEN; i++) { printf("%d\t%s\n", i+1, table[i] != NULL ? table[i] : "-------"); } } int main() { char* hash_table[T_LEN]; init(hash_table); while (1) { add(hash_table); print_table(hash_table); } // 注意:实际使用中需要在退出前释放哈希表的内存,避免泄漏 return 0; }
修复说明
- 使用栈数组
input临时存储输入,再通过strdup将字符串复制到堆内存,确保哈希表中存储的指针指向独立的、持久的内存空间。 - 哈希函数改用
strlen遍历整个字符串,计算准确的哈希值。 - 初始化哈希表时将元素置为
NULL,便于判断桶是否为空,且释放内存时更安全。 - 添加了输入长度限制,防止缓冲区溢出。
内容的提问来源于stack exchange,提问作者at_Root
相关产品推荐
相关产品推荐

