⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyword.c

📁 统计 C 语言源程序里标识符的个数及相应标识符出现次数的程序
💻 C
字号:
//---------------------------------------------------------------------------
/* 统计 C 语言源程序里标识符的个数及相应标识符出现次数的程序 */
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused

#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>
#include <string.h>


#define KEYWORDMAXLENGTH     32
#define KEYWORDTABLELENGTH   32

#undef getchar
#undef isalnum
#undef isalpha

typedef struct _KeywordTable {
    char *key;
    int count;
}KeywordTable;

KeywordTable keywordTable[KEYWORDTABLELENGTH] = {
    "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};

int getword(char *word,int limit,int handle);
int _isalnum(char ch);
int _isalpha(char ch);
int _getchar(int handle);
KeywordTable *binsearch(KeywordTable *pkeywordTable, char *keyWord, int keywordTableLength);
void format(int space);

int main(int argc, char *argv[])
{
        char keyWord[KEYWORDMAXLENGTH + 1];
        KeywordTable *found;
        int handle;
        if(argc != 2) {
            fprintf(stderr,"请在命令行中指定一个 C 语言源程序文件。\n");
            exit(1);
        }
        else  if ((handle = open(*(++argv), O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1) {
            fprintf(stderr,"打开指定的文件 %s 时出现错误。\n",*argv);
            exit(2);
        }
        while(getword(keyWord, KEYWORDMAXLENGTH + 1, handle) > 0) /* 只有这样改一下,在getword函数中的循环while(len<limit)因为len==limit结束时,word[len] = '\0'才不会产生越界防问的嫌疑. */
            if((found = binsearch(keywordTable, keyWord, KEYWORDTABLELENGTH)) != NULL)
                found->count++;
        close(handle);
        for(found = keywordTable; found < keywordTable + KEYWORDTABLELENGTH; found++) {
            printf("%10s: %5d\n",found->key,found->count);
            //format(0);
        }
        getch();
        return 0;
}
int getword(char *word,int limit,int handle) {
/* 这个 getword 函数没有考虑预处理宏的影响;考虑了注释和字符串常量。
 * 在处理过程中,函数会把预处理宏当作正常的程序代码对待,同时,函数
 * 也会掠过空白类字符(比如空格、换行符、横向制表符等)、注释和字符
 * 串常量
 * */
     static int priorch,ch = ' ';
     int len = 0;

     while(ch != EOF && !_isalpha(ch)) {
         if(isspace(ch)){  /* 掠过空白类字符 */
             while(isspace(ch))
                 ch = _getchar(handle);
             continue;
         }
         else if(ch == '/') {  /* 掠过注释 */
                  if((ch = _getchar(handle)) == '*') {
                      while(priorch = ch,(ch = _getchar(handle)) != EOF && (priorch != '*' || ch != '/'));
                      ch = _getchar(handle);
                      continue;
                  }
                  continue;
              }
         else if(ch == '\"') { /* 掠过字符串常量 */
                  while((ch = _getchar(handle)) != EOF) {
                      if(ch == '\\') {
                          ch = _getchar(handle);
                          continue;
                      }
                      else if(ch == '\"')
                          break;

                  }
                  ch = _getchar(handle);
                  continue;
              }
         ch = _getchar(handle);
     }
     if(ch == EOF)
         return len;
     word[len++] = ch; /* 标识符的第一个字符是字母 */
     while(len < limit - 1 && _isalnum(ch = _getchar(handle)))/* word里面最多放limit个字符,也就是(KEYWORDMAXLENGTH + 1)个字符. */
        word[len++] = ch;
     word[len] = '\0';
     //printf("%s ",word);
     return len;
}/* iint getword(char *word,int limit,int *handle) */

int _isalpha(char ch) {
/* 如果一个字符是字母返回 1 否则返回 0 */

    return ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == '_';
}/* int _isalpha(char ch) */
int _isalnum(char ch) {
/* 如果一个字符是数字字符或者字母返回 1 否则返回 0 */

    return _isalpha(ch) || ch >= '0' && ch <= '9';
}/* int _isalnum(char ch) */
int _getchar(int handle) {
/* 带有预读缓冲区的 _getchar */
    static char buffer[1024];
    static char *bufp;
    static int n;

    if(n == 0) { /* 预读缓冲区是空的 */
        //n = read(handle,buffer,sizeof(buffer));
        n = read(handle,buffer,1024);
        bufp = buffer;
    }
    return (--n >= 0) ? (unsigned char) *bufp++ : (n = 0,EOF);
}/* int _getchar(int *handle) */
KeywordTable *binsearch(KeywordTable *pkeywordTable, char *keyWord, int keywordTableLength) {
/* 使用二分查找法查找一个单词是不是出现在指定的关键词表中 */
    KeywordTable *low  = pkeywordTable;
    KeywordTable *high = pkeywordTable + keywordTableLength;
    KeywordTable *middle;
    int cond;

    while(low < high) {
        middle = low + (high - low) / 2;
        if((cond = strcmp(keyWord, middle->key)) < 0)
            high = middle;
        else if(cond > 0)
            low = middle + 1;
        else
            return middle;
    }
    return NULL;
}/* KeywordTable *binsearch(KeywordTable *pkeywordTable, char *keyWord, int keywordTableLength) */
void format(int space) {
/* 这个函数以每 (space + 1)次调用形成一个周期,其中的前 space 次每次调用输出一个空格,第
 * (space + 1)次调用输出一个换行符
 * */
     static char count;
     ++count <= space ? putchar(' ') : (count = 0, putchar('\n'));
}/* void format(void) */

//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -