私はこれを理解するのに苦労しています。
まず、入力コマンドラインからこれを宣言すると、次のようになります。
#define Please 100
#define routine 120
'Please' と 'routine' の両方が同じハッシュ値を持っているためです。私のプログラムは、入力コンソールから「Please」と入力すると値が 120 になるハッシュタブの値を上書きします。
第二に、この部分
struct nlist *lookup (char *s)
{
struct nlist *np;
for (np = hashtab[hash(s)]; np != NULL; np = np->next)
return np;
return NULL;
}
具体的には for ループ ステートメントで。私の質問は、for ループを複数回繰り返すにはどうすればよいですか? すべての hashtab[hash(s)] 値に対して 1 つのインスタンスしか表示されないためです。
とにかく、ここに完全なコードがあります。これは gcc で実行できます。Undef() は問題なく動作します。
#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 be 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 i = 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 a 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; i < 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 a 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 {/* already 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;
for (hashval = 0; *s != '\0'; s++)
hashval = *s + 31 * hashval;
return hashval % HASHSIZE;
}
struct nlist *lookup (char *s)
{
struct nlist *np;
for (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 a 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 for ungetch */
int bufp = 0; /* next free position in buf */
int getca(void) /* get a (possibly pushed-back) character */
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetca(int c) /* push character back on input */
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}