//#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define MAXWORD 100 //关键字最大的个数
struct key //结构体数组,关键字按顺序排列
{
char *word;
int count;
} keytab[] = {
"auto", 0,
"break", 0,
"case", 0,
"char", 0,
"const", 0,
"continue", 0,
"default", 0,
/* ... */
"unsigned", 0,
"void", 0,
"volatile", 0,
"while", 0
};
//关键字的个数等于数组的长度除以单个元素的长度
#define NKEYS (sizeof keytab / sizeof(struct key))
int getword(char *, int); //从输入中读取下一个字符或单词
int binsearch(char *, struct key *, int); //在tab[0]到tab[n-1]中查找单词
int main(void)
{
int n;
char word[MAXWORD];
while(getword(word, MAXWORD) != EOF)
{
if (isalpha(word[0])) //word的第一个单词为字母
if ((n = binsearch(word, keytab, NKEYS)) >= 0)
keytab[n].count++; //在结构体中查找成功,关键字计数加1
}
//统计结束,打印结果
for (n = 0; n < NKEYS; n++)
{
if (keytab[n].count > 0)
printf("%4d %s\n",keytab[n].count, keytab[n].word);
}
return 0;
}
/* binsearch: find word in tab[0]...tab[n-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;
}
/*getword从输入中读取下一个单词是以字母开头的字母和数字串,
也可以是以字母开头的字母和数字串,也可以是一个非空白字符串。
函数返回值可能是单词的第一个字符、文件结束符EOF或字符本身(如果该字符不是字母字符本身)*/
int getword(char *word, int lim)
{
int c, getch(void);
void ungetch(int);
char *w = word;
while (isspace(c = getch())) //c跳过空白符
;
if (c != EOF)
*w++ = c;
if (!isalpha(c)) //c不是字母
{
*w = '\0';
return c;
}
for ( ; --lim > 0; w++)
{
if (!isalnum(*w = getch())) //输入不是字母或数字时,该单词结束
{
ungetch(*w);
break;
}
}
*w = '\0'; //字符串结束符'\0'
return word[0]; //返回值是单词的第一个字符
}
#define BUFSIZE 100 //缓冲区的大小
char buf[BUFSIZE]; //用于ungetchar函数的缓冲区
int bufp = 0; //buf中下一个空闲位置
//读取一个字符(可能是压回的字符)
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
//把字符压回到输入中
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}