第四次作业——结对编程
这个作业要求在哪里:第四次作业要求
Github项目地址:Wordcount
伙伴作业地址:iron-man
PSP表格:
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
15 |
30 |
· Estimate |
· 估计这个任务需要多少时间 |
30 |
30 |
Development |
开发 |
360 |
360 |
· Analysis |
· 需求分析 (包括学习新技术) |
60 |
90 |
· Design Spec |
· 生成设计文档 |
45 |
45 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
60 |
60 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
60 |
90 |
· Design |
· 具体设计 |
60 |
60 |
· Coding |
· 具体编码 |
300 |
300 |
· Code Review |
· 代码复审 |
60 |
60 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
60 |
30 |
Reporting |
报告 |
30 |
30 |
· Test Report |
· 测试报告 |
30 |
30 |
· Size Measurement |
· 计算工作量 |
30 |
45 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
45 |
|
合计 |
1230 |
1305 |
解题思路
刚得到题目,分析它的难易程度时,发现查找到单词以及词组运用正则运算来匹配的话,会匹配到单词前面的分割符,所以就if语句来进行判断。由于c#掌握的不是很熟练,在csdn博客上查找了文件读取,字符分割及拼接,正则匹配的符号
设计实现过程
首先main函数来获取参数,并传递给ReadTxt函数,Readtxt函数调用wordnumber函数来构建分割字符数组,并且得到字符串数组;传递给wordn,wordn函数将其整合成两个单词列表,
将sdx列表传给wordcount来统计词组,最后又回到readtxt输出到文件中。
将sd列表传给listdo函数统计单词出现的次数,然后又交给chosewords函数排序,最后在readtxt函数输出到文件中。
把简单的功能设计出来了,把统计行数、统计字符数放在了firstcount函数里。最后也是在在readtxt函数输出到文件中。
代码规范
命名规范,不能简写或用首字母代替。关键地方一定要注释,把函数的作用,参数的含义都注释出来。
代码说明
函数WordN(string[] ma,int h)作用是:将分割文件数据字符串得到的字符列表。
public static List<string> WordN(string[] ma,int h) { List<string> sd = new List<string>(); List<string> sdx = new List<string>();//建立一个存储词组的列表 int i = 0; foreach (string s in ma) //遍历集合中每个单词 { if(s!=="") { if(s.Length<4) { sdx.Add("!no"); } else { int j = 1; for (i = 0; i < 4; i++) { if (((s[i] >= 'a') && (s[i] <= 'z')) || ((s[i] >= 'A') && (s[i] <= 'Z'))) { } else { j = 0; break; } } if (j == 1) { string s2 = s.ToLower(); sd.Add(s2); sdx.Add(s); } else { sdx.Add("!no"); } } } } sdx.Add("!no"); if (h == 0) return sd; else return sdx; }
函数wordcount作用是:将函数wordn返回的字符串列表sdx,进行词组统计,将每一个词组都先后存入字符串列表ac中,然后返回ac
public static List<string> WordsCount(List<string> sdx,int n) { List<string> ad = new List<string>(); int i = 0; List<string> ac = new List<string>(); foreach (string s in sdx) { if(s=="!no") { while(i>=n) { string ae=""; int j = 0; foreach (string af in ad) { ae+=af+" "; j++; if(j ==n) { ac.Add(ae); break; } } ad.RemoveAt(0); i--; } ad.Clear(); i = 0; } else { ad.Add(s);//这是一个大的词组 i++; } } return ac; }
函数readtext的作用是:将词组和单词和字符数,行数,单词数,输入到指定文件夹。
public static void ReadTxt(string path,string outpath,int n,int number,int a,int b) { Dictionary<string, int> e = new Dictionary<string, int>();//筛选后的词典 StreamReader sr = new StreamReader(path, Encoding.utf8); string restOfStream = sr.ReadToEnd(); if (outpath != "out") { StreamWriter sw = new StreamWriter(outpath, false);//true表示追加 sw.WriteLine("characters: " + a); sw.WriteLine("words: " + WordN(WordNumber(restOfStream), 0).Count()); sw.WriteLine("lines: " + b); //输出单词 if (number > 0) { e = Chosewords(Listdo(WordN(WordNumber(restOfStream), 0)), number); foreach (string s in e.Keys) { sw.WriteLine("<" + s + ">: " + e[s]); } } if (n > 0) { List<string> ac = WordsCount(WordN(WordNumber(restOfStream), 1), n); for (int k=0;k) { if(ac[k] != "!no") { string xs = ac[k]; sw.Write(xs); int numa = 0; for(int u=0;u ) { if (ac[u] == xs) { ac[u] = "!no"; numa++; } } sw.WriteLine(": " + numa); } } } sw.Flush(); sw.Close(); } }
main函数是提供readtext函数需要的参数
static void Main(string[] args) { string p ="in";//输入文件路径 string q="out";//输出文件路径 int n=0;//词组长度 int number=0;//输出单词个数 for (int i=0;i) { switch (args[i]) { case "-i":p = args[i + 1];break; case "-o": q = args[i + 1]; break; case "-m": n=int.Parse(args[i+1]); break; case "-n": number= int.Parse(args[i+1]); break; } i++; } //计算字符数汉字除外 int a = FirstCount(p,0); //计算非空行数 int b = FirstCount(p,1); //输出到目标文件 ReadTxt(p,q,n,number,a,b); }
错误处理并设计单元测试
创建单元测试,这里只展示出错的函数测试
单元测试没有通过,修改了源码,发现了很多新的问题
第一个问题是读取文件时没有使用utf8编码,导致汉字占用了后面单词的空间,改变了单词的长度
不过及时地找出了这个问题的原因,并且解决了
然而解决完上面这个问题,新的问题又出现了,
把字符串数组换行输出,发现数组存在空字符串
最终测试通过
效能分析
加入以下代码,进行效能分析
效能分析结果如下
做了很多次测试与更改,最终编译成功
f) 结对感受
从这次作业中可以感受到结对编程的魅力,1+1是大于2的,在这个过程中,两个人能够互相监督和学习,发现并指出对方的错误。多一个人就多一份力,虽然因为基础不一样可能不能很快达成共识,但是这个过程也是一种学习。在这次结对编程中也让我认识到了我基础的不足,感谢小伙伴的耐心指导。