英文單詞詞頻統計
阿新 • • 發佈:2019-01-01
英文單詞詞頻統計
問題描述:做一個詞頻統計程式,該程式具有以下功能
(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; }