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

小型词典哈希开发续篇:哈希正常但显示桶时出现段错误

哈希词典显示时的段错误解决方法

先看你代码里最直接导致段错误的问题——链表遍历的循环条件写错了!

while(!NULL) {
    printf("%s", ptr->name);
    ptr = ptr->next;
}

这里的!NULL等价于!0,也就是布尔值true,这会让循环无限执行下去。当ptr走到链表末尾变成NULL后,你还继续访问ptr->name,这就触发了空指针访问的段错误。

第一步:修复循环条件

把循环改成检查ptr是否不为空:

node* ptr = first[6];
while (ptr != NULL) {  // 这里改对
    printf("%s", ptr->name);
    ptr = ptr->next;
}

第二步:排查其他潜在问题(避免后续踩坑)

除了循环条件,你的代码还有几个隐患可能导致奇怪的问题:

  • fgets读取的字符串带换行符:fgets会把换行符\n也读进数组里,插入到链表后,显示的时候会多换行,甚至影响后续的哈希匹配。可以在插入前去掉换行符:

    char* c = fgets(h,sizeof(h),fd);
    if (c == NULL) {
        // ... 错误处理
    }
    // 去掉换行符
    h[strcspn(h, "\n")] = '\0';
    int hashedValue = hash(h);  // 这里用h而不是c,因为c就是h的指针
    insert(hashedValue, h);
    
  • 链表节点的字符串复制问题:如果你的insert函数直接把传入的字符串指针(也就是h的地址)存到node->name里,那所有链表节点都会指向同一个栈数组h,循环结束后h的内容会被覆盖,导致链表中所有节点的name都是最后一个单词。正确的做法是在insert里为字符串分配内存:

    // 假设你的insert函数大概是这样,修正字符串复制部分
    void insert(int hash_val, char* word) {
        node* new_node = malloc(sizeof(node));
        if (new_node == NULL) {
            // 内存分配失败处理
            return;
        }
        // 复制字符串,而不是直接赋值指针
        new_node->name = strdup(word);  // 或者用malloc(strlen(word)+1) + strcpy
        new_node->next = first[hash_val];
        first[hash_val] = new_node;
    }
    
  • first数组的初始化:如果first是局部数组,一定要确保初始化为NULL,否则里面的野指针会导致访问错误。如果是全局数组的话,默认会被初始化为NULL,这没问题。

修正后的完整main函数示例

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <string.h>
#include "hash.c"
#include "dictionary.h"
#define LENGTH 45
#define DICTIONARY "dictionaries/small"

int main(void) {
    char* dictionary = DICTIONARY;
    FILE* fd = fopen(dictionary, "r");
    if (fd == NULL) {  // 别忘了检查文件是否打开成功!
        printf("Failed to open dictionary\n");
        return 1;
    }
    char h[LENGTH];
    while(true) {
        char* c = fgets(h,sizeof(h),fd);
        if (c == NULL) {
            if ( feof (fd) != 0) {
                printf ("\nEOF\n");
                break;
            } else {
                printf ("\nERROR\n");
                break;
            }
        }
        // 处理换行符
        h[strcspn(h, "\n")] = '\0';
        int hashedValue = hash(h);
        insert(hashedValue, h);
    }
    // 遍历链表的正确写法
    node* ptr = first[6];
    while (ptr != NULL) {
        printf("%s\n", ptr->name);
        ptr = ptr->next;
    }
    fclose (fd);
    return 0;
}

先把循环条件改过来,应该就能解决当前的段错误了,再把上面提到的其他隐患也处理掉,你的哈希词典功能就会更稳定。

内容的提问来源于stack exchange,提问作者user13279908

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 17:47:57