C语言哈希表统计CSV文件姓名频率insert函数段错误问题求助
问题原因与修复方案
1. 触发段错误的直接原因
报错行int primaryIndex = hash1(hashArray[index]->name) % maxSize;的本质是对空指针/野指针解引用:
- 你的哈希表
hashArray是全局的struct individual *数组,全局指针默认初始化为NULL - 你注释了
initArray函数调用,就算你没注释,initArray本身也是错误实现:没有给每个hashArray[i]分配内存就直接访问hashArray[i]->frequency和hashArray[i]->name,本身就会触发段错误 - 你在insert函数里没有做非空判断就直接访问
hashArray[index]->name,此时hashArray[index]大概率是NULL,对空指针取成员直接触发段错误。 - 你删除这行之后不会提前访问空指针的成员,所以不会触发段错误,但此时你的频率统计逻辑完全错误,无法实现需求。
2. 现有代码的其他逻辑问题
你的实现和哈希表插入、频率统计的需求不匹配,还存在多处隐含风险:
- 你
malloc了person结构体之后,没有把传入的p的姓名、初始频率赋值给person,最终存入哈希表的都是垃圾数据 - 频率统计逻辑错误:就算哈希值相同也可能是哈希冲突,必须对比姓名字符串是否完全相等才能累加频率,不能只对比哈希索引
next_field函数没有判断读入长度是否超过缓冲区最大限制,会触发缓冲区溢出feof用法错误:feof是在读取操作失败之后才会置位,你现有的循环会多读一次无效的空行- 线性探测逻辑错误:你要拿的是当前插入元素的初始哈希索引,不是哈希表现有元素的哈希索引,原有逻辑完全不符合需求。
3. 修复代码
修正哈希表初始化逻辑
不要提前给每个哈希表位置分配内存,只需要把所有指针初始化为NULL即可:
void initArray(){ for (int i = 0; i < maxSize; i++){ hashArray[i] = NULL; } }
之后在main函数中取消initArray();的注释。
修正insert函数逻辑
void insert(struct individual *p){ int index = hash1(p->name) % maxSize; int original_index = index; // 保存当前插入元素的初始哈希索引 /* 线性探测找匹配的姓名或者空位置 */ while(hashArray[index] != NULL){ // 必须字符串对比确认是同一个姓氏才累加频率 if(strcmp(hashArray[index]->name, p->name) == 0){ hashArray[index]->frequency++; return; // 已经统计过,直接返回不需要新增节点 } ++index; index %= maxSize; // 哈希表满直接返回避免死循环 if(index == original_index){ printf("哈希表已满,无法插入 %s\n", p->name); return; } } // 找到空位置,新建节点存入 struct individual *person = malloc(sizeof(struct individual)); strcpy(person->name, p->name); person->frequency = 1; // 第一次出现频率为1 hashArray[index] = person; };
修正next_field避免缓冲区溢出
int next_field(FILE *f, char *buffer, int max){ int i = 0, end = 0; for(;;){ buffer[i] = fgetc(f); if(buffer[i] == '\n' || feof(f)){ end = 1; break; } i++; // 超过缓冲区最大长度提前截断 if(i >= max - 1){ break; } } buffer[i] = 0; return end; };
修正main函数读取逻辑避免多读空行
while(!feof(list)){ if(next_field(list, in.name, 50) == 1 && strlen(in.name) > 0){ insert(&in); display(&in); } }
内容的提问来源于stack exchange,提问作者JsM
相关产品推荐
相关产品推荐

