/* 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; }