要求0:作业要求地址 https://edu.cnblogs.com/campus/nenu/2016CS/homework/2110
要求1:git仓库地址 (在分支v1.0上!!!):https://git.coding.net/sonicsun/WordFrequencyCount.git
要求2:
1. PSP阶段表格
sp2.1 | 任务内容 | 计划共完成需要时间 (min) | 实际完成需要时间 (min) |
Planning | 计划 | 30 | 40 |
Estimate |
估计这个任务需要多少时间, 并规划大致工作步骤 |
30 | 40 |
Development | 开发 | 960 | 1250 |
Analysis | 需求分析(包括学习新技术) | 150 | 180 |
Design Spec | 生成设计文档 | 10 | 10 |
Design Reviewe | 设计复审(和同事审核设计文档) | 0 | 0 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 30 | 40 |
Desgin | 具体设计 | 120 | 100 |
Coding | 具体编码 | 500 | 780 |
Code Review | 代码复审 | 30 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 120 | 120 |
Test Report | 测试报告 | 10 | 10 |
Size Measurement | 计算工作量 | 20 | 30 |
Postmortem & Process Improvement Plan | 事后总结,提出过程改进计划 | 90 | 80 |
功能模块 | 具体阶段 | 预计时间 (min) | 实际时间 (min) |
功能1 | 具体设计 | 120 | 90 |
具体编码 | 180 | 190 | |
测试完善 | 40 | 40 | |
功能2 | 具体设计 | 120 | 120 |
具体编码 | 250 | 300 | |
测试完善 | 70 | 60 | |
功能3 | 具体设计 | 50 | 60 |
具体编码 | 180 | 240 | |
测试完善 | 20 | 20 |
2. 预估耗时与实际耗时的差距原因:
(1)这次使用了很少使用的c语言来编写程序,对语言的掌握不太熟练,很多地方都要去网上查资料;
(2)还有其他的事情需要忙;
(3)题目部分阐述含糊不清,花了一定时间来反复思考审清题意。
要求3:
1. 解题思路描述:
刚开始拿到题目反复思考需要几个函数来实现功能,每个函数之间的功能上有什么关系,确定好关键点在于读取文件,分割单词,文件路径的转换,单词计数。
然后先把每个函数之间调用的关系大致框架写了出来,发现主函数与方法都写在一个cpp中可读性太差,于是采用了多文件编译。
去网上看博客学习了c语言如何读取文件。
在单词的分隔上遇到了困难,多次测试应该如何读入单词才能更简便的实现单词分隔,一开始采用的使用结构体进行存储,直接读入一整行,然后进行遍历判断分隔,但是发现在单词的存储上实现难度大,于是采用了直接读入字符串的方法,发现字符串如果遇到了特殊符号同样在存储上有所困难,最终选择采用string和map,一位一位的判断,在计数上也更加方便。
实现 wf -c 和 wf -f 的功能后,wf -n的功能实现只需要调用实现 wf -c 和 wf -f 的函数就可以,然后进行排序输出n个就行。
2. 代码介绍:
(1)单词的分割,计数:采用了map和string的方式对单词进行存储计数,利用map的特性可以轻易的对单词进行存储,但是在txt末尾判断结束时一开始有所困难,如果不是以特殊符号结束,最后一个单词总是丢失,最后在if语句中多加上了feof(fpRead)来对是否结束进行判断。
void judge(char textname[]) //判断单词 { string line=""; char zxsb; map<string,int> Map; map<string,int> ::iterator it; FILE *fpRead = fopen(textname,"r"); if(fpRead == NULL){ printf("read file fail!!"); return; } while(!feof(fpRead)){ fscanf(fpRead,"%c",&zxsb); if((!(zxsb >= 'a' && zxsb <= 'z')&&!(zxsb >= 'A' && zxsb <= 'Z')&&!(zxsb >= '0' && zxsb <= '9'))||(feof(fpRead))){ //判断特殊符号 if(( (line!="") &&!((line[0]>='0')&&(line[0]<='9')))){ //对单词进行计数 Map[line]++; } line=""; } else if (zxsb >= 'A' && zxsb <= 'Z') { //大写转换为小写 zxsb = zxsb + 32; line = line + zxsb; } else if ((zxsb >= 'a' && zxsb <= 'z')||(zxsb >= '0' && zxsb <= '9')) { //符合条件的字符加入string中 line = line + zxsb; } } printf("totle %d ",Map.size()); for(it=Map.begin();it!=Map.end();it++) cout<<it->first<<" "<<it->second<<endl; fclose(fpRead); return; }
(2)wf -f 对文件路径的处理
void pathopen(char filepath[]){ changesign(filepath); //对写入路径进行改变的函数,将单个斜杠改为两个斜杠 int j; j = strlen(filepath); char filepath2[100]; strcpy(filepath2,filepath); filepath2[j++]='*'; filepath2[j++]='.'; filepath2[j++]='t'; filepath2[j++]='x'; filepath2[j++]='t'; filepath2[j++]='