C语言实现英文文本词频统计

这几天写了一个基于C语言对文本词频进行统计的程序,开发及调试环境:mac集成开发环境Xcode;测试文本,马丁.路德金的《I have a dream》原文演讲稿。
主要运行步骤:
1. 打开文本把文本内容读入流中并且开辟相应空间放入内存
2 .对文本内容进行处理,去除大写字母(转化为小写),去除特殊字符
3. 基于单链表对词频进行统计
4. 把统计结果进行归并排序
5.打印输出全部词频或者频率最高的10个单词和其出现次数
6.释放所有结点消耗的内存
废话不多说,上代码!

//
//  main.c
//  word_frequency_statistic
//
//  Created by tianling on 14-3-16.
//  Copyright (c) 2014年 tianling. All rights reserved.
//  实现英文文本的词频统计
//

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

#define ERROR 1
#define OK 0
const int WORD_LENGTH = 250;//定义单个单词最大长度
typedef int status;


/*
 **定义存储单词及其出现次数的结构体
 */
typedef struct Node{
    char word[WORD_LENGTH];
    int time;
    struct Node *next;
}wordNode;

wordNode *headNode = NULL;//定义链表头指针

/*
 **函数声明
 */
wordNode *wordSearch(char *word,int *num);
status wordCount(char *word,int *num);
void printCountList(int *num);
void PrintFirstTenTimes();
void mergeSort(wordNode **head);
void FrontBackSplit(wordNode *head,wordNode **pre,wordNode **next);
void wordJob(char word[]);
wordNode *SortedMerge(wordNode *pre,wordNode *next);
void release();

status main(int argc,char *argv[])
{
    char temp[WORD_LENGTH];//定义用以临时存放单词的数组
    FILE *file;
    int count,articleWordNum = 0;//定义统计结点个数的变量
    int *num = &articleWordNum,choose;
    
    /*
     **读取文件
     */
    if((file = fopen("/Users/tianling/Documents/Data_Structure/word_frequency_statistic/word_frequency_statistic/article.txt", "r")) == NULL){
        //这里是绝对路径,基于XCode编译器查找方便的需求
        printf("文件读取失败!");
        exit(1);
    }
    
    while((fscanf(file,"%s",temp))!= EOF){
        wordJob(temp);
        count = wordCount(temp,num);
    }
    
    fclose(file);//关闭文件
    
    printCountList(num);
    
    printf("***********请选择***********\n");
    printf("*****1. 输出词频最高的10个词**\n");
    printf("*****2. 退出****************\n");
    
    scanf("%d",&choose);
    if(choose == 1){
        mergeSort(&headNode);
        PrintFirstTenTimes();

    }else{
        release();
        exit(0);
    }
    
    release();
    return 0;
    
    
}

/*
 **查找单词所在结点
 */
wordNode *wordSearch(char *word,int *num){
    wordNode *node;//声明一个新结点
    
    if(headNode == NULL){//若头结点为空
        node = (wordNode*)malloc(sizeof(wordNode));
        strcpy(node->word, word);//将第一个单词赋值给这个新结点
        node->time = 0;//初始化该单词的出现次数
        *num+=1;
        headNode = node;//将头结点指向这个新结点
        return node;
        
    }
    
    wordNode *nextNode = headNode;
    wordNode *preNode = NULL;
    
    while(nextNode != NULL && strcmp(nextNode->word, word) != 0){
        preNode = nextNode;
        nextNode = nextNode->next;
    }
    
    //若该单词不存在,则在链表中生成新结点
    if(nextNode == NULL){
        node = (wordNode*)malloc(sizeof(wordNode));
        strcpy(node->word, word);
        node->time = 0;
        node->next = headNode->next;
        headNode->next = node;
        *num+=1;
        
        return node;
    }else
        return nextNode;
    
}


/*
 **词频统计
 */
status wordCount(char *word,int *num){
    wordNode *tmpNode = NULL;
    tmpNode = wordSearch(word,num);
    
    if(tmpNode == NULL){
        return ERROR;
    }
    
    tmpNode->time++;
    
    return 0;
}


/*
 **打印所有词频
 */
void printCountList(int *num){
    if(headNode == NULL){
        printf("该文件无内容!");
        
    }else{
        wordNode *preNode = headNode;
        printf("总词量 %d \n",*num);
        
        while(preNode != NULL){
            printf("%s 出现次数 %d\n",preNode->word,preNode->time);
            preNode = preNode->next;
        }
    }
    
}


/*
 **打印词频最高的10个词
 */
void PrintFirstTenTimes(){
    if(headNode == NULL){
        printf("该文件无内容!");
        
    }else{
        wordNode *preNode = headNode;
        int i = 0;
        printf("出现次数最多的10个词如下: \n");
        
        while (preNode != NULL && i<=10) {
            printf("%s 出现次数 %d\n",preNode->word,preNode->time);
            preNode = preNode->next;
            i++;

        }
    }
}


/*
 **对词频统计结果进行归并排序
 */
void mergeSort(wordNode **headnode){
    wordNode *pre,*next,*head;
    head = *headnode;
    
    //若链表长度为0或1则停止排序
    if(head == NULL || head->next == NULL){
        return;
    }
    
    FrontBackSplit(head,&pre,&next);
    
    mergeSort(&pre);
    mergeSort(&next);
    
    *headnode = SortedMerge(pre,next);
    
}


/*
 **将链表进行分组
 */
void FrontBackSplit(wordNode *source,wordNode **pre,wordNode **next){
    wordNode *fast;
    wordNode *slow;
    
    if(source == NULL || source->next == NULL){
        *pre = source;
        *next = NULL;
    }else{
        slow = source;
        fast = source->next;
        
        while(fast != NULL){
            fast = fast->next;
            
            if(fast != NULL){
                slow = slow->next;
                fast = fast->next;
            }
        }
        *pre = source;
        *next = slow->next;
        slow->next = NULL;
    }
}


/*
 **根据排序结果更换头结点
 */
wordNode *SortedMerge(wordNode *pre,wordNode *next){
    wordNode *result = NULL;
    
    if(pre == NULL)
        return next;
    else if(next == NULL)
        return pre;
    
    if(pre->time >= next->time){
        result = pre;
        result->next = SortedMerge(pre->next,next);
        
    }else{
        result = next;
        result->next = SortedMerge(pre,next->next);
    }
    return result;
}


/*
 **处理大写字母及特殊字符
 */
void wordJob(char word[]){
    int i,k;
    char *specialChar = ",.;:'?!><+=|*&^%$#@\"";//定义特殊字符集
    
    for(i = 0;i<strlen(word);i++){
        //筛选并将字符串中的大写字母转化为小写字母
        if(word[i]>='A'&& word[i]<='Z'){
            word[i] += 32;
        }
        //筛选并去除字符串中的特殊字符
        for(k = 0;k<strlen(specialChar);k++){
            
            if(word[i] == specialChar[k]){
                
                while(i<strlen(word)){
                    word[i] = word[i+1];
                    i++;
                }
               
            }
        }
    }
    
}


/*
 **释放所有结点内存
 */
void release(){
    if(headNode == NULL)
        return;
    
    wordNode *pre = headNode;
    while(pre != NULL){
        headNode = pre->next;
        free(pre);
        pre = headNode;
        
    }
}

调试结果:(Xcode环境)




  • 16
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值