分析一个文本文件(英文文章)中各个词出现的频率,并且把频率最高的10个词打印出来

  第一次这样交作业,好不习惯,废话不多说,上代码及整个分析编写过程。
  这次的程序大约花费了不到4个小时(2课时+一晚上),整体的设计思想是分三部分:从文件读入并分析收集单词,统计单词的频率,排序输出。下面是具体实现过程:
  1.   建立一个哈希表结构体Hash_table和一个单词缓存区buffer并分别对其做初始化
    typedef struct Hash{ 
        int count; 
        char str[20];     
    }Hash_table;
 初始化:
void initial_buffer ()
{
    for (tail_prob = 0; tail_prob < MAXWORD ;tail_prob++)
    {
        buffer[tail_prob++] = '';
    }
    tail_prob = 0;
}

void initial_hashtable ()
{while (i < hashnum)
    {
        hash_table[i].count = 0;
        i++;
    }
}
  
2. 统计文件中单词出现的频率,将单词及其频率存储在哈希表中

  

void find_frquence(FILE *in,FILE *out)
{do
    {
        if (character >0x20 && character < 0x80)
        {
            if (flag==1)
            {
                copytobuffer (character);
            }
            else //新单词,且是字母和数字的组合*/ 
            {
                if(find_match())
         { }
          else { addtoHash (); Hcount++; } copytobuffer (character); flag = !flag; } } else { if (character <= 0x20 || character >= 0x80) { if (flag) { buffer[tail_prob] = '/0'; if (find_match) /*如果能够找到,则对应的频率加1,find_match实现频率加1*/ { } else /*不能找到,则到哈希表中*/ { addtoHash (); Hcount++; } copytobuffer (character); flag = !flag; } else { copytobuffer (character); } } } }while ((character = fgetc (in)) != EOF); /*处理最后缓冲区所存储的单词*/ if(find_match()) { } else { addtoHash(); Hcount++; } }

 3.使用除留余数法查询哈希表中的单词,若存在则频率+1

int find_match ()
{while (hash_table[index].count)
    {
        if (len1 == len2)     //些比较len1和len2是否相等,如果不等再比较
        {
            for (i = 0;i<len1 && *str == *temp;i++)
            {
                str++;
                temp++;
            }
            if (i != len2)
            {
                index = (index + 1) % hashnum;
                temp = hash_table[index].str;
                str = buffer;
                return -1;
            }
            else   //能找到
            {
                hash_table[index].count++;
                return TURE;
            }
        }
        else
        {
            index = (index + 1) % hashnum;
            temp = hash_table[index].str;
            str = buffer;
            return -1;
        }
    }
}

4.排序后输出到一个文件中,也可输出在屏幕上

void Hash_sort(FILE *out)
{
    while (i < Hcount)  
    {
        /*找到第一个遇见的频率非零的结点*/
        while (hash_table[index].count == 0)
        {
            index ++;
        }
        symbol = hash_table[index].count;  /*充当最大值*/
        num = index;
        index++;
        while (index < hashnum)
        {
            if (symbol < hash_table[index].count && hash_table[index].count)
            {
                symbol = hash_table[index].count;
                num = index;
            }
            index ++;
        }
        len = strlen (hash_table[num].str);
        //printf("%d	",hash_table[num].count);
        //printf("%s
",hash_table[num].str);
        fprintf(out,"%s,%d
",hash_table[num].str,hash_table[num].count);
        hash_table[num].count = 0;
        i++;
        index = 0;
    }  
}

5.源代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define  FOOL     int
#define  TURE      1
#define  FALSE     0
#define  MAXWORD   20
#define  hashnum  1024

/*采用哈希表结点结构*/
typedef struct Hash{ 
    int count; 
    char str[20];     /*不一定为1,而是动态分配*/
}Hash_table;

Hash_table hash_table[hashnum];

char buffer[256];     /*缓冲区大小,用来暂时存储单词*/
int tail_prob;              /*缓冲区结束位指针 */
int Hcount = 0;                   /*用来计算有多少单词*/

/******************************************************************/
/**                      初始化操作                              **/
/**                                                              **/
void initial_buffer ()
{
    for (tail_prob = 0; tail_prob < MAXWORD ;tail_prob++)
    {
        buffer[tail_prob++] = '';
    }
    tail_prob = 0;
}

void initial_hashtable ()
{
    unsigned int i;
    i = 0; 
    while (i < hashnum)
    {
        hash_table[i].count = 0;
        i++;
    }
}
/******************************************************************/  
/**    关于缓冲区的操作                                          **/ 
/**                                                              **/

/*把一个字符拷贝到缓存区中*/
void copytobuffer (char character)
{    
    if (tail_prob >= MAXWORD)
    {
        printf("Usag:this word is too long!");
        exit (-1);
    }
    buffer[tail_prob++] = character;
}

/*清除缓冲区*/
void clear_buffer ()
{
    while (tail_prob != 0)
    {
        buffer[--tail_prob] = '';
    }
}

/**************************************************************/
/** 找哈希表的关键字,这里使用的是把字符串的值相加再求与哈希表**/
/**长度的余                                                  **/  
unsigned int get_key (char *str)
{
    unsigned result = 0;
    do
    {
        result = result + (*str);
        str++;
    }while (*str != NULL);
    result = result % hashnum;
    return result;
}

/***************************************************************/
/**看哈希表中是否有对应的单词,有返回真                       **/
/**                                                           **/
int find_match ()
{
    int i;
    char *str;
    char *temp;
    int len1;          /*缓冲区中单词的长度*/
    int len2;          /*哈希表中单词的长度*/
    int index;

    str = buffer;
    index = get_key (buffer);
    temp = hash_table[index].str;
    len1 = strlen (buffer);
    len2 = strlen (temp);

    while (hash_table[index].count)
    {
        if (len1 == len2)     /*些比较len1和len2是否相等,如果不等再比较*/
        {
            for (i = 0;i<len1 && *str == *temp;i++)
            {
                str++;
                temp++;
            }
            if (i != len2)
            {
                index = (index + 1) % hashnum;
                temp = hash_table[index].str;
                str = buffer;
                return -1;
            }
            else   //能找到
            {
                hash_table[index].count++;
                return TURE;
            }
        }
        else
        {
            index = (index + 1) % hashnum;
            temp = hash_table[index].str;
            str = buffer;
            return -1;
        }
    }
}

/***************************************************************/
/** 根据缓冲区里面的字符生成哈希表                            **/
/**                                                           **/
void addtoHash()
{
    char str_temp[256];
    char *str;
    char *temp;
    int len;
    unsigned int index;
    int i;

    i=0;
    str = str_temp;
    strcpy (str,buffer);
    index = get_key (str);
    len = strlen(str);
    temp = hash_table[index].str;

    while (hash_table[index].count)  /*找到没有被储存的结点*/
    {
        index = (index + 1) % hashnum;
    }
    hash_table[index].count++;
    while (i < len)  /*复制字符串*/
    {
        *temp++ = *str++;
        i++;
    }
}

/***************************************************************/
/**                 排序后输出到out文件中                     **/
/**                                                           **/
void Hash_sort(FILE *out)
{
    int index;
    unsigned int symbol; /*最大值*/
    int num;
    int len;
    int i = 0;
    index = 0;
    /*排序输出到out文件中,共有Hcount个单词*/ 
    while (i < Hcount)  
    {
        /*找到第一个遇见的频率非零的结点*/
        while (hash_table[index].count == 0)
        {
            index ++;
        }
        symbol = hash_table[index].count;  /*充当最大值*/
        num = index;
        index++;
        while (index < hashnum)
        {
            if (symbol < hash_table[index].count && hash_table[index].count)
            {
                symbol = hash_table[index].count;
                num = index;
            }
            index ++;
        }
        len = strlen (hash_table[num].str);
        //printf("%d	",hash_table[num].count);
        //printf("%s
",hash_table[num].str);
        fprintf(out,"%s,%d
",hash_table[num].str,hash_table[num].count);
        hash_table[num].count = 0;
        i++;
        index = 0;
    }  
}


/*****************************************************************
/*找文件in中单词出现的频率,存储其单词以及其频率,调用find_match*/
/*输入的字符小于等于Ox20或者大于0x80时说明不是数字或者字母。但是*/
/*也能组成一个单词                                              */
void find_frquence(FILE *in,FILE *out)
{
    char character;
    FOOL flag;
    flag = 1; /*开关语句*/
    initial_buffer();
    initial_hashtable ();
    /*当没有到文件结束时*/
    character = fgetc (in);
    do
    {
        if (character >0x20 && character < 0x80)
        {
            if (flag)
            {
                copytobuffer (character);
                //find_match();
            }
            else /*新单词,且是字母和数字的组合*/ 
            {
                buffer[tail_prob] = '';/*表示结束*/
                if(find_match ())  /*如果能够找到,相对应的频率加1*/
                {
                    //Tprob->count++;
                }
                else             /*不能找到,则生成一个新的结点加入孩子兄弟链表中*/
                {
                    addtoHash ();
                    Hcount++;
                }
                clear_buffer ();   
                copytobuffer (character);
                flag = !flag;
            }
        }
        else
        {
            if (character <= 0x20 || character >= 0x80)
            {
                if (flag)
                {
                    buffer[tail_prob] = '/0';
                    if (find_match ())   /*如果能够找到,则对应的频率加1,find_match实现频率加1*/
                    {
                        //      Tprob->count++;
                    }
                    else                 /*不能找到,则到哈希表中*/
                    {
                        addtoHash ();
                        Hcount++;
                    }
                    clear_buffer ();   /*清除缓冲区*/
                    copytobuffer (character);
                    flag = !flag;
                }
                else
                {
                    copytobuffer (character);
                }
            }
        }// if - else 结束 
    }while ((character = fgetc (in)) != EOF);

    /*处理最后缓冲区所存储的单词*/
    if(find_match())
    {
        //  Tprob->count++;
    }
    else
    {
        addtoHash();
        Hcount++;
    }

    /*排序并按从小到大输出到out文件中*/
    Hash_sort(out);
}


/**************************************************************/

void main(int argc,char *argv[])
{
    FILE *in;
    FILE *out;
    char temp_string1[256];
    char temp_string2[256];
    if((in=fopen("temp_string1.txt","r"))==NULL)
    {  
        printf("Please input the file you want to compile:
");    
        exit(0);
    }
    in=fopen("temp_string1.txt","r");

    //in = fopen (temp_string1,"r");
    out = fopen ("temp_string2.txt","w");

    /*找到各个单词,并且存储其频率,按频率顺序排列后输出到out中*/
    find_frquence (in,out);
   fclose(in); fclose(out);
}

6.总结

  说实话,自己学的真的很渣,在有了大体思想后就开始从网上各种收集资料,但在编写的过程中还是遇到了很多问题,编译各种不通过,最后在多处求教同学和查资料后,得到了解决。这次的作业体会最深的一点就是,什么事都得靠自己去完成(因为不能类同了)!在这次的作业中,也对fgetc有了很深的了解,同时了解到了字符在16进制中的表示,还有一点就是,对哈希表又重新温习了一次。继续努力学习,望鼓励支持,哈哈

原文地址:https://www.cnblogs.com/caojinfeng/p/3579293.html