1. 统计输入各个c语言关键字出现的次数(6.3)
其中: #define NKEYS (sizeof keytab / sizeof(struct key))
sizeof 是一个一元运算符 sizeof 对象 或者 sizeof (类型名字)
sizeof 可以用在#define 中(预处理不计算#define语句中的表达式),但是不能用在#if条件编译中(预处理不对类型名进行分析),
利用结构数组:
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define MAXWORD 100
#define NKEYS (sizeof keytab / sizeof(struct key))
struct key
{
char *word;
int count;
}keytab[]={
"auto", 0,
"break",0,
"case", 0,
"char", 0,
"const",0,
"continue",0,
"unsigned",0,
"void", 0,
"volatile", 0,
"while",0
};
int getword(char *, int);
int binsearch(char *, struct key *, int);
int main()
{
int n;
char word[MAXWORD];
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 1;
}
int binsearch(char *word, struct key tab[], int n)
{
int cond;
int low, high,mid;
low = 0;
high = n -1;
while(low < high)
{
mid = (low + high)/2;
if((cond = strcmp(word,tab[mid].word)) < 0)
high = mid -1;
else if(cond > 0)
low = mid + 1;
else
return mid;
}
return -1;
}
int getword(char *word, int lim)
{
int c, getch();
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];
}
#define BUFSIZE 1000
int buf[BUFSIZE];
int bufp = 0;
int getch()
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("the stack of ungetch is full\n");
else
buf[bufp++] = c;
}
2. 上题中利用指向结构体的指针
mid = (low + high)/ 2 /* 错误 */ 两个指针之间的假发运算是非法的
mid = low + (high - low) / 2
&tab[-1] 和 &tab[n] : 前者是错误的,后者是正确的,后者和 tab + n 是等价的,这个地址是真是存在的,但是对地址指向操作和运算操作都是非法的。
mid = (low + high)/ 2 /* 错误 */ 两个指针之间的假发运算是非法的
mid = low + (high - low) / 2
&tab[-1] 和 &tab[n] : 前者是错误的,后者是正确的,后者和 tab + n 是等价的,这个地址是真是存在的,但是对地址指向操作和运算操作都是非法的。
int main()
{
struct key *p;
char word[MAXWORD];
while(getword(word,MAXWORD) != EOF)
{
if(isalpha(word[0]))
if((p = binsearch(word,keytab,NKEYS)) != NULL)
p->count++;
}
for(p = keytab; p < keytab + NKEYS; p++)
if(p->count> 0)
printf("%4d %s\n",p->count,p->word);
return 1;
}
struct key * binsearch(char *word, struct key tab[], int n)
{
int cond;
struct key *low, *high, *mid;
low = &tab[0];
high = &tab[n] -1;
while(low < high)
{
mid = low + (high - low)/2;
if((cond = strcmp(word,mid->word)) < 0)
high = mid -1;
else if(cond > 0)
low = mid + 1;
else
return mid;
}
return NULL;
}
3.统计单词出现的频率并俺字符顺序排序(6.5)
以下几个文件夹为常用函数文件夹:
以下几个文件夹为常用函数文件夹:
GetchAndUngetch.c
#define BUFSIZE 1000
int buf[BUFSIZE];
int bufp = 0;
int getch()
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c)
{
if(bufp >= BUFSIZE)
printf("the stack of ungetch is full\n");
else
buf[bufp++] = c;
}
TallocAndStrdup.c
#include<malloc.h>
struct tnode *talloc()
{
return (struct tnode *)malloc(sizeof(struct tnode));
}
char *strdp(char *s)
{
char *p;
p = (char *)malloc(strlen(s)+1);
if(p != NULL)
strcpy(p,s);
return p;
}
getword.c
int getword(char *word, int lim)
{
int c, getch();
void ungetch(int);
char *w = word;
//while((isspace(c = getch())) && c != '\n') //for 6-3.c
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];
}
主函数
#include<stdio.h>
#include<ctype.h>
#define MAXWORD 100
#define NDISTINCT 1000
struct tnode
{
char *word;
int count;
struct tnode *left;
struct tnode *right;
};
#include"GetchAndUngetch.c"
#include"TallocAndStrdup.c"
#include"getword.c"
struct tnode *addtree(struct tnode *p,char *p);
void treeprint(struct tnode *root);
int main()
{
struct tnode *root;
char word[MAXWORD];
int i;
root = NULL;
while(getword(word,MAXWORD) != EOF)
if(isalpha(word[0]))
root = addtree(root,word);
treeprint(root);
return 0;
}
struct tnode *addtree(struct tnode *p, char *w)
{
int cond;
if(p == NULL)
{
p = talloc();
p ->word = strdp(w);
p ->count = 1;
p ->left = p ->right = NULL;
}
else if((cond = strcmp(w,p->word)) < 0)
p ->left = addtree(p->left,w);
else if(cond > 0)
p ->right = addtree(p->right,w);
else
p->count++;
return p;
}
void treeprint(struct tnode *p)
{
if(p != NULL)
{
treeprint(p->left);
printf("%4d %s\n",p->count, p->word);
treeprint(p->right);
}
}
4. 读取变量,并按字母是顺序打印变量名字,要求每一组内各变量名前6个字符相同,其余字符不同,6作为一个可以在命令行设定的参数。(6-2)
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
struct tnode
{
char *word;
int match;
struct tnode *left;
struct tnode *right;
};
#define MAXWORD 100
#define YES 1
#define NO 0
#include"GetchAndUngetch.c"
#include"TallocAndStrdup.c"
#include"getword.c"
struct tnode *addtreex(struct tnode *, char *, int ,int *);
void treexprint(struct tnode*);
int main(int argc, char *argv[])
{
struct tnode *root;
char word[MAXWORD];
int found = NO;
int num;
num = (--argv && (*++argv)[0] == '-') ? atoi(argv[0]+1) :6;
root = NULL;
while(getword(word,MAXWORD) != EOF)
{
if(isalpha(word[0]) && strlen(word) >= num)
root = addtreex(root,word,num,&found);
found = NO;
}
treexprint(root);
return 1;
}
struct tnode *addtreex(struct tnode *p, char *w, int num, int *found)
{
int cond;
int compare(char* s, struct tnode *p, int num, int *found);
if(p == NULL)
{
p = talloc();
p ->word = strdp(w);
p ->match = *found;
p -> left = p -> right = NULL;
}
else if((cond = compare(w,p,num,found)) < 0)
p -> left = addtreex(p->left,w,num,found);
else if(cond > 0)
p -> right = addtreex(p->right,w,num,found);
return p;
}
int compare(char *s, struct tnode *p, int num, int *found)
{
int i;
char *t = p->word;
for(i = 0; *s == *t; i++,s++,t++)
if(*s == '\0')
return 0;
if(i >= num )
{
*found = YES;
p->match = YES;
}
return *s - *t;
}
void treexprint(struct tnode *p)
{
if(p != NULL)
{
treexprint(p->left);
if(p->match == YES)
printf("%s\n",p->word);
treexprint(p->right);
}
}
5.编写一个程序,根据单词出现的频率俺降序打印输入的各个不同单词,并在每个单词的前面标上它的出现次数。
#include<stdio.h>
#include<ctype.h>
#define MAXWORD 100
#define NDISTINCT 1000
struct tnode
{
char *word;
int count;
struct tnode *left;
struct tnode *right;
};
#include"GetchAndUngetch.c"
#include"TallocAndStrdup.c"
#include"getword.c"
struct tnode *addtree(struct tnode *, char *);
void sortlist();
void treestore(struct tnode *);
struct tnode *list[NDISTINCT];
int ntn = 0;
int main()
{
struct tnode *root;
char word[MAXWORD];
int i;
root = NULL;
while(getword(word,MAXWORD) != EOF)
if(isalpha(word[0]))
root = addtree(root,word);
treestore(root);
sortlist();
for(i = 0; i < ntn; i++)
printf("%2d:%20s\n", list[i]->count, list[i]->word);
return 0;
}
struct tnode *addtree(struct tnode *p, char *w)
{
int cond;
if(p == NULL)
{
p = talloc();
p ->word = strdp(w);
p ->count = 1;
p ->left = p ->right = NULL;
}
else if((cond = strcmp(w,p->word)) < 0)
p ->left = addtree(p->left,w);
else if(cond > 0)
p ->right = addtree(p->right,w);
else
p->count++;
return p;
}
void treestore(struct tnode *p)
{
if(p != NULL)
{
treestore(p->left);
if(ntn < NDISTINCT)
list[ntn++] = p;
treestore(p->right);
}
}
void sortlist()
{
int gap, i, j;
struct tnode *temp;
for(gap = ntn/2; gap > 0; gap /=2)
for(i = gap; i < ntn; i++)
for(j = i-gap; j >= 0; j-=gap)
{
if((list[j]->count) >= (list[j+gap]->count))
break;
temp = list[j];
list[j] = list[j+gap];
list[j+gap] = temp;
}
}
#include<stdio.h>
#include<string.h>
#include<malloc.h>
struct nlist
{
struct nlist *next;
char *name;
char *defn;
};
#define HASHSIZE 101
struct nlist *hashtab[HASHSIZE];
//hash函数:为字符串s生成散列值
unsigned hash(char *s)
{
unsigned hashval;
for(hashval = 0; *s != '\0'; s++)
hashval = *s + 31 * hashval;
return hashval % HASHSIZE;
}
// lookup函数:在hashtab中查找s
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;
}
// 将(name,defn)加入到hashtab中
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] = np;
}
else
free((void *)np->defn);
if((np->defn = strdup(defn)) == NULL)
return NULL;
return np;
}
// 将删除字符串s以及其定义
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);
}
}
}
void print()
{
int i;
for(i = 0; i < HASHSIZE; i++)
if(hashtab[i] != NULL)
{
struct nlist *temp = hashtab[i];
while(temp)
{
printf("%15s %5s\n",temp->name, temp->defn);
temp = temp ->next;
}
}
}
int main()
{
install("chenyiming","1");
install("huangyazhen","2");
install("xuyang","3");
install("wangchao","4");
install("zhengnan","5");
print();
return 1;
}
7.编写一个适合c语言程序使用的#define处理的简单版本(即无参数的情况)。(练习6-6)你会发现getch和ungetch函数非常有用。
#include<stdio.h>
#include<ctype.h>
#include<string.h>
#define MAXWORD 100
struct nlist
{
struct nlist *next;
char *name;
char *defn;
};
#include"getword.c"
#include"TallocAndStrdup.c"
#include"GetchAndUngetch.c"
void error(int, char *);
struct nlist *install(char *,char *);
struct nlist *lookup(char *);
void skipblanks();
void getdef();
void undef(char *);
int main()
{
char w[MAXWORD];
struct nlist *p;
while(getword(w,MAXWORD) != EOF)
{
if(strcmp(w,"#")== 0)
getdef();
else if(!isalpha(w[0]))
printf("%s",w);
else if((p = lookup(w)) == NULL)
printf("%s",w);
else
ungets(p->defn);
}
return 0;
}
void getdef()
{
void undef(char *);
int c, 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] = getch()) == EOF || def[i] =='\n')
break;
def[i] = '\0';
if(i <= 0)
error('\n',"getdef: incomplete define");
else
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 #");
}
void error(int c, char *s)
{
printf("error: %s\n",s);
while(c != EOF && c != '\n')
c = getch();
}
void skipblanks()
{
int c;
while((c = getch())== ' ' || c == '\t')
;
ungetch(c);
}
#define HASHSIZE 101
struct nlist *hashtab[HASHSIZE];
//hash函数:为字符串s生成散列值
unsigned hash(char *s)
{
unsigned hashval;
for(hashval = 0; *s != '\0'; s++)
hashval = *s + 31 * hashval;
return hashval % HASHSIZE;
}
// lookup函数:在hashtab中查找s
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;
}
// 将(name,defn)加入到hashtab中
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] = np;
}
else
free((void *)np->defn);
if((np->defn = strdup(defn)) == NULL)
return NULL;
return np;
}
// 将删除字符串s以及其定义
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);
}
}
}