演習6-1 K&R プログラミング言語C
2010年02月24日
演習6-1
コメント、文字列リテラル内を無視するために skip_char
関数を定義して処理する。
現在の状態をセットして、コメント、文字列リテラル内では文字の取得をスキップする。
#include <stdio.h> #include <ctype.h> #include <string.h> #define MAXWORD 100 #define BUFSIZE 100 #define NKEYS (sizeof keytab / sizeof keytab[0]) char buf[BUFSIZE]; /* ungetch 用のバッファ */ int bufp = 0; /* buf 中の次の空き位置 */ int getword(char *, int); int skip_char(void); enum boolean { FALSE, TRUE }; enum skipping_state { COMMENT_START, IN_COMMENT, COMMENT_END, IN_STR_C, OTHER }; struct key { char *word; int count; } keytab[] = { { "#define", 0}, { "#include", 0}, { "auto", 0 }, { "break", 0 }, { "case", 0 }, { "char", 0 }, { "const", 0 }, { "continue", 0 }, { "default", 0 }, { "double", 0}, { "int", 0 }, /* ... */ { "return", 0 }, { "size_t", 0 }, { "unsigned", 0 }, { "void", 0 }, { "volatile", 0 }, { "while", 0 } }; /* C のキーワードを数える */ int main(void) { int n; char word[MAXWORD]; int binsearch(char *, struct key *, int); while (getword(word, MAXWORD) != EOF) { if (isalpha(word[0]) || 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 : 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 skip_char(void) { int c, getch(void); int escaped = FALSE; void ungetch(int); int type = OTHER; while ((c = getch()) != EOF) { switch (c) { case '/': if (type == OTHER) { type = COMMENT_START; } else if (type == COMMENT_END) { type = OTHER; } escaped = FALSE; break; case '*': if (type == COMMENT_START) { type = IN_COMMENT; } else if (type == IN_COMMENT) { type = COMMENT_END; } escaped = FALSE; break; case '"': if (!escaped) { if (type == OTHER) { type = IN_STR_C; } else if (type == IN_STR_C) { type = OTHER; } } escaped = FALSE; break; case '\\': if (type == IN_STR_C) { escaped = TRUE; } break; default: escaped = FALSE; break; } if (!isspace(c) && type == OTHER) { return c; } } return c; } /* getword : 入力から次の語または文字を求める */ int getword(char *word, int lim) { int c, getch(void); void ungetch(int); char *w = word; c = skip_char(); if (c != EOF) { *w++ = c; } if (c != '#' && !isalpha(c)) { *w = '\0'; return c; } for ( ; --lim > 0; w++) { if (!isalnum(*w = getch()) && *w != '_') { ungetch(*w); break; } } *w = '\0'; return word[0]; } int getch(void) /* (押し戻された可能性もある) 1文字をとってくる */ { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) /* 文字を入力に押し戻す */ { if (bufp > BUFSIZE) fprintf(stderr, "ungetch : too many characters\n"); else buf[bufp++] = c; }
実行結果
$ cat sample.c #include <stdio.h> #include <stdlib.h> #define MAX 100 int main(void) { int i = 0; size_t n = MAX; /* int j = 0; */ printf("\"int\" i is %d\n", i); /* printf("int j is %d\n", j); */ printf("\"size_t\" n is %d\n", n); /*printf("\"size_t\" n is %d\n", n); */ return 0; } $ ./word_count <sample.c 1 #define 2 #include 2 int 1 return 1 size_t 1 void
プログラミング言語C 第2版 ANSI規格準拠
posted with amazlet at 09.11.27
B.W. カーニハン D.M. リッチー
共立出版
売り上げランキング: 9726
共立出版
売り上げランキング: 9726