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
Post a Comment