Learn and understand "open hashing", which handles arbitrary sizes.
Open hashing declares each "bucket" to be a link list.
struct hashtableentry {
char *lexeme; /* actual string matched, unique in the hash table */
union lexval {
int category; /* when the entry is an identifier or reserved word */
int ival; /* when the entry is an integer literal */
float rval; /* when the entry is an real number literal */
char *sval; /* when the entry is a string literal */
} val;
struct hashtableentry *next;
};
typedef struct hashtableentry *hashtable[43]; /* large prime ending in 21? */
Sample code for hash table lookups and/or inserts. This function is intended
to do a lookup in the hash table. If the item is found, the shared copy of
the lexeme string is returned and the union pointed at by lexval l is filled
in from the entry. If the item is NOT found, it is inserted into the table
using a strdup()'ed copy of the string, which is returned. I have done most
of the changes needed to make this function calculate the lexval at
insert-time; you need to fix it for string constants.
hashtable myhashtable;
char *lookup_insert(char *s, union lexval *l)
{
int i = hash(s) % 43; /* compute which bucket to use */
struct hashtableentry *e = myhashtable[i % 43]; /* select that bucket */
/*
* From here on out, the hash table works like a link list.
* This while loop performs a lookup.
*/
while (e) {
if (!strcmp(s,e->lexeme)) {
if (l)
*l = e->val;
return e->lexeme;
}
e = e->next;
}
/*
* insert
*/
e = malloc(sizeof (struct hashtableentry));
if (e == NULL) return NULL;
e->lexeme = strdup(s);
switch(l->category) {
case INTEGER: /* calculate ival */
e->val.ival = atoi(s); break;
case REAL: /* calculate sval */
e->val.rval = atof(s); break;
case SCONST: /* calculate sval; add your code here */
e->val.sval = e->lexeme /* WRONG!!! */ ; break;
default:
if (l)
e->val = *l;
}
e->next = myhashtable[i];
myhashtable[i] = e;
return e->lexeme;
}