【软工实践】第二次作业--词频统计
Github项目地址
https://github.com/RayBH/PersonProject-C2
PSP表格
解题思路
一开始拿到这个题目感觉有点熟悉又有点陌生,感觉不是很难又感觉很难,有很多地方要注意。想了下根据自顶向下的方法我觉得应该把大体的功能往下拆分成一个个小功能,之后再合起来。大致要做的几个工作就是:
读入文件input.txt
读入文件内容之后进行单词划分
统计各个单词出现频率
按照频率对各个单词排序
将单词及频率写入到result.txt
把一个大任务拆分成几个小任务,之后就开始寻找解决方案。
实现过程
首先第一步当然是对应以上功能去查阅资料,至少先把文件读进去再说,发现有个东西叫文件流,从然后就去查,应该可以实现这个功能,然后就开始慢慢看资料,发现可以用ifstream从硬盘读到内存,ofstream从内存读到硬盘,这样就解决了输入输出的问题。
因为不知道读入文本具体大小的原因,所以需要一个动态的容器,就需要创建向量vector,能够容纳许多其他类型相同的元素,并且能够根据需要随时自动调整自身的大小以便容下所要放入的元素。
接下来要实现对单词的划分,可以用stringstream字符串流,ss函数实现单词划分。然后统计频率,就需要用到结构体,把一个单词以及出现频率当做一条记录。
之后再用ofstream输出到文本。
部分代码说明及测试
读取文件并统计词频
void WordStatic::read(const string & name)//读文件
{
ifstream ifs(name.c_str());//用文件输入流读入文件名为name这个文件
string str;
if(ifs.good() == 0)//流类成员函数,判断状态是否良好,读入文件的时候有无出错
{
cout << "不好意思哦亲,读入文件失败!" << endl;
return;
}
while(getline(ifs,str))//不断重复读取每一行,读取流中的字符串
{
lines ++;
stringstream ss(str);//划分str中的单个字节
string word;
while(ss >> word)
{
vector<cipin>::iterator i;//迭代器
for(i = vec.begin(); i !=vec.end(); i++)
{
characters++;
if(word == (*i).word)
{
(*i).count +=1;
break;
}
}
if(i == vec.end())//新建一个记录
{
words++;
characters++;
cipin temp;
temp.word = word;
temp.count = 1;
vec.push_back(temp);
}
}
}
ifs.close();
sort(vec.begin(),vec.end(),set_word); //排序
}
排序算法
void WordStatic::write(const string & name)//写文件
{
//从流中写数据
vector<cipin>::iterator i;
int j = 0;
ofstream ofs(name);//做一个输出文件流
if(ofs.good() == 0)
{
cout<< "不好意思哦亲,写入文件失败!" <<endl;
}
ofs << "characters:" << " " <<characters <<endl;//输出字符数
ofs << "words:"<< " " << words <<endl;//输出单词数
ofs << "lines:"<< " " << lines <<endl;//输出行数
for(i = vec.begin(); i != vec.end(); i++)
{
ofs << (*i).word << " " << (*i).count <<endl;
j++;
if(j==10)break;//只允许输出10个
}
ofs.close();
}
写入文件
void WordStatic::write(const string & name)//写文件
{
//从流中写数据
vector<cipin>::iterator i;
int j = 0;
ofstream ofs(name);//做一个输出文件流
if (ofs.good() == 0)
{
cout << "不好意思哦亲,写入文件失败!" << endl;
}
ofs << "characters:" << " " << characters << endl;//输出字符数
ofs << "words:" << " " << words << endl;//输出单词数
ofs << "lines:" << " " << lines << endl;//输出行数
for (i = vec.begin(); i != vec.end(); i++)
{
ofs <<"<"<< (*i).word << ">: " << (*i).count << endl;
j++;
if (j == 10)break;//只允许输出10个
}
ofs.close();
}
部分测试结果
总结与收获
虽说是第二次作业,不过却是本学期软工实践的第一次实践项目,个人感觉收获还是挺大的,因为我是第一次做这种东西,以前基本只打算法题那种,一开始很不适应。其实很多内容以前老师上课都没有教,以前教的更多的是关于算法的问题,关于工程的问题基本没有学过,所以这次作业也遇到了很多问题,花了很多时间,结果做的也挺糙的T^T。主要是有很多新的东西要去学要去看。不过这种遇到新问题然后查阅资料,然后再慢慢学习新知识的感觉,还是会让人感觉很充实,有一种学到了的感觉。,就比如后面有一个输出到文件的问题,我一开始用cout<<发现会显示在程序中,但是文件里没有,后来查了好久发现要用ofs<<,之后才慢慢去看这部分的知识,所以很多知识都是在遇到问题的时候,去查阅相关资料以后才懂的,才发现这些东西以前都没学。还有我发现一开始出发的那个方向非常关键,一开始的方向如果对了,在过程中遇到小问题的时候去网上查,都能慢慢解决,解决不了的再花时间也能慢慢解决,但是如果一开始方向错了,那可能就很难说了。所以我发现一开始构思的那个框架非常重要,还有其实一开始写代码并不花太多时间,毕竟只是写个框架,后来开始找问题,慢慢改,调试那个部分才花时间。
而且注释也很重要,有时候前一天写的,没注释的话,第二天还要在看一遍理解下,毕竟都是现学现用,有注释的话就会好很多。
虽然做的有点粗糙,但是总的来说,通过这几天的自主学习还算是有收获。