EDIT:我已经更新了init函数(更新了代码(以使用malloc,分段错误已经消失。但是,我现在没有从打印表函数得到任何输出。根据建议进一步更新了代码。它现在似乎起作用了
我一直在关注K&R(C初学者(为C,并尝试使用第6.7节中的示例编写哈希表(几乎没有修改(
代码如下-
#include <stdio.h>
#include <string.h>
#include "hashtable.h"
#define HASHSIZE 101
listptr * init_table()
{
listptr *hashtab = (listptr *) calloc(HASHSIZE, sizeof(*hashtab));
return hashtab;
}
unsigned hash (char *s)
{
unsigned hashval;
for (hashval=0; *s != ' '; s++)
hashval = *s + 31 * hashval;
return hashval % HASHSIZE;
}
listptr lookup (listptr * hashtab, char *s)
{
listptr np;
for (np = hashtab[hash(s)]; np!=NULL; np = np->next)
if (strcmp(s, np->name) == 0)
return np;
return NULL;
}
listptr install(listptr * hashtab, char *name, char * defn)
{
listptr np;
unsigned hashval;
if((np = lookup(hashtab, name)) == NULL) {
np = (listptr) malloc(sizeof(*np));
if (np==NULL || (np->name = strdup(name))==NULL)
return NULL;
hashval = hash(name);
np->next = hashtab[hashval];
hashtab[hashval] = np;
}
else
{
free((void*) np->defn);
}
if ((np->defn = strdup(defn)) == NULL)
return NULL;
return np;
}
void printtable(listptr * table, int len)
{
listptr p;
int i =0;
while (i < len) {
if (table[i] != NULL) {
for (p = table[i];p!=NULL;p=p->next) {
printf("%st%sn", p->name, p->defn);
}
}
i++;
}
}
hashtable.h包含-
#ifndef HDR
#define HDR
#include <stdlib.h>
typedef struct nlist *listptr;
typedef struct nlist {
listptr next;
char *name;
char *defn;
} Hashtablebucket;
listptr * init_table();
listptr lookup(listptr *, char *);
listptr install (listptr *, char *, char *);
void printtable(listptr *, int );
#endif
我主要有-
#include <stdio.h>
#include <string.h>
#include "hashtable.h"
int main()
{
listptr * table = init_table();
install(table, "key1", "value1");
install(table, "key2", "value2");
install(table, "key3", "value3");
printtable(table, 101);
return 0;
}
这导致了分割错误,我不知道会出什么问题,因为哈希表有101个空间元素。
如果您能帮我调试这个问题,我将不胜感激。。。
编辑:对于上面的代码,根本没有输出。有人能帮忙调试吗?
提前感谢
原始K&R代码采用全局表。在您的情况下,您尝试在本地分配它,但不能返回指向本地变量的指针(当然可以,但行为未定义(。相反,您需要使用malloc
/或更好的calloc
来分配内存,在本例中为:
listptr * init_table()
{
listptr *table = calloc(HASHSIZE, sizeof *table);
return table;
}
最好为哈希表制作一个结构,这样您就可以拥有不同大小的表:
struct hashtable {
size_t n_slots;
listptr *slots;
};
struct hashtable *init_table(size_t n_slots) {
struct hashtable *tbl = malloc(sizeof *tbl);
tbl->n_slots = n_slots;
tbl->slots = calloc(n_slots, sizeof *(tbl->slots));
return tbl;
}
对于hash
函数,最好保留它,使其始终返回unsigned int
(或size_t
!(,并在该函数之外执行模运算。此外,char
可以是有符号的,也可以是无符号的;你很可能想要使用unsigned char
s。
即
size_t hash (char *s)
{
size_t hashval;
for (hashval=0; *s != ' '; s++)
hashval = *(unsigned char*)s + 31 * hashval;
return hashval;
}
和
hashval = hash(name) % tbl->n_slots;