软件工程个人小项目:写一个程序,分析一个文本文件(英文文章)中各个词出现的频率,并且把频率最高的10个词打印出来
思想:看到这个问题,我想到了我们曾经做过的一些小程序,例如在C语言中有统计单词个数的程序,在编译原理时我们曾做过分离一个文件中各种符号,字符串等工作,所以我想利用这两个思想来进一步实现这个程序。
我的想法是利用一个结构体,在这个结构体中有两个变量一个数这个单词出现的次数,第二是保存一个单词的字符数组。然后读取一个文件,利用控制条件先读取一个单词存储在这个大的结构体数组中,接着当保存好第二个单词时与第一个单词对比看看是否相等,如果不等,接着使这个结构体数组加1,如果相等那么这个单词的次数加1并且使结构体数组不加1,便于以后比较,对于什么时候判断是一个单词则用word来判断。将这些单词保存在结构体数组中时在比较其大小从而输出其频率出现最多的10个单词。
缺点:这样标识符太多,麻烦容易出错,而且调试起来繁琐
改正:可以先将单词不分类直接保存在字符数组中,同时消去逗号,空格等的影响,然后在通过比较函数来比较单词出现的次数即可,这样思想大概相同,但是不会那么的繁琐,省去了很多的变量。
程序:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct WORD
{
int num;
char a[20];
};//结构体数组用于保存单词及出现的个数
int main()
{
struct WORD A[600];//结构体数组
int i;
char b[20];
FILE *in;
char ch;
int word=0;
int j=0;
int m,n,k;
int max;
char infile[50];
printf("输入文件路径\n");
scanf("%s",infile);//输入文件名字
if((in=fopen(infile,"r"))==NULL)
{
printf("此文件无法打开");
exit(0);
}
for(i=0;i<600;i++)//初始化其次数
{ A[i].num=1;}
i=0;
while(!feof(in))//一个个的读取字符
{
A[i].a[j]='\0';//单词结束的标志是‘\0’。
ch=fgetc(in);
if((ch==' '||ch=='.'||ch==',')&&word==1)//判断单词结束的标志
{
word=0;
j=0;
n=i;
i++;//结构体数组加1
if(n>=1)//从第二个单词开始,每提取一个单词都与前边比较是否相等。
{
for(m=0;m<n;m++)
{
if(strcmp(A[n].a,A[m].a)==0)
{
A[m].num++;//次数加1
i-=1;//结构体数组恢复原位
}
}
}
}
else if((ch==' '||ch=='.'||ch==',')&&word!=1)//消除一些空格的影响
continue;
else if(ch>=33&&ch<=122) //包含了所能出现的英文字符,消除文件结束符的影响。
{
A[i].a[j]=ch;
j++;
word=1;
}
}
for(n=0;n<i-1;n++)//通过比较法来排序,并将其单词相互交换
{
k=n;
for(j=n+1;j<i;j++)
if(A[j].num>A[k].num)
{ k=j;
max=A[k].num;A[k].num=A[n].num;A[n].num=max;
strcpy(b,A[k].a); strcpy(A[k].a,A[n].a); strcpy(A[n].a,b);
}
}
printf("频率\t单词\t个数\n");
for(i=0;i<10;i++) //显示出频率最高的前10个单词,及出现次数
{
printf("%d\t%s\t%d\n",i+1,A[i].a,A[i].num);
}
return 0;
}
结果:
感想:程序有些复杂,控制变量太多,需要自己再去改正优化,争取做得更好。