You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 05:54:04