福大软工1816 · 第五次作业 - 结对作业2
1.结对同学的博客链接、本作业博客的链接、所Fork的同名仓库的Github项目地址
Github地址:https://github.com/Stellaaa18/pair-project
结对同学的博客链接:http://www.cnblogs.com/Stella12/p/9769114.html
本作业博客的链接:https://edu.cnblogs.com/campus/fzu/Grade2016SE/homework/2138
2.分工
杨礼亮:负责爬虫、处理数据;分权重词频统计部分代码;实现字符、行数统计部分代码;
(队友)林翔宇:负责实现多参数混合使用功能实现;词组、单词、统计部分代码;负责整合代码;性能分析;
各自写自己负责部分的博客。
3.PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
20 |
30 |
· Estimate |
· 估计这个任务需要多少时间 |
20 |
30 |
Development |
开发 |
750 | 820 |
· Analysis |
· 需求分析 (包括学习新技术) |
200 |
230 |
· Design Spec |
· 生成设计文档 |
30 |
40 |
· Design Review |
· 设计复审 |
30 |
10 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
100 |
60 |
· Design |
· 具体设计 |
200 |
300 |
· Coding |
· 具体编码 |
100 |
100 |
· Code Review |
· 代码复审 |
30 |
20 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
60 |
60 |
Reporting |
报告 |
80 |
100 |
· Test Repor |
· 测试报告 |
60 |
60 |
· Size Measurement |
· 计算工作量 |
5 |
5 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
15 |
35 |
合计 |
850 |
950 |
4. 使用工具爬取论文信息
爬虫工具:八爪鱼采集器
使用方法:
这个工具使用起来很简易。
首先建立一个自定义采集,输入将要采集的网页网址,保存网址后便会自动跳转。
第二,我将标题与简介分开采集,采集标题只需要在本页面直接采集,采集简介要设计循环链接。
采集完成后就可以以excel格式导出,再将excel中的数据粘贴到文本中。
我是将标题和简介放到两个文本中,采集后的数据比较混乱,需要按格式输出,所以用c语言写了一些程序来整理文本。
这里附上一些伪代码
//在简介前面加上 Abstract: void Abstract(char *filename) {ifstream file;file.open(filename);string s;string t="Abstract: ";ofstream fileOutput;fileOutput.open("2.txt", ios::app);while(getline(file, s)){fileOutput << t+s << endl;}file.close(); }
//在标题前面加上 Title: void Title(char *filename) {ifstream file;file.open(filename);string s;string t="Title: ";ofstream fileOutput;fileOutput.open("1.txt", ios::app);while(getline(file, s)){fileOutput << t+s << endl;}file.close(); }
//按格式输出 void Title(char *filename) {ifstream file;file.open(filename);string s;int count= 979;for(int i=0;i<count;i++){getline(file, s);title[i]=s;}file.close(); }void Abstract(char *filename) {ifstream file;file.open(filename);string s;int count= 979;for(int i=0;i<count;i++){getline(file, s);abstract[i]=s;}file.close(); }int main() {ofstream fileOutput;fileOutput.open("result.txt", ios::app);char filename1[105]= "1.txt";char filename2[105]= "2.txt";Title(filename1);Abstract(filename2);int count= 979;for(int i=0;i<count;i++){ fileOutput<<i<<endl;fileOutput<<title[i]<<endl;fileOutput<<abstract[i]<<endl;fileOutput<<endl<<endl;}return 0; }
最终结果如下
5.代码组织与内部实现设计(类图)
分装成五个接口函数,分别实现多参数混合使用、字符统计、行数统计、词组统计、分权重词频统计
int AnalyseParameter(char **argv); int CountChar(string name); int CountLines(string name); void PhraseFreq(string str); void TopNPhrases(); int WordFreq(string s); void TopNWords();
内部实现如下:
类图:
6.算法的关键与关键实现部分流程图
本次任务的关键在于词组统计的实现,实现部分代码如下:
void PhraseFreq(string s) {string word = "";string phrase = "";int cnt = 0, secWord;int len = s.length();for (int i = 0; i < len; i++) {if (s[i] >= 'A' && s[i] <= 'Z') {s[i] += 32; //change into lower case }if ((s[i] >= '0'&&s[i] <= '9') || (s[i] >= 'a'&&s[i] <= 'z')) {word += s[i];if (i == len - 1 && IsWord(word)) {cnt++;if (cnt == 1) {phrase += word;}else {phrase += " ";phrase += word;}if (cnt == 2) {secWord = i - word.size() - 1;}if (cnt == phraseLen) {if (weightOnWord && inTitle) {mapPhrase[phrase] += 10;}elsemapPhrase[phrase]++;i = secWord;}}}else if (word != "") {if (IsWord(word)) {cnt++;if (cnt == 1) {phrase += word;}else {phrase += " ";phrase += word;}if (cnt == 2) {secWord = i - word.size() - 1;}if (cnt == phraseLen) {if (weightOnWord && inTitle) {mapPhrase[phrase] += 10;}elsemapPhrase[phrase]++;i = secWord;cnt = 0;phrase = "";}}else {cnt = 0;phrase = "";}word = "";}} }
流程图:
7.关键代码解释
以下是主函数的部分代码,用来处理输入文件
int main() {ifstream fin(inputFile); string str;while (getline(fin, str)) { //按行读取文件内容 inTitle = 0;if (str.substr(0, 7) == "Title: ") {//"Title: "不计算在内str = str.substr(7, str.length());inTitle = 1;}else if (str.substr(0, 10) == "Abstract: ") {//"Abstract: "不计算在内str = str.substr(10, str.length());}else if (IsNum(str[0]) || str==""){ //不统计论文编号和空行continue;}if (countPhrase) {//countPhrase=1,启用词组词频统计 PhraseFreq(str);}characters += CountChar(str);words += WordFreq(str);lines += CountLines(str);}fin.close();return 0;} ``` //统计一行中的词组词频 ``` void PhraseFreq(string s) {string word = "";string phrase = "";int cnt = 0, secWord;int len = s.length();for (int i = 0; i < len; i++) {if (s[i] >= 'A' && s[i] <= 'Z') {s[i] += 32; //大写转小写 }//遍历到最后一个字符,和遇到分隔符一样,要判断当前词组是否符合条件if ((s[i] >= '0'&&s[i] <= '9') || (s[i] >= 'a'&&s[i] <= 'z')) {word += s[i];if (i == len - 1 && IsWord(word)) { cnt++;if (cnt == 1) {phrase += word;}else {phrase += " ";phrase += word;}if (cnt == 2) {secWord = i - word.size()-1;}if (cnt == phraseLen) {if (weightOnWord && inTitle) {mapPhrase[phrase] += 10;}elsemapPhrase[phrase]++;i = secWord;}}}else if(word!=""){ //遇到分隔符且word不为空if (IsWord(word)) { //如果是有效单词cnt++;//单词加到phrase中if (cnt == 1) {phrase += word;}else {phrase += " ";phrase += word;}if (cnt == 2) { //记录词组第二个单词的位置secWord = i - word.size()-1;}if (cnt == phraseLen) { if (weightOnWord && inTitle) { //若启用权重统计并且是属于title的单词mapPhrase[phrase]+=10; //权重为10 }elsemapPhrase[phrase]++;i = secWord; //回到第二个单词首cnt = 0; //当前单词数清零phrase = ""; //phrase清零 }}else {cnt = 0;phrase = "";}word = "";}} }
8.性能分析与改进
展示性能分析图和程序中消耗最大的函数
使用爬取的论文进行测试,输入命令行参数为WordCount.exe -i paper.txt -o result.txt -w 1 -m 3 -n 10,运行时间为18.716s,输出结果如下:
性能报告截图:
从中可以看出,消耗最大的函数是TopNPhrase(),占据总运行时间的49.1%。
9.单元测试
附上检测代码:
TEST_METHOD(TestMethod1){string name;name="chartest1.txt";int chars = CountChar(name);Assert::AreEqual(chars, 40);}TEST_METHOD(TestMethod2){string name;name = "chartest2.txt";int chars = CountChar(name);Assert::AreEqual(chars, 74);}TEST_METHOD(TestMethod3){string name;name = "wordtest1.txt";ifstream fin(name);int words = 0;string str;while (getline(fin, str)) {inTitle = 0;if (str.substr(0, 7) == "Title: ") {str = str.substr(7, str.length());inTitle = 1;}else if (str.substr(0, 10) == "Abstract: ") {str = str.substr(10, str.length());}else if (IsNum(str[0]) || str == "") { //ignore paper number and empty linescontinue;}if (countPhrase) {PhraseFreq(str);}words += WordFreq(str);}fin.close();Assert::AreEqual(words, 5);}TEST_METHOD(TestMethod4){string name;name = "wordtest2.txt";ifstream fin(name);int words = 0;string str;while (getline(fin, str)) {inTitle = 0;if (str.substr(0, 7) == "Title: ") {str = str.substr(7, str.length());inTitle = 1;}else if (str.substr(0, 10) == "Abstract: ") {str = str.substr(10, str.length());}else if (IsNum(str[0]) || str == "") { //ignore paper number and empty linescontinue;}if (countPhrase) {PhraseFreq(str);}words += WordFreq(str);}fin.close();Assert::AreEqual(words, 9);}TEST_METHOD(TestMethod5){string name;name = "linetest1.txt";ifstream fin(name);int lines = 0;string str;while (getline(fin, str)) {inTitle = 0;if (str.substr(0, 7) == "Title: ") {str = str.substr(7, str.length());inTitle = 1;}else if (str.substr(0, 10) == "Abstract: ") {str = str.substr(10, str.length());}else if (IsNum(str[0]) || str == "") { //ignore paper number and empty linescontinue;}if (countPhrase) {PhraseFreq(str);}lines += CountLines(str);}fin.close();Assert::AreEqual(lines, 5);}TEST_METHOD(TestMethod6){string name;name = "linetest2.txt";ifstream fin(name);int lines = 0;string str;while (getline(fin, str)) {inTitle = 0;if (str.substr(0, 7) == "Title: ") {str = str.substr(7, str.length());inTitle = 1;}else if (str.substr(0, 10) == "Abstract: ") {str = str.substr(10, str.length());}else if (IsNum(str[0]) || str == "") { //ignore paper number and empty linescontinue;}if (countPhrase) {PhraseFreq(str);}lines += CountLines(str);}fin.close();Assert::AreEqual(lines, 5);}TEST_METHOD(TestMethod7){string name;name = "characterstest.txt";ifstream fin(name);int characters = 0;string str;while (getline(fin, str)) {inTitle = 0;if (str.substr(0, 7) == "Title: ") {str = str.substr(7, str.length());inTitle = 1;}else if (str.substr(0, 10) == "Abstract: ") {str = str.substr(10, str.length());}else if (IsNum(str[0]) || str == "") { //ignore paper number and empty linescontinue;}if (countPhrase) {PhraseFreq(str);}characters += CountChar(str);}fin.close();Assert::AreEqual(characters, 5);}TEST_METHOD(TestMethod8){string name;name = "phrasetest1.txt";ifstream fin(name);string str;while (getline(fin, str)) {inTitle = 0;if (countPhrase) {PhraseFreq(str);}}fin.close();if (countPhrase) { //phrase statistics TopNPhrases();}else { //word statistics TopNWords();}for (auto x : mapPhrase) {vecPhrase.push_back(x);}sort(vecPhrase.begin(), vecPhrase.end(), cmp2);Assert::AreEqual(vecPhrase[1].first, string("monday tuesday wednesday"));Assert::AreEqual(vecPhrase[1].second, 11);}TEST_METHOD(TestMethod9){string name;name = "phrasetest2.txt";ifstream fin(name);string str;while (getline(fin, str)) {inTitle = 0;if (countPhrase) {PhraseFreq(str);}}fin.close();if (countPhrase) { //phrase statistics TopNPhrases();}else { //word statistics TopNWords();}for (auto x : mapPhrase) {vecPhrase.push_back(x);}sort(vecPhrase.begin(), vecPhrase.end(), cmp2);Assert::AreEqual(vecPhrase[1].first, string("convolutional neural networks"));Assert::AreEqual(vecPhrase[1].second, 196);}
10.遇到的代码模块异常或结对困难及解决方法
困难:
尝试用python写爬虫;
在结对合作的过程中,各部分的代码是两个人分开写的,在定义函数接口上出现的参数不一致的情况,合并代码麻烦;
在写代码的过程中两个人都没有注释代码的习惯,看对方的代码特别吃力,很多变量和代码逻辑意思不懂。
结对过程中联系很少,经常不知道对方的进度。
解决方法:
用python写爬虫还没实现;
彼此约定下次写各自代码时一定要注释清楚。
11.评价你的队友
值得学习:办事效率高,代码能力强大,技术稳稳的,全程带飞我,紧抱队友大腿。
需要改进的地方:合作过程沟通较少,彼此工作比较分离。
12.学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
5 | 200 | 600 | 30 | 80 |
1.熟悉了爬虫工具的使用 2.使用c++处理数据 3.写代码过程中学会了新的算法 4.提高了分工合作能力 |
13.贴出Github的代码签入记录
转载于:https://www.cnblogs.com/YangLiLiang/p/9752105.html
福大软工1816 · 第五次作业 - 结对作业2相关推荐
- 福大软工1816:选题报告(团队作业二)
"Jarvis For Chat"团队选题报告 组长博客链接 本次作业链接 NABCD在项目中的使用 N(Need,需求) QQ和微信已经成为人们社交的必需品,在QQ有7.8亿活跃 ...
- 福大软工1816 · 第一次作业 - 准备
福大软工1816 · 第一次作业 - 准备 期待→迷茫→恐惧→振作or放弃? 前言:个人情况概述 虽然长辈都说我是个聪明的孩子,但我觉得也许那只是客套话-- 还记得从小学时我的成绩仅处于中游偏下,初中 ...
- 福大软工1816:项目测评
福大软工 · 第十次作业 - 项目测评(团队) 评测 个人上手体验 查看课程表上效仿了超级课程表,界面美观 功能多,整合了课程表.查成绩.考场查询.历年卷.易班.空教室.图书馆.教务通知.大物实验.嘉 ...
- 福大软工1816:Alpha事后诸葛
福大软工·第十一次作业-Alpha事后诸葛亮 组长博客链接 本次作业博客链接 项目Postmortem 模板 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描 ...
- 福大软工1816 · 第三次作业 - 结对项目1
软工实践第三次作业-结对项目1 简要目录: Step1 · 结对信息 成员信息 项目简介 Step2 · 项目信息 设计说明 原型模型 Step3 · 结对过程 ...
- 福大软工1816 · 第一次作业——准备
一.自我介绍 031602442:我是时而懒时而又异常坚持的郑孔宇:我的爱好是听音乐和玩游戏:我比较喜欢玫瑰一楼的拌面扁肉:及时行乐! 二.阅读与思考 1.回想一下你初入大学时对计算机专业的畅想 (1 ...
- 福大软工1816 · 第一次团队作业
如果记忆是一个罐头的话,我希望这一罐罐头不会过期――――<重庆森林> 404 Note Found Team 如果记忆是一个备忘录的话,别说了,它不会过期――――<404 Note ...
- 福大软工1816:Alpha(3/10)
Alpha 冲刺 (3/10) 队名:第三视角 组长博客链接 本次作业链接 团队部分 团队燃尽图 工作情况汇报 张扬(组长) 过去两天完成了哪些任务: 文字/口头描述: 1.学习qqbot库: 2.实 ...
- 福大软工1816 - 404 Note Found选题报告
目录 NABCD分析引用 N(Need,需求): A(Approach,做法): B(Benefit,好处): C(Competitors,竞争): D(Delivery,交付): 初期 中期 个人贡 ...
最新文章
- linux平台软件动态分析工具valgrind系列工具及其可视化
- 特权级——保护模式的特权级检查 DPL,RPL,CPL, 一致代码段,非一致代码段
- 关于Hadoop多用户管理支持客户端远程操作的理论总结
- gevent-tutorial翻译和解读
- Android之Activity框架
- 学法减分助手PRO小程序
- SpringBoot精通系列-使用Mybatis Generator生成Dao层代码
- Chrome 无法抓取跳转请求的解决办法
- java.sql.SQLException
- Zerodium 称 iOS exploit 过剩,将暂停收购且买价或下跌
- HDU2566 统计硬币【暴力】
- 类名作为形式参数传递
- 北理工计算机学院新闻,新闻睇睇睇 | 计算机学院举办第八届ACM/ICPC程序设计竞赛校内选拔赛暨北理工邀请赛...
- 杭州最新公交线路一览(91-100)
- VUE项目中高德地图选择坐标和输入搜索功能
- 欧盟CE公告号-外贸人不得不了解的通关证书
- 软考--快速掌握操作系统的PV操作
- 6000字总结MySQL最基础的增删查改命令
- 手机直播连麦技术分析
- 智能驾驶之技术概念综述