Exercise 6.5 - undef: remove name and definition from table¶
Question¶
Write a function undef that will remove a name and definition from the table maintained by lookup and install.
/* Write a function undef that will remove a name and definition
* from the table maintained by lookup and install.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HASHSIZE 101
static struct nlist *hashtab[HASHSIZE]; /* pointer table */
/* linked List of words. nlist from K&R Page 144 */
struct nlist { /* table entry: */
struct nlist *next; /* next entry in chain */
char *name; /* defined name */
char *defn; /* replacement text */
};
/* hash: form hash value for string s */
unsigned hash(char *s) {
unsigned hashval;
for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31 * hashval;
return hashval % HASHSIZE;
}
/* lookup: look for s in hashtab */
struct nlist *lookup(char *s) {
struct nlist *np;
for (np = hashtab[hash(s)]; np != NULL; np = np->next)
if (strcmp(s, np->name) == 0)
return np; /* found */
return NULL; /* not found */
}
/* install: put (name, defn) in hashtab */
struct nlist *install(char *name, char *defn) {
struct nlist *np;
unsigned hashval;
if ((np = lookup(name)) == NULL) { /* not found */
np = (struct nlist *) malloc(sizeof(*np));
if (np == NULL || (np->name = strdup(name)) == NULL)
return NULL;
hashval = hash(name);
np->next = hashtab[hashval];
hashtab[hashval] = np;
} else /* already there */
free((void *) np->defn); /* free the previous defn */
if ((np->defn = strdup(defn)) == NULL)
return NULL;
return np;
}
/**
* undef will be if it is just hashtable. Remove it.
* If it is in linked list, delete from linked list.
**/
struct nlist *undef(char *name) {
struct nlist *found;
found = lookup(name);
if (found == NULL) /* not found and nothing to do */
return NULL;
else {
if (found->next != NULL) {
found->next = found->next->next;
found = found->next;
} else {
hashtab[hash(name)] = NULL;
free((void *) found);
}
}
return found;
}
int main(int argc, char *argv[]) {
struct nlist *table[4] = {
(install("key", "value")),
(install("key1", "value1")),
(install("key2", "value2")),
(install("key3", "value3"))};
int i;
for (i = 0; i < 4; i++) {
printf("%s->%s\n", table[i]->name, table[i]->defn);
}
undef("key");
undef("key3");
struct nlist *result;
char *keys[4] = {"key", "key1", "key2", "key3"};
for (i = 0; i < 4; i++) {
if ((result = lookup(keys[i])) == NULL) {
printf("key not found\n");
} else {
printf("%s->%s\n", result->name, result->defn);
}
}
return 0;
}
Explanation¶
This program demonstrates implementing a hash table for inserting key -> value. When there is a collision to inserting values against a key, it will create a linked list of values.
So, it implements
install - installs the word in the hash table. Creates a linked list for the new value.
lookup - looks up the word in the hash table.
undef - removes the word in the hash table.
For each of these operations, it takes word, calculates the hash value. If there is a collision, it will add the word to the linked list in the hashtable key.
Sample run of this program.
key1->value1
key2->value2
key3->value3
key not found
key1->value1
key2->value2
key not found