第三次作业——结对编程
第三次作业——结对编程
github地址 | https://github.com/LipeishanDawn/WordCount |
结对伙伴作业地址 |
一、结对过程
1.下图是我和我的结对伙伴一起讨论时的照片
二、PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
30 |
35 |
· Estimate |
· 估计这个任务需要多少时间 |
720 |
750 |
Development |
开发 |
60 |
50 |
· Analysis |
· 需求分析 (包括学习新技术) |
60 |
70 |
· Design Spec |
· 生成设计文档 |
30 |
30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
60 |
55 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
30 |
30 |
· Design |
· 具体设计 |
60 |
50 |
· Coding |
· 具体编码 |
300 |
390 |
· Code Review |
· 代码复审 |
60 |
60 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
60 |
130 |
Reporting |
报告 |
60 |
60 |
· Test Report |
· 测试报告 |
60 |
90 |
· Size Measurement |
· 计算工作量 |
20 |
30 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
10 |
10 |
|
合计 |
1620 |
1840 |
三、解题思路
我和我的结对伙伴首先一起对整个程序的功能进行了分析,然后进行分工。整个程序可以分为四个部分,分别是统计文件的字符数Charnum,统计文件行数Filelines,统计文件里面的单词总数和指定长度的词组的功能Wordnum,包含根据字典顺序输出出现次数最多的前n个数和将结果输出功能的Program。经过分工,我的伙伴主要负责Filelines和Wordnum,而我负责Charnum和Program。由于我对于字典顺序不是很了解,所以我首先百度了字典对象的用法。之前在学习C#的时候,对于文件的部分用法,这次的代码对文件的要求很高,所以我通过翻阅书籍和百度学习了文件。
四、设计实验过程
1、本次的代码分为了四个部分,具体的分工在上一点我有说到。整个函数分为了三个类,分别是Charnum,Fileline和Wordnum。对于我自己的部分Charnum中只有一个getCharCount函数,Program里面也只有一个Main函数。
Charnum
:
Program:
其他具体的设计,以及函数的关系,可详见我伙伴的作业:https://www.cnblogs.com/230332663abcd/p/10626290.html
2、单元测试详见:https://www.cnblogs.com/230332663abcd/p/10626290.html
五、代码制定规范
我们主要参照“http://www.cnblogs.com/xinz/archive/2011/11/20/2255971.html”进行代码规范和复审。
1、互审的模块:我是审查我结对伙伴写的filelines和wordnum这两个类。
2、互审的问题:
即使我们要求按照邹欣老师写的代码规范进行的,但还是避免不了一两处的不规范。
(1)我们规定注释是另起一行,但还是出现了在代码后面直接注释的情况。
(2)对于变量的命名风格不同意。比如我喜欢取每个单词的首字母进行命名,我的同伴习惯使用单词的前几个字母进行命名。后来经过我们讨论,决定采用同伴的命名方式,这样更直观一点。
(3)我们在查看对方代码的时候多有对代码的疑惑,对于这些不是很清楚的地方我们又重新添加了注释。
六、改进程序性能
该部分可详见我伙伴的博客中:https://www.cnblogs.com/230332663abcd/p/10626290.html
七、代码说明
在Charnum里面,主要是将文件中的内容存入一个数组然后通过循环判断Ascii码来统计字符数。
class CharNum { public int getCharCount(string FilePath) { int charCount = 0; FileStream fsRead = new FileStream(FilePath, FileMode.Open);//流方式读取文件 int fsLen = (int)fsRead.Length;//判断文件长度 byte[] heByte = new byte[fsLen];//创建对应长度的byte数组 int r = fsRead.Read(heByte, 0, heByte.Length);//文件内容放到数组里 foreach(byte b in heByte) //循环数组判断 是不是在ASCII表内 { if (b >= 0 && b <= 126 ) { charCount++; // 是就+1 } } fsRead.Close(); return charCount; } }
在主函数里面首先建立各个类的对象,定义词组长度,单词数量、输出内容output等之后会用到的对象。
CharNum charNum = new CharNum(); WordNum wordNum = new WordNum(); FileLines fileLine = new FileLines(); string filePath = "input.txt";//默认文件为 input.txt int wordLength = 0; int wordCount = 0; string outFile = ""; string outPut = "";
判断输入的参数,通过“-i”,"-m","-o","-n"后面紧跟的内容来对文件路径Filepath、词组的长度、要求输出的次数最多个前worldcount个单词和输出文件的路径outfile进行赋值。
再用多个if语句来判断输入内容是否含有多个参数,然后用switch和case来处理参数不同的先后顺序。
if (args.Length > 0 ) // 判断输入参数 { switch (args[0]) { case "-i": filePath = args[1];
//读入的文件路径 break; case "-m": wordLength = int.Parse(args[1]);
//m个单词组成一个词组 break; case "-n": wordCount = int.Parse(args[1]);
//输出出现次数最多的前worldCount个单词 break; case "-o": outFile = args[1];
//生成的文件路径 break; } if(args.Length > 2) switch (args[2]) { case "-i": filePath = args[3]; break; case "-m": wordLength = int.Parse(args[3]); break; case "-n": wordCount = int.Parse(args[3]); break; case "-o": outFile = args[3]; break; } if (args.Length > 4) switch (args[4]) { case "-i": filePath = args[5]; break; case "-m": wordLength = int.Parse(args[5]); break; case "-n": wordCount = int.Parse(args[5]); break; case "-o": outFile = args[5]; break; } if (args.Length > 6) switch (args[6]) { case "-i": filePath = args[7]; break; case "-m": wordLength = int.Parse(args[7]); break; case "-n": wordCount = int.Parse(args[7]); break; case "-o": outFile = args[7]; break; }
调用之前定义的对象的各自的函数,以文件路径作为参数,完成它们相应的功能,将返回值存入output中。
outPut +="characters:" + charNum.getCharCount(filePath) + "\n"; outPut += "words:" + wordNum.getWordCount(filePath) + "\n"; outPut += "lines:" + fileLine.getFileLineCount(filePath) + "\n";
最后用字典顺序,将要输出的内容赋值给output。
wordNum.getWordCount(filePath, wordLength);//先调用方法把单词处理完成 Dictionary<string, int> dict = wordNum.getLinq();//再调用排序 int i = 10; if (wordCount != 0) i = wordCount; foreach (KeyValuePair<string, int> kvp in dict) { if (i == 0) break; else { outPut += "<" + kvp.Key + ">:" + kvp.Value+"\n"; i--; } }
最后再将output的内容存入到输出文件的路径outfile。
如果outfile=“”,则直接输出output即可。
if (outFile == "") { Console.WriteLine(outPut); } else { FileStream fs = new FileStream(outFile, FileMode.Create); //获得字节数组 byte[] data = System.Text.Encoding.Default.GetBytes(outPut); //开始写入 fs.Write(data, 0, data.Length); //清空缓冲区、关闭流 fs.Flush(); fs.Close(); } Console.ReadKey(); }
八、总结
这次的结对编程项目让我学会了如何去和结对伙伴沟通,两个人一起思考得到的效果是比一个人要好得多,因此在整个程序设计水平上都比我以前有了很大的进展。在这次的解决问题中,我们对每一个出现的问题都分析了其出现的原因,对于以后避免此类问题出现有很大的帮助。同时我也从我的同伴的不同思路中得到了新的启发,总体来说这是一次1+1>2的经历。