需求:
1.設計一個詞頻統計軟件,統計給定英文文章的單詞頻率。
2.文章中包含的標點不計入統計。
3.將統計結果以從大到小的排序方式輸出。
設計:
1.因為是跨專業0.0···並不會c++和java,只能用僅學過的C語言進行編寫,還是挺費勁的。
2.定義一個包含單詞和頻率兩個成員的結構體來統計詞頻(進行了動態分配內存,可以處理較大文本)。
3.使用fopen函數讀取指定的文檔。
4.使用fgetc函數獲取字符,再根據取得的字符是否是字母進行不同的處理。
5.采用快速排序法對統計結果進行排序。
5.將整個統計結果循環輸出。
部分代碼:
結構體定義:
struct fre_word
{
int num;
char a[18];
};
分配初始內存:
struct fre_word *w;
w=(struct fre_word *)malloc(100*p*sizeof(struct fre_word));//給結構體分配初始內存
讀取文本:
printf("輸入讀入文件的名字:");
scanf("%s", filename); //輸入需要統計詞頻的文件名
if((fp=fopen(filename, "r"))==NULL)
{
printf("無法打開文件\n");
exit(0);
}
單詞匹配:
/****************將單詞出現次數設置為1****************************/
for(i=0;i<100;i++)
{
(w+i)->num=1;
}
/****************單詞匹配****************************************/
i=0;
while(!feof(fp))//文件尚未讀取完畢
{
ch=fgetc(fp);
(w+i)->a[j]='\0';
if(ch>=65&&ch<=90||ch>=97&&ch<=122) //ch若為字母則存入
{
(w+i)->a[j]=ch;
j++;
flag=0; //設標志位判斷是否存在連續標點或者空格
}
else if(!(ch>=65&&ch<=90||ch>=97&&ch<=122)&&flag==0) //ch若不是字母且上一個字符為字母
{
i++;
j=0;
flag=1;
for(m=0;m<i-1;m++) //匹配單詞,若已存在則num+1
{
if(stricmp((w+m)->a,(w+i-1)->a)==0)
{
(w+m)->num++;
i--;
}
}
}
/****************動態分配內存****************************************/
if(i==(p*100)) //用i判斷當前內存已滿
{
p++;
w=(struct fre_word*)realloc(w,100*p*(sizeof(struct fre_word)));
for(n=i;n<=100*p;n++) //給新分配內存的結構體賦初值
(w+n)->num=1;
}
}
快速排序:
void quick(struct fre_word *f,int i,int j)
{
int m,n,temp,k;
char b[18];
m=i;
n=j;
k=f[(i+j)/2].num; //選取的參照
do
{
while(f[m].num>k&&m<j) m++; // 從左到右找比k小的元素
while(f[n].num<k&&n>i) n--; // 從右到左找比k大的元素
if(m<=n)
{ //若找到且滿足條件,則交換
temp=f[m].num;
strcpy(b,f[m].a);
f[m].num=f[n].num;
strcpy(f[m].a,f[n].a);
f[n].num=temp;
strcpy(f[n].a,b);
m++;
n--;
}
}
while(m<=n);
if(m<j) quick(f,m,j); //運用遞歸
if(n>i) quick(f,i,n);
}
結果輸出:
for(n=0;n<=i;n++)
{
printf("文檔中出現的單詞:");
printf("%-18s",(w+n)->a);
printf("其出現次數為:");
printf("%d\n",(w+n)->num);
}
測試用例:
看了之前同學的博客以及老師的評論,就使用了較長的文本進行測試,用的是奧巴馬就職演講稿。

部分測試結果:
