/* EXERCISE 6-1 */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
struct key {
char *word;
int count;
};
struct key keytab[] = {
"auto", 0,
"break", 0,
"case", 0,
"char", 0,
"const", 0,
"continue", 0,
"default", 0,
"do", 0,
"double", 0,
"else", 0,
"enum", 0,
"extern", 0,
"float", 0,
"for", 0,
"goto", 0,
"if", 0,
"int", 0,
"long", 0,
"register", 0,
"return", 0,
"short", 0,
"signed", 0,
"sizeof", 0,
"static", 0,
"struct", 0,
"switch", 0,
"typedef", 0,
"union", 0,
"unsigned", 0,
"void", 0,
"volatile", 0,
"while", 0
};
#define MAXWORD 100
#define NKEYS (sizeof keytab / sizeof keytab[0])
int getword(char *, int);
int binsearch(char *, struct key *, int);
/* COUNT C KEYWORDS */
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 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;
}
int getch(void);
void ungetch(int);
/* GETWORD: GET NEXT WORD OR CHARACTER FROM INPUT */
int getword(char *word, int lim)
{
int c;
char *w = word;
int skiprtn(int);
while (isspace(c = getch())) /* SKIP BLANKS */
;
if (c == '/' || c == '\"' || c == '\'' || c == '#')
c = skiprtn(c);
if (c == EOF) {
*w = '\0';
return c;
}
*w++ = c;
if (isalpha(c) || c == '_') /* UNDERSCORE */
for ( ; --lim > 0; w++)
if (!isalnum(*w = getch()) && *w != '_') {
ungetch(*w);
break;
}
*w = '\0';
return word[0];
}
/* SKIPRTN: SKIP MULTIPLE CONSECUTIVE OCCURRENCES OF STRING CONSTS, */
/* COMMENT STRINGS AND PREPROCESSOR CONTROL LINES. */
/* RETURN THE NEXT CHARACTER ENCOUNTERED. */
int skiprtn(int c)
{
for (;;) {
if (c == '/') { /* SKIP COMMENTS */
if ((c = getch()) != '*') {
ungetch(c);
return '/';
}
while ((c = getch()) != EOF)
if (c == '*' && ((c = getch()) == '/' || c == EOF))
break;
}
else
if (c == '\"') /* SKIP STRING CONSTANTS */
while ((c = getch()) != EOF) {
if (c == '\"')
break;
if (c == '\\') /* SKIP ESCAPE SEQUENCE \" */
if ((c = getch()) == EOF)
break;
}
else
if (c == '\'') /* SKIP CHARACTER CONSTANTS */
while ((c = getch()) != EOF) {
if (c == '\'')
break;
if (c == '\\') /* SKIP ESCAPE SEQUENCE \' */
if ((c = getch()) == EOF)
break;
}
else
if (c == '#') /* SKIP # LINES */
while ((c = getch()) != '\n' && c != EOF)
;
else /* CAPTURE THE CHARACTER AFTER */
return c; /* THE LAST OCCURRENCE */
if (c == EOF)
return c;
while (isspace((c = getch())))
;
}
}
#define BUFSIZE 100
char buf[BUFSIZE]; /* BUFFER FOR ungetch */
int bufp = 0; /* NEXT FREE POSITION IN buf */
/* GETCH: GET A (POSSIBLY PUSHED BACK) CHARACTER */
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
/* UNGETCH: PUSH CHARACTER BACK ON INPUT */
void ungetch(int c)
{
if (bufp >= BUFSIZE)
printf("UNGETCH: TOO MANY CHARACTERS\n");
else
buf[bufp++] = c;
}