WordCount结对编程
合作人:软件工程 徐建敏 201631062323; 软件工程 林布尔 201631062223;
源代码地址:https://gitee.com/xjm861710023/wordcount_development;
作业链接:https://edu.cnblogs.com/campus/xnsy/2018softwaretest2398/homework/2187;
一,代码互审部分
两人均使用C#语言进行编写,故在合并阶段只需将变量名稍作修改即可。且
命名意义清楚,注释充分,故没有遇到较大阻碍,只是由于本身环境原因(x86架
构匹配问题),在静态代码测试阶段遇到了一些问题,不过得到了有效解决。在代
码检测后修改了部分代码,使得程序更加可靠,但仍有部分警告没能得以解决。
二,代码部分
1)WordCount部分、
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.IO; 6 7 8 namespace wc 9 { 10 public class WC 11 { 12 public string filename; // 文件名 13 public string[] filenames; //多个文件名 14 public string stopwordfile; //停用词文件名 15 public string[] msgSplit; //所有参数数组 16 public string outfile; //输出文件名 17 public string str; //输出字符串 18 public int iccount; // 字符数 19 public int iwcount; // 单词数 20 public int ilcount; // 总行数 21 public int inulllinecount; //空行数 22 public int icodelinecount; //代码行数 23 public int inotelinecount; //注释行数 24 //引入输入字符串,并对字符串进行处理 25 public void Operator(string[] msgSplit) 26 { 27 this.msgSplit = msgSplit; //引入操作数组 28 int Length; 29 Length = msgSplit.Length; 30 foreach (string s in msgSplit) 31 { 32 if (s == "-e") 33 { 34 Length = Length - 2; 35 } 36 else if (s == "-o") 37 { 38 Length = Length - 2; 39 } 40 } 41 this.filename = msgSplit[Length - 1];//获取文件名 42 if (msgSplit[0] == "wc.exe") 43 { 44 foreach (string s in msgSplit) 45 { 46 if (s == "-s") 47 { 48 //获取所有后缀名符合的文件 49 string fileDir = Environment.CurrentDirectory; 50 filenames = Directory.GetFiles(fileDir, filename); 51 } 52 else if (s == "-e") 53 { 54 //获取停用词表文件 55 for (int i = 0; i < msgSplit.Length; i++) 56 { 57 if (msgSplit[i] == "-e") 58 { 59 stopwordfile = msgSplit[i + 1]; 60 } 61 } 62 } 63 } 64 if (filenames == null) 65 { 66 SuperCount(filename); 67 BaseCount(filename, stopwordfile); 68 Display(filename); 69 } 70 else 71 { 72 for (int i = 0; i < filenames.Length; i++) 73 { 74 SuperCount(filenames[i]); 75 BaseCount(filenames[i], stopwordfile); 76 Display(filenames[i]); 77 } 78 } 79 } 80 else 81 { 82 Console.WriteLine("输入指令不存在!请重新输入。。。"); 83 } 84 } 85 // 统计基本信息:字符数 单词数 行数 86 public void BaseCount(string filename, string stopwordfile) 87 { 88 try 89 { 90 // 打开文件 91 FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 92 StreamReader sr = new StreamReader(file); 93 int nChar; 94 int charcount = 0; 95 int wordcount = 0; 96 int linecount = 0; 97 //定义一个字符数组 98 char[] symbol = { ' ', '\t', '\r', ',', '.', '?', '!', ':', ';', '\'', '\"', '\n', '{', '}', '(', ')', '<', '>', '+', '-', '*', '=' }; 99 while ((nChar = sr.Read()) != -1) 100 { 101 charcount++; // 统计字符数 102 if (nChar == '\n') 103 { 104 linecount++; // 统计行数 105 } 106 } 107 sr.Close(); 108 file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); 109 sr = new StreamReader(file); 110 string words = sr.ReadToEnd(); 111 string[] word = words.Split(symbol, StringSplitOptions.RemoveEmptyEntries);//将文件内所有单词分割 112 if (stopwordfile != null) 113 { 114 //有停用词表 115 FileStream stopfile = new FileStream(stopwordfile, FileMode.Open, FileAccess.Read, FileShare.Read); 116 StreamReader stopsr = new StreamReader(stopfile); 117 string stopwords = stopsr.ReadToEnd(); 118 string[] stopword = stopwords.Split(symbol, StringSplitOptions.RemoveEmptyEntries);//将停用词表内所有单词分割 119 foreach (string s in word) 120 { 121 foreach (string stop in stopword) 122 { 123 if (s != stop) 124 { 125 wordcount++;//统计单词数 126 } 127 } 128 } 129 stopsr.Close(); 130 } 131 else 132 { 133 //没有停用词表 134 wordcount = word.Length; 135 } 136 sr.Close(); 137 iccount = charcount; 138 iwcount = wordcount; 139 ilcount = linecount + 1; 140 } 141 catch (IOException ex) 142 { 143 Console.WriteLine(ex.Message); 144 return; 145 } 146 } 147 // 统计代码行 空行 注释行 148 public void SuperCount(string filename) 149 { 150 try 151 { 152 // 打开文件 153 using (FileStream file = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)) 154 { 155 StreamReader sr = new StreamReader(file); 156 String line; 157 int nulllinecount = 0; 158 int codelinecount = 0; 159 int notelinecount = 0; 160 while ((line = sr.ReadLine()) != null) 161 { 162 // 除去每行开头多余空格和格式控制字符 163 line = line.Trim(' '); 164 line = line.Trim('\t'); 165 // 空行 166 if (line == "" || line.Length <= 1) 167 { 168 nulllinecount++; 169 } 170 // 注释行 171 else if (line.Substring(0, 2) == "//" || line.Substring(1, 2) == "//") 172 { 173 notelinecount++; 174 } 175 // 代码行 176 else 177 { 178 codelinecount++; 179 } 180 } 181 inulllinecount = nulllinecount; 182 icodelinecount = codelinecount; 183 inotelinecount = notelinecount; 184 } 185 } 186 catch (IOException ex) 187 { 188 Console.WriteLine(ex.Message); 189 return; 190 } 191 } 192 193 // 打印信息 194 public void Display(string filename) 195 { 196 //将操作命令以-c,-w,-l的顺序输出 197 foreach (string s in msgSplit) 198 { 199 if (s == "-c") //遍历第一次找-c命令,有的话输出字符数 200 { 201 Console.WriteLine(filename + ",字符数:{0}", iccount); 202 str = filename + ",字 符 数:" + iccount + "\r\n"; 203 File.AppendAllText("result.txt", str, Encoding.Default); 204 } 205 } 206 foreach (string s in msgSplit) 207 { 208 if (s == "-w") //遍历第二次找-w命令,有的话输出单词数 209 { 210 Console.WriteLine(filename + ",单词数:{0}", iwcount); 211 str = filename + ",单 词 数:" + iwcount + "\r\n"; 212 File.AppendAllText("result.txt", str, Encoding.Default); 213 } 214 } 215 foreach (string s in msgSplit) 216 { 217 if (s == "-l") //遍历第三次找-l命令,有的话输出行数 218 { 219 Console.WriteLine(filename + ",行 数:{0}", ilcount); 220 str = filename + ",总 行 数:" + ilcount + "\r\n"; 221 File.AppendAllText("result.txt", str, Encoding.Default); 222 } 223 } 224 foreach (string s in msgSplit) 225 { 226 if (s == "-a") //遍历第四次找-a命令,有的话输出代码行/空行/注释行 227 { 228 Console.WriteLine(filename + ",代码行/空行/注释行:{0}/{1}/{2}", icodelinecount, inulllinecount, inotelinecount); 229 str = filename + ",代码行/空行/注释行:" + icodelinecount + '/' + inulllinecount + '/' + inotelinecount + "\r\n"; 230 File.AppendAllText("result.txt", str, Encoding.Default); 231 } 232 } 233 foreach (string s in msgSplit) 234 { 235 if (s == "-o") //遍历第四次找-o命令,有的话将结果存入输出文件 236 { 237 this.outfile = msgSplit[msgSplit.Length - 1]; //引入输出文件名 238 foreach (string st in msgSplit) 239 { 240 if (st == "-c") //遍历第一次找-c命令,有的话将字符数存入输出文档 241 { 242 str = filename + ",字 符 数:" + iccount + "\r\n"; 243 File.AppendAllText("" + outfile + "", str, Encoding.Default); 244 } 245 } 246 foreach (string st in msgSplit) 247 { 248 if (st == "-w") //遍历第二次找-w命令,有的话将单词数存入输出文档 249 { 250 str = filename + ",单 词 数:" + iwcount + "\r\n"; 251 File.AppendAllText("" + outfile + "", str, Encoding.Default); 252 } 253 } 254 foreach (string st in msgSplit) 255 { 256 if (st == "-l") //遍历第三次找-l命令,有的话将行数存入输出文档 257 { 258 str = filename + ",总 行 数:" + ilcount + "\r\n"; 259 File.AppendAllText("" + outfile + "", str, Encoding.Default); 260 } 261 } 262 foreach (string st in msgSplit) 263 { 264 if (st == "-a") //遍历第四次找-a命令,有的话将代码行/空行/注释行存入输出文档 265 { 266 str = filename + ",代码行/空行/注释行:" + icodelinecount + '/' + inulllinecount + '/' + inotelinecount + "\r\n"; 267 File.AppendAllText("" + outfile + "", str, Encoding.Default); 268 } 269 } 270 } 271 } 272 Console.WriteLine(); 273 } 274 } 275 }
2)单元测试部分
1 using System; 2 using System.Text; 3 using System.Collections.Generic; 4 using System.Linq; 5 using Microsoft.VisualStudio.TestTools.UnitTesting; 6 using System.IO; 7 8 namespace TestWC 9 { 10 [TestClass] 11 public class UnitTest1 12 { 13 [TestMethod] 14 public void TestBaseCount() 15 { 16 //测试统计字符数,单词书,行数 17 wc.WC wordcount = new wc.WC(); 18 string filename = "D://myPROJECTS//wc//wc//bin//Debug//file1.c"; 19 string stopwordfile = "D://myPROJECTS//wc//wc//bin//Debug//stop.txt"; 20 wordcount.BaseCount(filename, stopwordfile); 21 int ccount = wordcount.iccount; 22 int wcount = wordcount.iwcount; 23 int lcount = wordcount.ilcount; 24 Assert.AreEqual(87, ccount); 25 Assert.AreEqual(10, wcount); 26 Assert.AreEqual(7, lcount); 27 } 28 [TestMethod] 29 public void TestOperator() 30 { 31 //测试对输入字符串进行引入并处理 32 wc.WC wordcount = new wc.WC(); 33 string[] msgSplit = { "wc.exe", "-c", "-w", "-l", "D://myPROJECTS//wc//wc//bin//Debug//file1.c"}; 34 wordcount.Operator(msgSplit); 35 string filename = wordcount.filename; 36 string stopword = wordcount.stopwordfile; 37 string[] filenames = wordcount.filenames; 38 Assert.AreEqual("D://myPROJECTS//wc//wc//bin//Debug//file1.c", filename); 39 Assert.AreEqual(null, stopword); 40 Assert.AreEqual(null, filenames); 41 } 42 [TestMethod] 43 public void TestSuperCount() 44 { 45 //测试统计代码行 空行 注释行 46 wc.WC wordcount = new wc.WC(); 47 string filename = "D://myPROJECTS//wc//wc//bin//Debug//file1.c"; 48 wordcount.SuperCount(filename); 49 int codecount = wordcount.icodelinecount; 50 int nullcount = wordcount.inulllinecount; 51 int notecount = wordcount.inotelinecount; 52 Assert.AreEqual(4, codecount); 53 Assert.AreEqual(2, nullcount); 54 Assert.AreEqual(1, notecount); 55 } 56 [TestMethod] 57 public void TestDisplay() 58 { 59 //测试输出 60 wc.WC wordcount = new wc.WC(); 61 string[] msg={"wc.exe","-c","D://myPROJECTS//wc//wc//bin//Debug//file1.c"}; 62 wordcount.msgSplit = msg; 63 string filename = "D://myPROJECTS//wc//wc//bin//Debug//file1.c"; 64 wordcount.Display(filename); 65 string result = wordcount.str; 66 Assert.AreEqual("D://myPROJECTS//wc//wc//bin//Debug//file1.c,字 符 数:0\r\n", result); 67 } 68 } 69 }
三,静态代码检查部分
静态代码检查结果如下:
所用静态代码检测工具为visual studio 2010自带的代码检测工具
对于SuperCount中出现的CA2000警告,已通过为file对象添加using释放了被引用的资源,而BaseCount中由于file及stopfile被多次引用,
使用using则无法有效解决问题,并未找到行之有效的处理方法且不会对程序产生重大影响,故此处不再对此警告进行解决。
初次静态代码检测时则遇到了TestWC的“处理器架构“x86”不匹配。这种不匹配可能会导致运行时失败。请考虑通过配置管理器更改您
的项目的目标处理器架构,以使您的项目与引用间的处理器架构保持一致,或者为引用关联一个与您的项目的目标处理器架构相符的处理器架构
”的警告,已通过TestWC配置属性解决,故在此不再赘述。
四,单元测试部分
单元测试全部通过。
五,功能展示部分
程序有WordCount基础功能与拓展功能。
六,心得体会
通过此次结对编程,学会了各种工具的使用方法,相信对我今后的学习能有很大的帮助。