zoukankan      html  css  js  c++  java
  • 福大软工1816 · 第五次作业

    一、在文章开头给出结对同学的博客链接、本作业博客的链接、你所Fork的同名仓库的Github项目地址

    结对同学的博客链接:https://www.cnblogs.com/YangLiLiang/p/9752105.html
    本作业博客的链接:https://edu.cnblogs.com/campus/fzu/Grade2016SE/homework/2138
    Github项目地址:https://github.com/Stellaaa18/pair-project

    二、给出具体分工

    林翔宇:负责实现多参数混合使用功能实现;单词数统计,词频统计;负责整合代码;性能分析;
    杨礼亮:负责爬虫、处理数据;分权重词频统计部分代码;实现字符、行数统计部分代码;
    各自写自己负责部分的博客。

    三、给出PSP表格

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 10 15
    · Estimate · 估计这个任务需要多少时间 10 15
    Development 开发 580 840
    · Analysis · 需求分析 (包括学习新技术) 30 30
    · Design Spec · 生成设计文档 20 30
    · Design Review · 设计复审 10 10
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 0 0
    · Design · 具体设计 60 150
    · Coding · 具体编码 240 300
    · Code Review · 代码复审 60 80
    · Test · 测试(自我测试,修改代码,提交修改) 160 240
    Reporting 报告 130 140
    · Test Repor · 测试报告 90 100
    · Size Measurement · 计算工作量 10 10
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 30
    |       | 	合计  |720  | 995
    

    四、解题思路描述与设计实现说明

    1、爬虫使用

    爬虫工具:八爪鱼采集器
    使用方法:
    这个工具使用起来很简易。
    首先建立一个自定义采集,输入将要采集的网页网址,保存网址后便会自动跳转。

    第二,我将标题与简介分开采集,采集标题只需要在本页面直接采集,采集简介要设计循环链接。

    采集完成后就可以以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;
    }
    
    

    最终结果如下

    2、代码组织与内部实现设计(类图)

    3、说明算法的关键与关键实现部分流程图

    五、关键代码解释

    1、贴出你认为重要的/有价值的代码片段,并解释

    以下是主函数的部分代码,用来处理输入文件

    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;
    					}
    					else
    						mapPhrase[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
    					}
    					else
    						mapPhrase[phrase]++;
    					i = secWord; //回到第二个单词首
    					cnt = 0;  //当前单词数清零
    					phrase = ""; //phrase清零
    				}
    			}
    			else {
    				cnt = 0;
    				phrase = "";
    			}
    			word = "";
    		}
    
    	}
    }
    

    六、性能分析与改进

    展示性能分析图和程序中消耗最大的函数
    使用爬取的论文进行测试,输入命令行参数为WordCount.exe -i paper.txt -o result.txt -w 1 -m 3 -n 10,运行时间为18.716s,输出结果如下:

    性能报告截图:

    从中可以看出,消耗最大的函数是TopNPhrase(),占据总运行时间的49.1%。

    七、单元测试

    附上检测代码:

    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 lines
                        continue;
                    }
                    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 lines
                        continue;
                    }
                    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 lines
                        continue;
                    }
                    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 lines
                        continue;
                    }
                    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 lines
                        continue;
                    }
                    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);
            }
    

    八、贴出Github的代码签入记录

    九、遇到的代码模块异常或结对困难及解决方法

    困难:

    • 由于事先没有确定接口,后期代码合并困难
    • 在写代码的过程中两个人都没有注释代码的习惯,使得两个人都看不懂对方的代码。一定要改!!!
    • 结对过程中联系很少,经常不知道对方的进度。

    解决方法:

    • 分工时接口一定一定要事先讲清楚
    • 养成写注释的习惯
    • 要经常沟通,知道对方的进度

    十、评价你的队友

    值得学习的地方:
    做事认真负责,也很积极,比较有时间观念,快要到截止时间时会提醒我。
    需要改进的地方 :
    合作过程沟通较少,彼此工作比较分离。

    十一、学习进度条

    第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
    1 400 400 30 30 学会写单元测试和用vs进行性能分析
    2 0 400 20 50 学会了墨刀这个原型设计软件的使用;学会了如何与队友沟通与合作
    3 344 744 16 66 进一步掌握git的使用
  • 相关阅读:
    final、static关键字
    this关键字与super关键字区别
    JAVA常见报错
    Java抽象类和多态
    Java 类和接口的继承
    JAVA封装
    库存管理案例
    Map的遍历
    LinkedList vector集合,Set接口
    Collection,迭代器iterator,list接口
  • 原文地址:https://www.cnblogs.com/Stella12/p/9769114.html
Copyright © 2011-2022 走看看