6-1:
上述getword函数不能正确处理下划线、字符串常量、注释及预处理器控制指令。请编写一个更完善的getword函数
/*原函数无法识别带下划线的字符串,例如keytab数组将if和else视为关键字,但是
如果我们输入if_else,这其实不是关键字,但是程序还会将其保留,我们需要排除
这种情况,同时对于""包裹的字符串常量、注释符包裹的注释语句、预处理器指令,
我们需要排除这些语句*/
#include
#include
#include
#define BUFSIZE 100
#define MAXWORD 100
#define NKEYS (sizeof(keytab)/sizeof(keytab[0]))
char buf[BUFSIZE];
int bufp = 0;
struct key {
char *word;
int count;
};
int binsearch(char *, struct key *, int);
int getword(char *, int);
int main(void)
{
char word[MAXWORD];
int n;
struct key keytab[] = {
{"break", 0},
{"continue", 0},
{"else", 0},
{"if", 0},
{"struct", 0}
};
while(getword(word, MAXWORD) != EOF)
if(isalpha(word[0]))
if((n = binsearch(word, keytab, NKEYS)) >= 0)
keytab[n].count++;
for(n = 0; n < NKEYS; n++)
if(keytab[n].count > 0)
printf("%4d %s\n", keytab[n].count, keytab[n].word);
return 0;
}
int binsearch(char *word, struct key tab[], int n)
{
int low, mid, high;
low = 0;
high = n - 1;
while(low <= high)
{
mid = (low + high) / 2;
if(strcmp(word, tab[mid].word) < 0)
high = mid - 1;
else if(strcmp(word, tab[mid].word) > 0)
low = mid + 1;
else
return mid;
}
return -1;
}
int getword(char *word, int lim)
{
int c, prev, getch(void);
void ungetch(int);
char *w = word;
while(isspace(c = getch()))
;
if(c != EOF)
*w++ = c;
if(!isalpha(c) && c != '_')//排除下划线在前的情况
{
if(c == '#')
{
while((c = getch()) != '\n')
;
}
else if(c == '\"')
{
while((c = getch()) != '\"')
;
}
else if(c == '/')
{
if((c = getch()) == '*')
{
prev = ' ';
while((c = getch()) != EOF)//从遇到/*开始循环,直到EOF或者*/退出
{
if(c == '/' && prev == '*')
break;
prev = c;
}
}
else if(c == '/')
{
while((c = getch()) != '\n')
;
}
else
ungetch(c);
}
else
*w = '\0';
return c;
}
for(; --lim > 0; w++)
if(!isalnum(*w = getch()) && *w != '_')//排除下划线在后的情况
{
ungetch(*w);
break;
}
*w = '\0';
return word[0];
}
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("error: too many parameters\n");
else
buf[bufp++] = c;
}
6-2:
编写一个程序,用以读入一个C语言程序,并按字母表顺序分组打印变量名,要求每一组内各变量名的前6个字符相同,其余字符不同。字符串和注释中的单词不予考虑。请将6作为一个可在命令行设定的参数
/*光看题目就有点晕,我理解的意思是:
建立一个二叉查找树(第一层),该树的每个节点本身又是一个二叉查找树(第二
层),将前6个字符相同的单词放在第一层树的一个节点中,然后在第二层树中再对
这些单词排序
*/
#include
#include
#include
#include
#define BUFSIZE 100
#define MAXWORD 100
char buf[BUFSIZE];
int bufp = 0;
struct tree2 { //第二层树,存储前6个字符相同的变量名
char *s;
int count;
struct tree2 *left;
struct tree2 *right;
};
struct tree1 { //第一层树,存储前6个字符不同的变量名
char *s;
struct tree1 *left;
struct tree1 *right;
struct tree2 *root;
};
int getword(char *, int);
struct tree1 *addtree1(struct tree1 *p, char *w, int n);
struct tree2 *addtree2(struct tree2 *p, char *w);
void treeprint2(struct tree2 *p);
void treeprint1(struct tree1 *p);
void *talloc(int n);
char *strdup(char *s, int n);
void freetree1(struct tree1 *p);
void freetree2(struct tree2 *p);
int main(int argc, char **argv)
{
int n = 6;
struct tree1 *root = NULL;
char word[MAXWORD];
if(argc != 2)
printf("parameters error!\n");
else
n = atoi(argv[1]);
while(getword(word, MAXWORD) != EOF)
if(isalpha(word[0]))
root = addtree1(root, word, n);
treeprint1(root);
freetree1(root); //释放malloc函数分配的空间
return 0;
}
struct tree1 *addtree1(struct tree1 *p, char *w, int n)
{
int cond;
if(p == NULL)
{
p = (struct tree1 *)talloc(1);
p -> s = strdup(w, n);
p -> left = p -> right = NULL;
p -> root = NULL;
p -> root = addtree2(p -> root, w);//将首个单词存入二层树树根
}
else if((cond = strncmp(w, p -> s, n)) == 0)
p -> root = addtree2(p -> root, w);
else if(cond > 0)
p -> right = addtree1(p -> right, w, n);
else
p -> left = addtree1(p -> left, w, n);
return p;
}
struct tree2 *addtree2(struct tree2 *p, char *w)
{
int cond;
if(p == NULL)
{
p = (struct tree2 *) talloc(2);
p -> s = strdup(w, MAXWORD);
p -> count = 1;
p -> left = p -> right = NULL;
}
else if((cond = strcmp(w, p -> s)) == 0)
p -> count++;
else if(cond > 0)
p -> right = addtree2(p -> right, w);
else
p -> left = addtree2(p -> left, w);
return p;
}
void *talloc(int n)
{
if(n == 1)
return (struct tree1 *) malloc(sizeof(struct tree1));//返回指向一层树一个节点的指针
else
return (struct tree2 *) malloc(sizeof(struct tree2));//返回指向二层树一个节点的指针
}
char *strdup(char *s, int n)
{
char *p;
if(n == MAXWORD)
p = (char *) malloc(strlen(s) + 1);
else
p = (char *) malloc(sizeof(char) * (n + 1));
if(p != NULL)
{
*p = '\0';
if(n == MAXWORD)
strcpy(p, s);
else
strncat(p, s, n);
}
return p;
}
void treeprint1(struct tree1 *p)
{
if(p != NULL)
{
treeprint1(p -> left);
printf("%s: ", p -> s);
treeprint2(p -> root);
putchar('\n');
treeprint1(p -> right);
}
}
void treeprint2(struct tree2 *p)
{
if(p != NULL)
{
treeprint2(p -> left);
printf("%s (%d) ", p -> s, p -> count);
treeprint2(p -> right);
}
}
void freetree1(struct tree1 *p)
{
struct tree1 *pright;
if(p != NULL)
{
pright = p -> right;
freetree1(p -> left);
freetree2(p -> root);
free(p);
freetree1(pright);
}
}
void freetree2(struct tree2 *p)
{
struct tree2 *pright;
if(p != NULL)
{
pright = p -> right;
freetree2(p -> left);
free(p);
freetree2(pright);
}
}
int getword(char *word, int lim)
{
int c, prev, getch(void);
void ungetch(int);
char *w = word;
while(isspace(c = getch()))
;
if(c != EOF)
*w++ = c;
if(!isalpha(c))
{
if(c == '\"')
{
while((c = getch()) != '\"')
;
}
else if(c == '/')
{
if((c = getch()) == '*')
{
prev = ' ';
while((c = getch()) != EOF)//从遇到/*开始循环,直到EOF或者退出
{
if(c == '/' && prev == '*')
break;
prev = c;
}
}
else if(c == '/')
{
while((c = getch()) != '\n')
;
}
else
ungetch(c);
}
else
*w = '\0';
return c;
}
for(; --lim > 0; w++)
if(!isalnum(*w = getch()))
{
ungetch(*w);
break;
}
*w = '\0';
return word[0];
}
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("error: too many parameters\n");
else
buf[bufp++] = c;
}
//上面的addtree1和addtree2、freetree1和freetree2函数可以合并,但是涉及到
//强制类型转换、函数返回类型、传入参数类型和数量等,会比较复杂,所以简单起
//见就将它们分开了
6-3:
编写一个交叉引用程序,打印文档中所有单词的列表,并且每个单词还有一个列表,记录出现过该单词的行号。对the、and等非实义单词不予考虑
/*此题采用一个二叉树加一个链表的形式储存单词和它出现的行号,链表可以视为单
子树的二叉树,即只有一个指向下一节点的指针*/
#include
#include
#include
#include
#define BUFSIZE 100
#define MAXWORD 100
char buf[BUFSIZE];
int bufp = 0;
struct tree {
char *s;
int count;
struct list *head;//指向链表表头的指针
struct tree *left;
struct tree *right;
};
struct list {
int line;
struct list *next;
};
int getword(char *, int);
struct tree *addtree(struct tree *p, char *w, int n);
struct list *addlist(struct list *p, int n);
void treeprint(struct tree *p);
void listprint(struct list *p);
void *talloc(int n);
char *strdup(char *s);
void freetree(struct tree *p);
void freelist(struct list *p);
int main(void)
{
struct tree *root = NULL;
int line = 1;
int c;
char word[MAXWORD];
while((c = getword(word, MAXWORD)) != EOF)
{
if(c == '\n')
{
line++;
}
if(isalpha(word[0]) && strstr("the and ", word) == NULL)
root = addtree(root, word, line);
}
treeprint(root);
freetree(root); //释放malloc函数分配的空间
return 0;
}
struct tree *addtree(struct tree *p, char *w, int n)
{
int cond;
if(p == NULL)
{
p = (struct tree *) talloc(1);
p -> s = strdup(w);
p -> count = 1;
p -> left = p -> right = NULL;
p -> head = NULL;
p -> head = addlist(p -> head, n);//将首次出现的单词的行号存入链表表头
}
else if((cond = strcmp(w, p -> s)) == 0)
{
p -> count++;
p -> head = addlist(p -> head, n);
}
else if(cond > 0)
p -> right = addtree(p -> right, w, n);
else
p -> left = addtree(p -> left, w, n);
return p;
}
struct list *addlist(struct list *p, int n)
{
if(p == NULL)
{
p = (struct list *) talloc(2);
p -> line = n;
p -> next = NULL;
}
else
p -> next = addlist(p -> next, n);
return p;
}
void *talloc(int n)
{
if(n == 1)
return (struct tree *) malloc(sizeof(struct tree));
else
return (struct list *) malloc(sizeof(struct list));
}
char *strdup(char *s)
{
char *p;
p = (char *) malloc(strlen(s) + 1);
if(p != NULL)
strcpy(p, s);
return p;
}
void treeprint(struct tree *p)
{
if(p != NULL)
{
treeprint(p -> left);
printf("%s(%d): ", p -> s, p -> count);
listprint(p -> head);
putchar('\n');
treeprint(p -> right);
}
}
void listprint(struct list *p)
{
if(p != NULL)
{
printf("%d ", p -> line);
listprint(p -> next);
}
}
void freetree(struct tree *p)
{
struct tree *pright;
if(p != NULL)
{
pright = p -> right;
freetree(p -> left);
freelist(p -> head);
free(p);
freetree(pright);
}
}
void freelist(struct list *p)
{
if(p -> next != NULL)
freelist(p -> next);
free(p);
}
int getword(char *word, int lim)
{
int c, prev, getch(void);
void ungetch(int);
char *w = word;
while((c = getch()) == ' ' || c == '\t')
;
if(c != EOF)
*w++ = c;
if(!isalpha(c))
{
*w = '\0';
return c;
}
for(; --lim > 0; w++)
if(!isalnum(*w = getch()))
{
ungetch(*w);
break;
}
*w = '\0';
return word[0];
}
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("error: too many parameters\n");
else
buf[bufp++] = c;
}
6-4:
编写一个程序,根据单词的出现频率按降序打印输入的各个不同单词,并在每个单词的前面标上它的出现次数
/*此题我能想到的有三种方法:
一、以链表的形式储存单词和它的出现次数这些信息,再以出现频率顺序交换这些信
息,再打印,但是在单词的储存过程中会很耗费时间
二、以二叉查找树的形式储存信息,再按顺序交换这些信息,但是具体的实现方法很
复杂,而且程序耗费的时间也是一个问题
三、以二叉查找树的形式储存信息,再创建一个指针数组,数组中的每个指针指向一
个二叉树节点,再对这些指针进行排序,相对前两种方法,其储存单词时间和排序时
间更少,所以采用这种方法*/
#include
#include
#include
#include
#define BUFSIZE 100
#define MAXWORD 100
char buf[BUFSIZE];
int bufp = 0;
int node = 0; //计算树中的节点个数,声明为外部变量
struct tree **tree_node;//指针数组,每个指针指向一个树节点
struct tree {
char *s;
int count;
struct tree *left;
struct tree *right;
};
int getword(char *, int);
struct tree *addtree(struct tree *p, char *w);
void treeprint(struct tree *p);
void *talloc(int n);
char *strdup(char *s);
void freetree(struct tree *p);
void qsort(struct tree **s, int left, int right);
void swap(struct tree **v, int i, int j);
int main(void)
{
struct tree *root = NULL;
char word[MAXWORD];
while(getword(word, MAXWORD) != EOF)
if(isalpha(word[0]))
root = addtree(root, word);
tree_node = (struct tree **) talloc(2);//为指针数组分配空间
printf("按字母表顺序排序单词\n");
treeprint(root);//为每个指针赋值
putchar('\n');
printf("按出现频率排序单词\n");
qsort(tree_node, 0, node - 1);//为指针数组排序
for(int i = 0; i < node; i++)
{
printf("(%d)%s\n", tree_node[i] -> count, tree_node[i] -> s);
}
freetree(root); //释放malloc函数分配的空间
free(tree_node);
return 0;
}
struct tree *addtree(struct tree *p, char *w)
{
int cond;
if(p == NULL)
{
p = (struct tree *)talloc(1);
p -> s = strdup(w);
p -> count = 1;
p -> left = p -> right = NULL;
node++;//统计节点个数
}
else if((cond = strcmp(w, p -> s)) == 0)
p -> count++;
else if(cond > 0)
p -> right = addtree(p -> right, w);
else
p -> left = addtree(p -> left, w);
return p;
}
void *talloc(int n)
{
if(n == 1)
return (struct tree *) malloc(sizeof(struct tree));
else
return (struct tree **) malloc(sizeof(struct tree *) * node);
}
char *strdup(char *s)
{
char *p;
p = (char *) malloc(strlen(s) + 1);
if(p != NULL)
strcpy(p, s);
return p;
}
void treeprint(struct tree *p)
{
static struct tree **s = tree_node;//此函数不能采用传递tree_node为指针数组的每个指针赋值,
//因为递归调用会造成混乱,新建一个static变量,防止重复初始化
if(p != NULL)
{
treeprint(p -> left);
printf("(%d) %s\n", p -> count, p -> s);
*s++ = p;
treeprint(p -> right);
}
}
void qsort(struct tree **s, int left, int right)
{
int i, last;
if(left >= right)
return;
swap(s, left, (left + right) / 2);
last = left;
for(i = left + 1; i <= right; i++)
if(s[i] -> count > s[left] -> count)
swap(s, ++last, i);
swap(s, left, last);
qsort(s, left, last - 1);
qsort(s, last + 1, right);
}
void swap(struct tree **v, int i, int j)
{
struct tree *temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
void freetree(struct tree *p)
{
struct tree *pright;
if(p != NULL)
{
pright = p -> right;
freetree(p -> left);
free(p);
freetree(pright);
}
}
int getword(char *word, int lim)
{
int c, prev, getch(void);
void ungetch(int);
char *w = word;
while(isspace(c = getch()))
;
if(c != EOF)
*w++ = c;
if(!isalpha(c))
{
*w = '\0';
return c;
}
for(; --lim > 0; w++)
if(!isalnum(*w = getch()))
{
ungetch(*w);
break;
}
*w = '\0';
return word[0];
}
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("error: too many parameters\n");
else
buf[bufp++] = c;
}
6-5:
编写函数undef,它将从由lookup和install维护的表中删除一个变量及其定义
/*在ASCII码中,每个字符都可以用一个数字代替,那么一个字符串同样可以转换为
一个数字,通过一个函数将一个字符串转换为合适大小的数字,这个函数成为哈希函
数,而这个数字就是存储这条字符串的数组的下标,下一次再遇到此字符串时,利用
哈希函数可得到相同的数字,查找这个数字下标的数组元素就可以找到之前存储的字
符串,这就是散列查找,也称哈希查找。哈希查找的时间复杂度为O(1),因为只需要
利用哈希函数得到数组下标就可以通过该下标查找到元素
但是哈希查找也有缺陷,易出现冲突,即两个不相同的字符串可能通过哈希函数得到
的数字相同,尤其是数组规模不大时,这种冲突极易出现,解决冲突的方式有多种,
此书采用的是链表法,即数组的每个元素是一个指向链表的指针,在链表中存放字符
串,当遇到冲突字符串时,将冲突字符串添加到链表中,查找时遍历整个链表,寻找
是否有相同字符串*/
#include
#include
#include
#include
#define HASHSIZE 101
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp = 0;
struct nlist {
struct nlist *next;
char *name;
char *defn;
};
static struct nlist *hashtab[HASHSIZE];
unsigned hash(char *s);
struct nlist *lookup(char *s);
struct nlist *install(char *name, char *defn);
int undef(char *name);
char *strdup(char *s);
int getword(char *word, int lim);
int getch(void);
void ungetch(int c);
int main(void)
{
char name[100], define[100];
struct nlist *np;
printf("请输入创建表的名字\n");
while(getword(name, 100) != EOF)
{
printf("请输入该名字的替换文本\n");
getword(define, 100);
if(install(name, define) == NULL)
break;
printf("继续输入名字\n");
}
printf("请输入待查找的名字\n");
while(getword(name, 100) != EOF)
{
if((np = lookup(name)) != NULL)
printf("%s %s\n", np -> name, np -> defn);
else
printf("error\n");
}
printf("请输入待删除的名称\n");
while(getword(name, 100) != EOF)
{
if(undef(name))
printf("删除成功\n");
else
printf("error\n");
}
printf("请输入待查找的名字\n");
while(getword(name, 100) != EOF)
{
if((np = lookup(name)) != NULL)
printf("%s %s\n", np -> name, np -> defn);
else
printf("error\n");
}
return 0;
}
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;
if((np = lookup(name)) == NULL)//查找链表有无匹配的名字,如果没有
{
np = (struct nlist *) malloc(sizeof(*np));
if(np == NULL || (np -> name = strdup(name)) == NULL)
return NULL;
hashval = hash(name);
np -> next = hashtab[hashval];//从链表的表头添加项,hashtab[hashval]指向的是原链表的表头
hashtab[hashval] = np;//np现在成为新链表的表头,hashtab[hashval]指向np
}
else
free((void *) np -> defn);//释放原替换文本分配的空间
if((np -> defn = strdup(defn)) == NULL)//不管链表有无匹配的名字,都将通过此语句为defn分配空间并赋值
return NULL;
return np;
}
int undef(char *name)
{
struct nlist *np1, *np2;
for(np1 = hashtab[hash(name)], np2 = NULL; np1 != NULL; np2 = np1, np1 = np1 -> next)
if(!strcmp(name, np1 -> name))
{
if(np2 == NULL)
hashtab[hash(name)] = np1 -> next;
else
np2 -> next = np1 -> next;
free(np1 -> name);
free(np1 -> defn);
free(np1);
return 1;
}
return 0;
}
char *strdup(char *s)
{
char *p;
p = (char *) malloc(strlen(s) + 1);
if(p != NULL)
strcpy(p, s);
return p;
}
int getword(char *word, int lim)
{
int c, getch(void);
void ungetch(int);
char *w = word;
while(isspace(c = getch()))
;
if(c != EOF)
*w++ = c;
if(!isalnum(c))
{
*w = '\0';
return c;
}
for(; --lim > 0; w++)
if(!isalnum(*w = getch()))
{
ungetch(*w);
break;
}
*w = '\0';
return word[0];
}
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("error: too many parameters\n");
else
buf[bufp++] = c;
}
6-6:
以本节介绍的函数为基础,编写一个适合C语言程序使用的#define处理器的简单版本(即无参数的情况下)。你会发现getch和ungetch函数非常有用
/*简单版本的程序,很多情况忽略了,如注释或者""中出现了宏时,仍然会执行替换*/
#include
#include
#include
#include
#define HASHSIZE 101
#define BUFSIZE 100
#define MAXWORD 100
char buf[BUFSIZE];
int bufp = 0;
char name[MAXWORD];
char defn[MAXWORD];
struct nlist {
struct nlist *next;
char *name;
char *defn;
};
static struct nlist *hashtab[HASHSIZE];
unsigned hash(char *s);
struct nlist *lookup(char *s);
struct nlist *install(char *name, char *defn);
int undef(char *name);
char *strdup(char *s);
int getword(char *word, int lim);
int getch(void);
void ungetch(int c);
void skipblanks(void);
int main()
{
char word[MAXWORD];
struct nlist *np;
while(getword(word, MAXWORD) != EOF)
{
if(isalpha(word[0]) || word[0] == '_')
{
if((np = lookup(word)) != NULL)
printf("%s", np -> defn);
else
printf("%s", word);
}
else
printf("%s", word);
}
return 0;
}
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;
if((np = lookup(name)) == NULL)//查找链表有无匹配的名字,如果没有
{
np = (struct nlist *) malloc(sizeof(*np));
if(np == NULL || (np -> name = strdup(name)) == NULL)
return NULL;
hashval = hash(name);
np -> next = hashtab[hashval];//从链表的表头添加项,hashtab[hashval]指向的是原链表的表头
hashtab[hashval] = np;//np现在成为新链表的表头,hashtab[hashval]指向np
}
else
free((void *) np -> defn);//释放原替换文本分配的空间
if((np -> defn = strdup(defn)) == NULL)//不管链表有无匹配的名字,都将通过此语句为defn分配空间并赋值
return NULL;
return np;
}
int undef(char *name)
{
struct nlist *np1, *np2;
for(np1 = hashtab[hash(name)], np2 = NULL; np1 != NULL; np2 = np1, np1 = np1 -> next)
if(!strcmp(name, np1 -> name))
{
if(np2 == NULL)
hashtab[hash(name)] = np1 -> next;
else
np2 -> next = np1 -> next;
free(np1 -> name);
free(np1 -> defn);
free(np1);
return 1;
}
return 0;
}
char *strdup(char *s)
{
char *p;
p = (char *) malloc(strlen(s) + 1);
if(p != NULL)
strcpy(p, s);
return p;
}
int getword(char *word, int lim)
{
int c, getch(void);
void ungetch(int);
char *w = word;
struct nlist *np;
while(isspace(c = getch()))
;
if(c != EOF)
*w++ = c;
if(!isalnum(c))
{
if(c == '#')
{
w = word;
for(; --lim > 0 && isalpha(c = getch()); *w++ = c)
;
*w = '\0';
skipblanks();
if(!strcmp(word, "define"))//处理#define命令
{
for(int i = 0; i < MAXWORD && (isalnum(c = getch()) || c == '_'); i++)
{
name[i] = c;
if(isdigit(name[0]))//排除首字符为字母的情况
printf("error: the first character cannot be a number\n");
}
name[i] = '\0';
skipblanks();
for(i = 0; i < MAXWORD; i++)
{
defn[i] = getch();
if(defn[i] == '\n' && defn[i - 1] != '\\')//允许使用'\'字符换行的情况
break;
}
defn[i] = '\0';
install(name, defn);
word[0] = '\0';
}
else if(!strcmp(word, "undef"))//处理#undef
{
for(int i = 0; i < MAXWORD && (isalnum(c = getch()) || c == '_'); i++)
{
name[i] = c;
if(isdigit(name[0]))
printf("error: the first character cannot be a number\n");
}
name[i] = '\0';
if(!undef(name))
printf("error: The name was not found");
word[0] = '\0';
}
else//处理#加宏名的情况,使用""包裹替换文本取代
{
if((np = lookup(word)) != NULL)
{
strcpy(word, "\"");
strcat(word, np -> defn);
strcat(word, "\"");
}
else
printf("error: invalid instruction\n");
}
return 0;
}
else
{
*w = '\0';
return c;
}
}
for(; --lim > 0; w++)
if(!isalnum(*w = getch()))
{
ungetch(*w);
break;
}
*w = '\0';
return word[0];
}
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("error: too many parameters\n");
else
buf[bufp++] = c;
}
void skipblanks(void)
{
int c;
while((c=getch())==' '||c=='\t')
;
ungetch(c);
}