【问题标题】:C Memory Management -> HashC 内存管理 -> 哈希
【发布时间】:2015-03-02 10:56:14
【问题描述】:

我不知道我的问题是内存泄漏,还是我没有以正确的方式访问哈希表。

我的哈希.h

#define HASHSIZE 31
#define EMPTY   ""
#define DELETED "-"

typedef char KeyType[9];

typedef void *Info;

typedef struct entry
{
    KeyType key;
    Info info;
}Entry;

typedef Entry HashTable[HASHSIZE];

我的 hash.c

int Hash(KeyType k){
    return atoi(k)%HASHSIZE;
}

void InitializeTable(HashTable t){
    for(int i=0; i < HASHSIZE; i++){
        strncpy(t[i].key,EMPTY,9);
    }
}

void ClearTable(HashTable t){
    InitializeTable(t);
}

void InsertTable_LP(HashTable t, KeyType k, Info i){
    int a = 0;
    int hash = Hash(k);
    while((a<HASHSIZE) 
            && strcmp(t[hash].key,EMPTY)!=0
                && strcmp(t[hash].key,DELETED)!=0  ){
        hash = (hash + 1) % HASHSIZE;
        a++;
    }

    strncpy(t[hash].key,k,9);
    t[hash].info = i;
    printf("Value of info is %d\n",(int)t[hash].info);

}

int RetrieveTable_LP(HashTable t, KeyType k){
    int a=0;
    int hash = Hash(k);

    while(a<HASHSIZE 
            && strcmp(t[hash].key,k)!=0
                && strcmp(t[hash].key,EMPTY)!=0){
        hash=(hash+1) % HASHSIZE;
        a++;    
    }

    if(strcmp(t[hash].key,k)==0)
        return hash;
    return -1;

}


int main(){
    HashTable *t = malloc(HASHSIZE*sizeof(Entry));
    int valores[] = {1,2,3,4,5,6,7,8,9};

    ClearTable(*t);
    InsertTable_LP(*t,"1",valores);
    InsertTable_LP(*t,"2",valores+1);
    InsertTable_LP(*t,"3",valores+2);
    InsertTable_LP(*t,"4",valores+3);
    InsertTable_LP(*t,"5",valores+4);

    int pos = RetrieveTable_LP(*t,"2");
    if(pos==-1){
        printf("Error\n");
    }
    else
        printf("Position %d\n",pos);
        printf("okay %d\n",(int)t[pos]->info);

    printf("asdasdas\n");

    return 1;
}

我的输出是

Value of info is 1537727040
Value of info is 1537727044
Value of info is 1537727048
Value of info is 1537727052
Value of info is 1537727056
Position 2
okay 0

如果有人能给我解释一下,在此先感谢。

【问题讨论】:

  • 看看你的代码,我发现(int)t[hash].info 是完全错误的:你将Info 转换为void*int
  • 将此作为练习,而不是我自己的实现。即便如此,如果我没记错的话 void* 让我得到任何类型的变量,因为我输入了一个 int 作为信息,我可以将它转换为 int。
  • 你的意思是取消引用它!不是很明显它会是*(int*) 而不是(int) !祝你好运!
  • 谢谢@Meninx!但是如果我这样做,我会遇到分段错误,但正如@iharob 所说,问题可能出在插入函数上!这就是为什么在进来之前,我在进来之前尝试了函数内部的printf。
  • 希望您解决了您的问题! :)

标签: c algorithm hash hashtable


【解决方案1】:

valores 是一个数组。您正在将Info 插入typedefed 到void *。你需要解决这些问题。

【讨论】:

  • 这应该是评论而不是答案。
  • 即便如此,它的头文件来自练习,如果我可以更改它,我的 HashTable 结构将是一个指针,我更容易使用它。
【解决方案2】:

您的malloc 不是必需的,之所以不明显是因为它被您typedefd 和HashTable 所隐藏,永远不要这样做,以下代码按您预期的那样工作你的事

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HASHSIZE 31
#define EMPTY   ""
#define DELETED "-"

typedef char KeyType[9];

typedef void *Info;

typedef struct entry
{
    KeyType key;
    Info info;
}Entry;

typedef Entry HashTable[HASHSIZE];

int Hash(KeyType k){
    return atoi(k)%HASHSIZE;
}

void InitializeTable(HashTable t) {
    int i;
    for(i=0; i < HASHSIZE; i++) {
        strncpy(t[i].key, EMPTY, 9);
    }
}

void ClearTable(HashTable t) {
    InitializeTable(t);
}

void InsertTable_LP(HashTable t, KeyType k, Info i){
    int a = 0;
    int hash = Hash(k);
    while((a<HASHSIZE) && strcmp(t[hash].key, EMPTY) !=0 && strcmp(t[hash].key, DELETED) !=0  ) {
        hash = (hash + 1) % HASHSIZE;
        a++;
    }
    strncpy(t[hash].key, k, 9);

    t[hash].info = i;

    printf("Value of info is %p\n", t[hash].info);

}

int RetrieveTable_LP(HashTable t, KeyType k){
    int a=0;
    int hash = Hash(k);

    while(a<HASHSIZE 
            && strcmp(t[hash].key,k)!=0
                && strcmp(t[hash].key,EMPTY)!=0){
        hash=(hash+1) % HASHSIZE;
        a++;    
    }

    printf("%s, %s\n", t[hash].key, k);
    if(strcmp(t[hash].key, k)==0)
        return hash;
    return -1;

}


int main(){
    /* 
     * You don't need to malloc, since HashTable is an array,
     * and it does not need to be a pointer, since it decays
     * to one when passed as such.
     */
    HashTable t;// = malloc(HASHSIZE * sizeof(Entry));
    int valores[] = {1,2,3,4,5,6,7,8,9};

    ClearTable(t);

    InsertTable_LP(t,"1",valores);
    InsertTable_LP(t,"2",valores+1);
    InsertTable_LP(t,"3",valores+2);
    InsertTable_LP(t,"4",valores+3);
    InsertTable_LP(t,"5",valores+4);

    int pos = RetrieveTable_LP(t, "2");
    if(pos==-1) {
        printf("Error\n");
    }
    else
    {
        printf("Position %d\n",pos);
        printf("okay %p\n", t[pos].info);
    }

    printf("asdasdas\n");

    return 1;
}

HashTable 中的 typedef 让人很难知道如何处理 HashTable 类型的变量,这不是 typedef 的一个很好的用途。

不管条件如何,第二个printf 也会被执行

else
    printf("Position %d\n",pos);
    printf("okay %d\n",(int)t[pos]->info);

您需要添加{

else
{
    printf("Position %d\n",pos);
    printf("okay %d\n",(int)t[pos]->info);
}

【讨论】:

  • 对不起,我不是很明确,我知道我正在打印内存位置。但我的问题是其他地方的 printf,我得到零作为位置 2 的 elemento 的值。尝试了相同的更正,但这样我得到了分段错误。
  • @Duozhasht 您应该使用unsigned 以使其正常工作。或使用"%p" 说明符。
  • 再一次,你是对的,但在我打印位置之前,我只是打印了 Okay + valueofinfo。即便如此,我仍然保持零。就像我在那个记忆位置失去了价值。 (题外话)如你所见,我在处理 C 中的内存时遇到了困难,也许你能指出我正确的方向,或者推荐一本好书。
  • 是的,事实上问题似乎出在您的RetrieveTable_LP 函数中,等等,我几乎找到了。
  • 哦,伙计,你就像第二个上帝,第一个是我的一位年长的老师。你们早餐必须吃点点滴滴!真的很泰!为了不提出另一个问题,如果我想要内存位置的空间,我应该只 malloc ?
猜你喜欢
  • 2014-01-24
  • 2016-01-07
  • 2010-09-06
  • 2018-12-17
  • 2014-10-24
  • 2014-09-11
  • 1970-01-01
相关资源
最近更新 更多