C語言實現(xiàn)英文文本詞頻統(tǒng)計
這幾天寫了一個基于C語言對文本詞頻進(jìn)行統(tǒng)計的程序,開發(fā)及調(diào)試環(huán)境:mac集成開發(fā)環(huán)境Xcode;測試文本,馬丁.路德金的《I have a dream》原文演講稿。
主要運(yùn)行步驟:
1. 打開文本把文本內(nèi)容讀入流中并且開辟相應(yīng)空間放入內(nèi)存
2 .對文本內(nèi)容進(jìn)行處理,去除大寫字母(轉(zhuǎn)化為小寫),去除特殊字符
3. 基于單鏈表對詞頻進(jìn)行統(tǒng)計
4. 把統(tǒng)計結(jié)果進(jìn)行歸并排序
5.打印輸出全部詞頻或者頻率最高的10個單詞和其出現(xiàn)次數(shù)
6.釋放所有結(jié)點消耗的內(nèi)存
廢話不多說,上代碼!
// // main.c // word_frequency_statistic // // Created by tianling on 14-3-16. // Copyright (c) 2014年 tianling. All rights reserved. // 實現(xiàn)英文文本的詞頻統(tǒng)計 // #include <stdio.h> #include <stdlib.h> #include <string.h> #define ERROR 1 #define OK 0 const int WORD_LENGTH = 250;//定義單個單詞最大長度 typedef int status; /* **定義存儲單詞及其出現(xiàn)次數(shù)的結(jié)構(gòu)體 */ typedef struct Node{ char word[WORD_LENGTH]; int time; struct Node *next; }wordNode; wordNode *headNode = NULL;//定義鏈表頭指針 /* **函數(shù)聲明 */ 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];//定義用以臨時存放單詞的數(shù)組 FILE *file; int count,articleWordNum = 0;//定義統(tǒng)計結(jié)點個數(shù)的變量 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);//關(guān)閉文件 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; } /* **查找單詞所在結(jié)點 */ wordNode *wordSearch(char *word,int *num){ wordNode *node;//聲明一個新結(jié)點 if(headNode == NULL){//若頭結(jié)點為空 node = (wordNode*)malloc(sizeof(wordNode)); strcpy(node->word, word);//將第一個單詞賦值給這個新結(jié)點 node->time = 0;//初始化該單詞的出現(xiàn)次數(shù) *num+=1; headNode = node;//將頭結(jié)點指向這個新結(jié)點 return node; } wordNode *nextNode = headNode; wordNode *preNode = NULL; while(nextNode != NULL && strcmp(nextNode->word, word) != 0){ preNode = nextNode; nextNode = nextNode->next; } //若該單詞不存在,則在鏈表中生成新結(jié)點 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; } /* **詞頻統(tǒng)計 */ 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("該文件無內(nèi)容!"); }else{ wordNode *preNode = headNode; printf("總詞量 %d \n",*num); while(preNode != NULL){ printf("%s 出現(xiàn)次數(shù) %d\n",preNode->word,preNode->time); preNode = preNode->next; } } } /* **打印詞頻最高的10個詞 */ void PrintFirstTenTimes(){ if(headNode == NULL){ printf("該文件無內(nèi)容!"); }else{ wordNode *preNode = headNode; int i = 0; printf("出現(xiàn)次數(shù)最多的10個詞如下: \n"); while (preNode != NULL && i<=10) { printf("%s 出現(xiàn)次數(shù) %d\n",preNode->word,preNode->time); preNode = preNode->next; i++; } } } /* **對詞頻統(tǒng)計結(jié)果進(jìn)行歸并排序 */ 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); } /* **將鏈表進(jìn)行分組 */ 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; } } /* **根據(jù)排序結(jié)果更換頭結(jié)點 */ 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++){ //篩選并將字符串中的大寫字母轉(zhuǎn)化為小寫字母 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++; } } } } } /* **釋放所有結(jié)點內(nèi)存 */ void release(){ if(headNode == NULL) return; wordNode *pre = headNode; while(pre != NULL){ headNode = pre->next; free(pre); pre = headNode; } }
調(diào)試結(jié)果:(Xcode環(huán)境)
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
如何調(diào)用C標(biāo)準(zhǔn)庫的exit函數(shù)詳解
這篇文章主要給大家介紹了關(guān)于如何調(diào)用C標(biāo)準(zhǔn)庫的exit函數(shù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07詳解如何在code block創(chuàng)建一個C語言的項目
這篇文章主要介紹了詳解如何在code block創(chuàng)建一個C語言的項目,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Qt實現(xiàn)SqlRelationalTable關(guān)聯(lián)表組件
在Qt中我們可以通過拖拽的方式將不同組件放到指定的位置,實現(xiàn)圖形化開發(fā)極大的方便了開發(fā)效率,本章將重點介紹SqlRelationalTable關(guān)聯(lián)表組件的常用方法及靈活運(yùn)用,感興趣的可以了解一下2023-12-12可能是全網(wǎng)最詳細(xì)的Qt連接MySQL數(shù)據(jù)庫教程
QT眾所周知是一個開源的,以C++為底層的可視化工具庫,下面這篇文章主要給大家介紹了關(guān)于最詳細(xì)的Qt連接MySQL數(shù)據(jù)庫教程的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04