C 哈希表-分段错误

C 哈希表-分段错误,c,hashtable,C,Hashtable,不知道为什么我会在这里出现分割错误。我正在尝试创建一个哈希表,它会有冲突,并且数据应该是字符串。所以我使用了一个字符数组作为数据。 最后需要检测碰撞 #define SIZE 20 struct DataItem { char data[50]; int key; }; struct DataItem* hashArray[SIZE]; struct DataItem* dummyItem; struct DataItem* item; int hashCode(in

不知道为什么我会在这里出现分割错误。我正在尝试创建一个哈希表,它会有冲突,并且数据应该是字符串。所以我使用了一个字符数组作为数据。 最后需要检测碰撞

#define SIZE 20    
struct DataItem
{
    char data[50];
    int key;
};

struct DataItem* hashArray[SIZE];
struct DataItem* dummyItem;
struct DataItem* item;

int hashCode(int key)
{
    return key % SIZE;
}
void insert(int key, char data[50])
{

    struct DataItem *item = (struct DataItem*) malloc(sizeof(struct DataItem));
    strcpy(item->data, data);
    item->key = key;

//get the hash 
    int hashIndex = hashCode(key);

//move in array until an empty or deleted cell
    while (hashArray[hashIndex] != NULL && hashArray[hashIndex]->key != -1)
    {
        //go to next cell
        ++hashIndex;

        //wrap around the table
        hashIndex %= SIZE;
    }

    hashArray[hashIndex] = item;
}

struct DataItem* delete(struct DataItem* item)
{
    int key = item->key;

    //get the hash 
    int hashIndex = hashCode(key);

    //move in array until an empty
    while (hashArray[hashIndex] != NULL)
    {

        if (hashArray[hashIndex]->key == key)
        {
            struct DataItem* temp = hashArray[hashIndex];

            //assign a dummy item at deleted position
            hashArray[hashIndex] = dummyItem;
            return temp;
        }

        //go to next cell
        ++hashIndex;

        //wrap around the table
        hashIndex %= SIZE;
    }

    return NULL;
}

int detect_collisions()
{
    int i = 0;
    int collision = 0;
    for (i = 0; i < SIZE; i++)
    {
        if (hashArray[i] != NULL)
        {
            if (hashArray[i]->key == hashArray[i + 1]->key)
                ;
            collision++;
        }

    }
    return collision;
}

void display()
{
    int i = 0;

    for (i = 0; i < SIZE; i++)
    {
        if (hashArray[i] != NULL)
        {
            printf("Phli dafa: %d\n", i);
            printf(" (%d,%s)", hashArray[i]->key, hashArray[i]->data);
        }
        else
            printf(" ~~ ");
    }

    printf("\n");
}
int main()
{
    dummyItem = (struct DataItem*) malloc(sizeof(struct DataItem));
    strcpy(dummyItem->data, NULL);
    dummyItem->key = -1;

    insert(1, "check");
    display();
    delete(item);
}

您在这里遇到了一个问题:

strcpy(dummyItem->data,NULL);
as strcpy将取消对空指针的引用

要输入空字符串,请使用:

strcpy(dummyItem->data, "");
你的第二个问题是:

delete(item);
此时项为空。因此,这里:

struct DataItem* delete(struct DataItem* item)
{
    int key = item->key;
              ^^^^^^
取消对空指针的引用

也许您的删除功能应该是:

struct DataItem* delete(int key)
{
第三个问题是这里实际上有三个问题:

for (i = 0; i < SIZE; i++)
{
    if (hashArray[i] != NULL)
    {
        if (hashArray[i]->key == hashArray[i + 1]->key)
                                 ^^^^^^^^^^^^^^^^
                                 a) May be NULL
                                 b) Out of range when i == size-1
            ;
           ^^^
           c) Delete this
        collision++;
    }

}
我猜你想要:

for (i = 0; i < SIZE-1; i++)        // Notice
{
    if (hashArray[i] != NULL && hashArray[i + 1] != NULL)   // Notice
    {
        if (hashArray[i]->key == hashArray[i + 1]->key)
        {
            collision++;
        }
    }
}

您在这里遇到了一个问题:

strcpy(dummyItem->data,NULL);
as strcpy将取消对空指针的引用

要输入空字符串,请使用:

strcpy(dummyItem->data, "");
你的第二个问题是:

delete(item);
此时项为空。因此,这里:

struct DataItem* delete(struct DataItem* item)
{
    int key = item->key;
              ^^^^^^
取消对空指针的引用

也许您的删除功能应该是:

struct DataItem* delete(int key)
{
第三个问题是这里实际上有三个问题:

for (i = 0; i < SIZE; i++)
{
    if (hashArray[i] != NULL)
    {
        if (hashArray[i]->key == hashArray[i + 1]->key)
                                 ^^^^^^^^^^^^^^^^
                                 a) May be NULL
                                 b) Out of range when i == size-1
            ;
           ^^^
           c) Delete this
        collision++;
    }

}
我猜你想要:

for (i = 0; i < SIZE-1; i++)        // Notice
{
    if (hashArray[i] != NULL && hashArray[i + 1] != NULL)   // Notice
    {
        if (hashArray[i]->key == hashArray[i + 1]->key)
        {
            collision++;
        }
    }
}
问题是

strcpy(dummyItem->data, NULL);
它将尝试复制由NULL指向的字符串,该字符串不指向字符串。。到您的阵列。所以它调用

我想你想要的是

memset(dummyItem->data, 0x00, sizeof(dummyItem->data));

还要注意,您必须始终检查malloc返回值:它可能无法返回NULL

你也有一个;刚过

if (hashArray[i]->key == hashArray[i + 1]->key)
移除它

我所能看到的最后一件事

delete(item);
是UB,因为项未初始化,因为insert函数中的代码使用了局部变量,可能需要更改

struct DataItem *item = (struct DataItem*) malloc(sizeof(struct DataItem));

编辑1

您还可以使用访问超出范围的数组

if (hashArray[i]->key == hashArray[i + 1]->key)
当i=SIZE-1时,哈希数组[i+1]超出范围 此外,hashArray[i+1]可以为空或未初始化。

问题在于

strcpy(dummyItem->data, NULL);
它将尝试复制由NULL指向的字符串,该字符串不指向字符串。。到您的阵列。所以它调用

我想你想要的是

memset(dummyItem->data, 0x00, sizeof(dummyItem->data));

还要注意,您必须始终检查malloc返回值:它可能无法返回NULL

你也有一个;刚过

if (hashArray[i]->key == hashArray[i + 1]->key)
移除它

我所能看到的最后一件事

delete(item);
是UB,因为项未初始化,因为insert函数中的代码使用了局部变量,可能需要更改

struct DataItem *item = (struct DataItem*) malloc(sizeof(struct DataItem));

编辑1

您还可以使用访问超出范围的数组

if (hashArray[i]->key == hashArray[i + 1]->key)
当i=SIZE-1时,哈希数组[i+1]超出范围
此外,hashArray[i+1]可以为空或未初始化。

如果您在编译代码时启用了调试,使用gcc启用ie-g选项,然后在调试器中运行它,它将告诉您发生seg故障的行。我可以看到有两个地方导致了seg错误——strcpy被传递了NULL,还有对deleteitem的调用,其中item仍然为NULL。大概是因为您认为您使用的是insert中定义的代码,而不是全局定义的代码。

如果您在编译代码时启用了带有gcc的ie-g选项,然后在调试器中运行它,它将告诉您发生seg故障的代码行。我可以看到有两个地方导致了seg错误——strcpy被传递了NULL,还有对deleteitem的调用,其中item仍然为NULL。大概是因为您认为您使用的是insert中定义的,而不是全局定义的。

strcpydummyItem->data,NULL;--->嘘!或者更好的歌舞厅!strcpydummyItem->数据,NULL;----->嘘!或者更好的歌舞厅!这修复了问题的一部分,但我仍然有一个分段错误。我认为我的显示函数有问题…或者struct DataItem*item=struct DataItem*mallocsizeofstruct DataItem;->item=mallocsizeofstruct数据项;这个问题已经解决了。我在寻找碰撞时又遇到了一个分割错误。int detect_collisions{int i=0;int collision=0;int prev=0;fori=0;ikey;ifhashArray[i]!=NULL prev=hashArray[i]->key;ifhashArray[i]->key==prev collision++;}返回冲突;}这修复了问题的一部分,但我仍然有一个分段错误。我认为我的显示函数有问题…或者struct DataItem*item=struct DataItem*mallocsizeofstruct DataItem;->item=mallocsizeofstruct数据项;这个问题已经解决了。我在寻找碰撞时又遇到了一个分割错误。int detect_collisions{int i=0;int collision=0;int prev=0;fori=0;ikey;ifhashArray[i]!=NULL prev=hashArray[i]->key;ifhashArray[i]->key==prev collision++;}返回冲突;}这修复了问题的一部分,但我仍然有一个分段错误。我认为我的显示功能有问题,这是问题的一个固定部分,但我仍然得到了一个分割错误。我想我的显示功能有问题