c - K&R Section 6-6 table lookup : Overwriting when hashvalues are the same -


i having trouble understanding this.

firstly point out when declare input command line:

#define please 100 #define routine 120 

since both 'please' , 'routine' have same hash values. program overwrites hashtab value typing 'please' input console have value of 120. how can fix overwriting problem or part of book?

secondly , part

struct nlist *lookup (char *s) { struct nlist *np; (np = hashtab[hash(s)]; np != null; np = np->next)     return np; return null; } 

specifically in loop statement. question how can loop repeat more once? since see 1 instance every hashtab[hash(s)] value.

here full code anyway. can run gcc. undef() works fine.

#include <stdio.h> #include <ctype.h> #include <stdlib.h> #include <string.h> //#include <vld.h> #define maxword 100  struct nlist {     struct nlist *next;     char *name;     char *defn; };  void error(int, char *); int getca(void); // getch() void getdef(void); int getword(char *, int); struct nlist *install(char *, char *); struct nlist *lookup(char *); void skipblanks(void); void undef(char *); void ungetca(int); // ungetch() void ungets(const char *);  #define hashsize 101 unsigned hash(char *); static struct nlist *hashtab[hashsize]; char *strdupli (char *); //strdup() function  int main(void) { char w[maxword]; struct nlist *p;  while (getword(w, maxword) != eof)     if (strcmp(w, "#") == 0) /* beginning of direct */         getdef();     else if (!isalpha(w[0]))         printf("%s", w);    /* cannot defined */     else if ((p = lookup(w)) == null)         printf("%s", w);   /* not defined */     else         ungets(p->defn); /* push definition */ return 0; }  void ungets(const char *s) { size_t = strlen(s); while(i > 0)     ungetca(s[--i]); }  void getdef(void) {     int i;     char def[maxword], dir[maxword], name[maxword]; skipblanks(); if (!isalpha(getword(dir, maxword)))     error (dir[0],     "getdef: expecting directive after #"); else if (strcmp(dir, "define") == 0) {     skipblanks();     if (!isalpha(getword(name, maxword)))         error(name[0],         "getdef: non-alpha - name expected");     else {         skipblanks();         for(i = 0; < maxword - 1; i++)             if((def[i] = getca()) == eof ||                                     def[i] == '\n')                 break;  /*end of definition*/         def[i] = '\0';         if(i <= 0)      /* no definition */             error('\n', "getdef: incomplete define");         else            /* install definition */             install (name, def);     } } else if (strcmp(dir, "undef") == 0) {     skipblanks();     if(!isalpha(getword(name, maxword)))         error(name[0], "getdef: non-alpha in undef");     else         undef(name); } else     error(dir[0],     "getdef: expecting directive after #"); }    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 = strdupli(name)) == null)         return null;     hashval = hash(name);     np->next = hashtab[hashval];     hashtab[hashval] = np; } else {/* there */     free((void *) np->defn); /*free previous defn */ } if ((np->defn = strdupli(defn)) == null)     return null; return np;  }  void undef(char *s) { int h; struct nlist *prev, *np;  prev = null; h = hash(s); for(np = hashtab[h]; np != null; np = np->next) {     if(strcmp(s, np->name)==0)         break;     prev = np; } if (np != null) {     if (prev == null)         hashtab[h] = np->next;     else         prev->next = np->next;     free((void *) np->name);     free((void *) np->defn);     free((void *) np); } }  unsigned hash(char *s) { unsigned hashval; (hashval = 0; *s != '\0'; s++)     hashval = *s + 31 * hashval; return hashval % hashsize; }  struct nlist *lookup (char *s) { struct nlist *np; (np = hashtab[hash(s)]; np != null; np = np->next)     return np; return null; }  int getword(char *word, int lim) {     int c, getca(void);     void ungetca(int);     char *w = word;      while(isspace(c = getca()))         ;     if(c != eof)         *w++ = c;     if(!isalpha(c)) {         *w = '\0';     return c; }     for( ; --lim > 0; w++)         if(!isalnum(*w = getca())) {             ungetca(*w);             break;         }     *w = '\0';     return word[0]; }  void error(int c, char *s) {     printf("error: %s\n", s);         while(c != eof && c != '\n')     c = getca(); }  void skipblanks (void) {     int c; while ((c = getca()) == ' ' || c == '\t') ; ungetca(c); }  void strcopy (char *, const char *); char *strdupli (char *s) /* make duplicate of s */ {     char *p;     p = (char *) malloc (strlen(s) + 1);     if (p != null)         strcopy(p, s);     return p; }  void strcopy (char *s, const char *t) {         while ((*s++ = *t++) != '\0')         ; }  #define bufsize 100 char buf[bufsize]; /* buffer ungetch */ int bufp = 0; /* next free position in buf */ int getca(void) /* (possibly pushed-back) character */ {     return (bufp > 0) ? buf[--bufp] : getchar(); }  void ungetca(int c) /* push character on input */ {     if (bufp >= bufsize)        printf("ungetch: many characters\n");     else     buf[bufp++] = c; } 

here's example, assuming else identical k&r's example:

define function prints hashtable:

void printtable(struct nlist* ptable[]) {     (int i=0; i<hashsize; i++)         if (ptable[i] != null)         {             printf("hash table index %d content: \n", i);             int j = 0;             struct nlist *plist;             (plist = ptable[i]; plist != null; plist = plist->next)                 printf("\tlist nr %d: name: '%s', defn: '%s'\n", j++, plist->name, plist->defn);         } } 

insert 2 definitions collide:

install("please", "bla"); install("routine", "blabla"); 

and print results:

printtable(hashtab); 

gives:

hash table index 90 content:      list nr 0: name: 'routine', defn: 'blabla'     list nr 1: name: 'please', defn: 'bla' 

Comments