为什么当#define处理器遇到#include时会出现奇怪的现象?
问题描述:
我写了一个#define
处理器的简单版本,用于练习K & R的C书(习题6.3)。它非常简单,适用于简单的输入。 但是,如果它遇到了一个#include行就会中断。它不会用替换文字取代任何名称。它只是打印确切的输入。 这里是我的代码:为什么当#define处理器遇到#include时会出现奇怪的现象?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define MAXWORD 100
#define SUCCESS 0
struct nlist {
struct nlist *next;
char *name;
char *defn;
};
struct nlist *lookup(char *);
struct nlist *install(char *, char *);
int getword(char *, int);
int gettoken(char *, int);
int nl = 0;
int main()
{
char word[MAXWORD], key[MAXWORD], value[MAXWORD], token[MAXWORD];
struct nlist *res, *rres;
FILE *fp = fopen("out", "w");
res = NULL;
while (getword(word, MAXWORD) != EOF) {
fprintf(fp, "%s_", word);
if (strcmp(word, "#define") == 0) {
getword(key, MAXWORD);
getword(value, MAXWORD);
install(key, value);
printf("%s %s %s\n", word, key, value);
} else if (strcmp(word, "#include") == 0) {
printf("%s ", word);
gettoken(word, MAXWORD);
printf("%s\n", word);
} else if ((res = lookup(word)) != NULL) {
printf("%s ", res->defn);
} else {
printf("%s ", word);
if (!strcmp(word, ";")) printf("\n");
else if (!strcmp(word, "{")) printf("\n");
else if (!strcmp(word, "}")) printf("\n");
}
}
return SUCCESS;
}
#define HASHSIZE 101
struct nlist *hashtab[HASHSIZE];
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)
if (strcmp(s, np->name) == 0)
return np;
return NULL;
}
struct nlist *install(char *name, char *defn)
{
struct nlist *np;
unsigned hashval;
char *mstrdup(char *);
if ((np = lookup(name)) == NULL) {
np = (struct nlist *) malloc(sizeof (*np));
if (np == NULL || (np->name = mstrdup(name)) == NULL)
return NULL;
hashval = hash(name);
np->next = hashtab[hashval];
hashtab[hashval] = np;
} else
free((void *) np->defn);
if ((np->defn = mstrdup(defn)) == NULL)
return NULL;
return np;
}
char *mstrdup(char *s)
{
char *p = malloc(strlen(s) + 1);
if (p != NULL)
strcpy(p, s);
return p;
}
int getch(void);
void ungetch(int);
int getword(char *word, int lim)
{
int c;
char *w = word;
while (isspace(c = getch()))
;
if (c != EOF)
*w++ = c;
if (!isalnum(c) && c != '#') {
*w = '\0';
return c;
}
for (; --lim > 0; w++) {
*w = getch();
if (!isalnum(*w) && *w != '_') {
if (*w != '\n')
ungetch(*w);
break;
}
}
if (*w == '\n')
nl = 1;
*w = '\0';
return word[0];
}
int gettoken(char *token, int lim)
{
int c;
char *t = token;
while (isspace(c = getch()))
;
if (c == '<') {
*t++ = c;
for (; --lim > 0 && *t != '>';)
*t++ = getch();
*t = '\0';
return token[0];
} else if (c == '\"') {
*t++ = c;
for (; --lim > 0 && *t != '\"';)
*t++ = getch();
*t = '\0';
return token[0];
} else {
strcpy(t, "Invalid token.");
return 0;
}
}
#define BUFF 100
char buff[BUFF];
char *bufp = buff;
int getch(void)
{
return (bufp > buff) ? *--bufp : getchar();
}
void ungetch(int c)
{
if (bufp < buff + BUFF)
*bufp++ = c;
else
bufp = buff;
}
我要输入这个文件:d.txt
#define MAX 100
#define MIN 0
int main() {
int i = MAX;
printf("%d %d", i, MIN);
return MIN;
}
,输出是:
$ ./defp < d.txt
#define MAX 100
#define MIN 0
int main () {
int i = 100 ;
printf (" % d % d " , i , 0) ; // notice the space between % and d It means that those characters was processed.
return 0 ;
}
但是当输入包含#include <stdio.h>
输出:
$ ./defp < d.txt
#define MAX 100
#define MIN 0
#include <stdio.h>
int main() {
int i = MAX;
printf("%d %d", i, MIN); // notice that there are no spaces just the exact input means that the line wasn't proccessed.
return MIN;
}
为什么它是这样的,我没有任何想法,请给我一个解释?
答
正如评论中所说,您的下一个任务是学习如何使用调试器。
提示:该错误是:
*t++ = getch();
TL; DR。提供[mcve]。使用调试器。 – Olaf
并且不要在C中投放'malloc'和朋友(或'void *')的结果! – Olaf
敢用调试器来调试你的代码吗? – alk