我为K&R的C书中的练习编写了一个简单的#define
处理器版本(练习6.3)。它非常简单,对于简单的输入很好。
但如果它遇到一个包含线,它就会断开。它不会用替换文本替换任何名称。它只是打印出准确的输入。
这是我的代码:
#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();
关于c - 为什么这个#define处理器遇到#include时表现奇怪?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33595301/