1. 程式人生 > >英文單詞詞頻統計

英文單詞詞頻統計

                                            英文單詞詞頻統計

問題描述:做一個詞頻統計程式,該程式具有以下功能

       (1)可匯入任意英文文字檔案

       (2)統計該英文檔案中單詞數和各單詞出現的頻率(次數),並能將單詞按字典順序輸出。

       (3)將單詞及頻率寫入檔案。

本次英文單詞的詞頻統計程式的設計過程中,使用了檔案的相關操作(檔案的讀與寫),在檔案中錄入資料,程式以一個字串為一個單位讀取單詞,並將結果輸出到result.txt中,而且也在程式中顯示。

基本演算法設計:在data.txt中輸入要統計的英文文章,按逐個字元進行讀取,並將連續的字元儲存為一個字串。當讀取到的字元不是26個英文字母以內時,則開始新的字串的讀取。直到將整片文章讀取為一個一個的字串。並將這些字串按照氣泡排序的方法進行排序,以使單詞可以按照字典的順序輸出。

      在本次設計過程中,還學會了一下一些知識點:

      1.malloc函式的用法

malloc 向系統申請分配指定size個位元組的記憶體空間。返回型別是 void* 型別。void* 表示未確定型別的指標。C,C++規定,void* 型別可以通過型別轉換強制轉換為任何其它型別的指標。

     2.c語言中,字元的差為它們對應的ASCII碼值之差。

程式原始碼:

//檔名:英文單詞詞頻統計.cpp
//作者:Vector_山水之間
//學號:1508010333
//版本:1.3
//完成日期:2017.3.31
//主要功能:在文字檔案中輸入一篇英文文章,統計文章中每個英文單詞出現的次數
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 27	                 //26個字母和其他字元
typedef struct Word              //字典樹的結構體定義
{
	
Word *next[MAX]; //陣列下標0-25代表小寫字母,26代表其他字元 int num; }; typedef struct tlist //結構體定義:單詞和對應頻率 { char word[200]; int time; }; struct tlist list[3000000]; //定義結構體陣列 Word *root; char str[200]=""; //字元資料初始化為空 char tempword[1000]; int size=0; //size為一篇文章中字串的個數 void output(); void display(); int main(); void createWord(char *str) //新建單詞的函式(形參為字串指標) { int len = strlen(str), id; //strlen函式是測量字串長度的函式 Word *p = root, *q; for(int i = 0; i < len; i ++)//遍歷單詞判斷當前字元是否為字母或其他字元 { if(str[i] >= 'a' && str[i] <= 'z') id = str[i] - 'a'; //字元相減為對應ASCII值相減 if(str[i] >= 'A' && str[i] <= 'Z') id = str[i] - 'A'; if(str[i] == '\'') id = 26; //當讀取到的字元為26個英文字母除外的其他字元,id置為26 if(p->next[id] == NULL) //若已到達連結串列結尾,開闢新的結構體存入字母 { q = (Word *)malloc(sizeof(Word)); for(int j = 0; j < MAX; j ++) { q->num=0; q->next[j] = NULL; } p->next[id] = q; p = p->next[id]; } else //若未到達連結串列結尾,指標指向下一個 { p = p->next[id]; } } p->num++; //重複單詞數加1 } void readWord(Word *p,int len) //讀單詞的函式 { int i; for(i=0;i<27;i++) { if(p->next[i]!=NULL) { if (i==26) { str[len+1]='\0'; str[len]='\''; len++; } else { str[len]='a'+i; len++; } readWord((Word*)p->next[i],len); len--; } } if(p->num!=0) { str[len]='\0' ; strcpy(list[size].word,str); //如果遇到單詞結束標誌,將str存入list[size].word list[size].time=p->num; size++; } } void output() //輸出函式 { int i; FILE *fpx; fpx=fopen("result.txt","w"); //將統計結果寫入到result.txt檔案中 for (i=1;i<size;i++) fprintf(fpx,"%s %d\n",list[i].word,list[i].time); for (i=1;i<size;i++) //輸出統計結果 printf("%s %d\n",list[i].word,list[i].time); fclose(fpx); } void menu() //選單函式 {
    int choose;
    printf("----------------英文單詞詞頻統計-----------------------------\n\n");
    printf("使用前請認真閱讀使用幫助!\n\n");
    printf("使用幫助:\n");
    printf("請在文字文件data.txt中輸入英文單詞或者英文文章\n");
    printf("若要修改需要統計的英文單詞或者英文文章,請在data.txt檔案中進行\n\n");
    printf("若以確保在data.txt文件中輸入資料,請按數字鍵1檢視詞頻統計結果!\n");
    scanf("%d",&choose);
    if(choose==1)
	display();
}void display() //展示統計結果函式{ int i,j; char x; int len=0; //初始時字串長度為0 root=(Word*)malloc(sizeof(Word)); //為結構體指標root動態開闢儲存空間 for (i=0;i<27;i++) root->next[i]=NULL; FILE *fp; fp=fopen("data.txt","r"); //檔案開啟方式為只讀 if(!fp) {printf("\n開啟檔案data.txt失敗!"); }while((x=fgetc(fp))!=EOF) //從txt文件中讀入 讀入失敗時,函式值為EOF(-1) fgetc為從檔案中讀取一個字元 { if ((x>='A'&&x<='Z')||(x>='a'&&x<='z')||(x=='\''&&len!=0)) { tempword[len]=x;len++;} else { tempword[len]='\0'; createWord(tempword); len=0; } } tempword[len]='\0'; createWord(tempword); //建立對文字最後一個英文字串的讀取 len=0; fclose(fp); readWord(root,0); struct tlist temp; for(i=0;i<size-1;i++) //比較頻率大小氣泡排序 for(j=i+1;j<size;j++) if(list[i].time>list[j].time||(list[i].time==list[j].time&&strcmp(list[i].word,list[j].word)>0)) { temp.time=list[i].time; list[i].time=list[j].time; list[j].time=temp.time; strcpy(temp.word,list[i].word); strcpy(list[i].word,list[j].word); strcpy(list[j].word,temp.word); } printf("英文單詞及詞頻統計結果如下:\n"); output();}int main() //主函式 { menu(); return 0; }