代码复审作业
我在结对编程的partner是程刚(博客 cnblogs.com/a1071986199/),以下是我对其个人项目(词频统计)的复审结果。
partner是用c++写的,只包含一个文件,是面向过程的程序。
代码写得好的地方:
一、程序流程较清晰。
二、变量命名能做到顾名思义。
代码存在的问题:
一、模块化设计不合理。
程序主要模块分为3个:main——交互;DirectoryList——扫描所有文件,并统计所有单词;Output——对单词进行排序,并输出结果
问题有:
1. DirectoryList实现的功能太多,模块庞大,难以维护。
2. Output包含了附加功能——排序,而这个单独作为一个模块会更好。
二、代码冗余度高
1. Output模块共设计了3个,分别对应3种模式。它们除了参数中泛型类型参数不同之外,代码几乎一样。
2. 在DirectoryList函数中,对于flag(即模式)的3个分支太多冗余代码。
进行重构是一个很好的选择。
三、代码重用度低
1. 在DirectoryList中的参数,为3个模式分别设置了3个vector参数。不仅其中两个参数将会变成打酱油的(取决于另一个参数flag),而且,如果需求变动(增加或减少模式),改动代价将会很大。
2. DirectoryList内置文件后缀名的筛选。如果需求变动,那么很难发现需要更改的地方。将其设置为接口会更好。
四、算法复杂度高
建立单词表时,每新增一个单词就要与单词表中所有项进行比较,效率太低。建议是以单词的小写形式为索引,维护一个有序表,这样在查找或更改时可以利用二分法缩短时间。
附上partner的源代码:
1 // ConsoleApplication1.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include <windows.h> 6 #include <string> 7 #include <fstream> 8 #include <vector> 9 #include <cstring> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 14 #define LEN 1024 15 16 BOOL Is_Letter(char c) 17 { 18 if ((c >= 'A' && c <= 'Z' )||( c<='z' && c >= 'a')) return true; 19 else return false; 20 } 21 22 BOOL Is_Number(char c) 23 { 24 if (c >= '0'&&c <= '9') return true; 25 else return false; 26 } 27 28 BOOL Is_OneWord(char letter[],string vec_word) 29 { 30 string Letter = letter; 31 transform(Letter.begin(), Letter.end(), Letter.begin(), toupper); 32 transform(vec_word.begin(), vec_word.end(), vec_word.begin(), toupper); 33 if (Letter == vec_word) return true; 34 else return false; 35 } 36 struct one 37 { 38 string word; 39 int num; 40 }; 41 struct two 42 { 43 string word1; 44 string word2; 45 int num; 46 }; 47 struct three 48 { 49 string word1; 50 string word2; 51 string word3; 52 int num; 53 }; 54 void One_Output(vector<one> *vec1) 55 { 56 int i, j, size; 57 size = (*vec1).size(); 58 one temp; 59 for (i = 0; i < size; i++) 60 { 61 int index = i; 62 for (j = i; j < size; j++) 63 { 64 if (((*vec1)[index].num < (*vec1)[j].num) || ((*vec1)[index].num == (*vec1)[j].num&& 65 (*vec1)[index].word>(*vec1)[j].word)) index = j; 66 } 67 if (i != index) 68 { 69 temp.word = (*vec1)[i].word; 70 temp.num = (*vec1)[i].num; 71 (*vec1)[i].word = (*vec1)[index].word; 72 (*vec1)[i].num = (*vec1)[index].num; 73 (*vec1)[index].word = temp.word; 74 (*vec1)[index].num = temp.num; 75 } 76 } 77 78 ofstream fout("程刚.txt", ios::out); 79 size = (*vec1).size(); 80 for (i = 0; i < size; i++) 81 fout << (*vec1)[i].word << ": " << (*vec1)[i].num << endl; 82 cout << "程序结束" << endl; 83 } 84 void Two_Output(vector<two> *vec1) 85 { 86 int i, j, size; 87 size = (*vec1).size(); 88 two temp; 89 for (i = 0; i < size; i++) 90 { 91 int index = i; 92 for (j = i; j < size; j++) 93 { 94 if ( (*vec1)[index].num < (*vec1)[j].num || ((*vec1)[index].num == (*vec1)[j].num && 95 (*vec1)[index].word1>(*vec1)[j].word1) || ((*vec1)[index].num == (*vec1)[j].num && 96 (*vec1)[index].word1 == (*vec1)[j].word1) && ((*vec1)[index].word2 >(*vec1)[j].word2) ) 97 index = j; 98 } 99 if (i != index) 100 { 101 temp.word1 = (*vec1)[i].word1; 102 temp.word2 = (*vec1)[i].word2; 103 temp.num = (*vec1)[i].num; 104 (*vec1)[i].word1 = (*vec1)[index].word1; 105 (*vec1)[i].word2 = (*vec1)[index].word2; 106 (*vec1)[i].num = (*vec1)[index].num; 107 (*vec1)[index].word1 = temp.word1; 108 (*vec1)[index].word2 = temp.word2; 109 (*vec1)[index].num = temp.num; 110 } 111 } 112 113 ofstream fout("程刚.txt", ios::out); 114 size = (*vec1).size(); 115 for (i = 0; i < size && i < 10; i++) 116 fout << (*vec1)[i].word1 << " " << (*vec1)[i].word2 << ": " << (*vec1)[i].num << endl; 117 cout << "程序结束" << endl; 118 } 119 void Three_Output(vector<three> *vec1) 120 { 121 int i, j, size; 122 size = (*vec1).size(); 123 three temp; 124 for (i = 0; i < size ; i++) 125 { 126 int index = i; 127 for (j = i; j < size; j++) 128 { 129 if (((*vec1)[index].num < (*vec1)[j].num) || 130 ((*vec1)[index].num == (*vec1)[j].num &&(*vec1)[index].word1>(*vec1)[j].word1) || 131 ((*vec1)[index].num == (*vec1)[j].num && ((*vec1)[index].word1 == (*vec1)[j].word1) && (*vec1)[index].word2 >(*vec1)[j].word2) || 132 ((*vec1)[index].word1 == (*vec1)[j].word1) && (*vec1)[index].word2 == (*vec1)[j].word2 && (*vec1)[index].word3 >(*vec1)[j].word3) 133 index = j; 134 135 } 136 if (i != index) 137 { 138 temp.word1 = (*vec1)[i].word1; 139 temp.word2 = (*vec1)[i].word2; 140 temp.word3 = (*vec1)[i].word3; 141 temp.num = (*vec1)[i].num; 142 (*vec1)[i].word1= (*vec1)[index].word1; 143 (*vec1)[i].word2 = (*vec1)[index].word2; 144 (*vec1)[i].word3 = (*vec1)[index].word3; 145 (*vec1)[i].num = (*vec1)[index].num; 146 (*vec1)[index].word1 = temp.word1; 147 (*vec1)[index].word2 = temp.word2; 148 (*vec1)[index].word3 = temp.word3; 149 (*vec1)[index].num = temp.num; 150 } 151 } 152 153 ofstream fout("程刚.txt", ios::out); 154 size = (*vec1).size(); 155 for (i = 0; i < size && i < 10; i++) 156 fout << (*vec1)[i].word1 << " "<<(*vec1)[i].word2 <<(*vec1)[i].word3 << ": " << (*vec1)[i].num << endl; 157 cout << "程序结束" << endl; 158 } 159 // 深度优先递归遍历目录中所有的文件,参考网上代码 160 int DirectoryList(LPCSTR Path, int flag, vector<one> *key1, vector<two> *key2, vector<three> *key3) 161 { 162 WIN32_FIND_DATA FindData; 163 HANDLE hError; 164 char FilePathName[LEN]; 165 // 构造路径 166 char FullPathName[LEN]; 167 strcpy_s(FilePathName, Path); 168 strcat_s(FilePathName, "\\*.*"); 169 hError = FindFirstFile(FilePathName, &FindData); 170 if (hError == INVALID_HANDLE_VALUE) 171 { 172 printf("搜索失败!"); 173 return 0; 174 } 175 while (::FindNextFile(hError, &FindData)) 176 { 177 // 过虑.和.. 178 if (strcmp(FindData.cFileName, ".") == 0 179 || strcmp(FindData.cFileName, "..") == 0) 180 { 181 continue; 182 } 183 184 // 构造完整路径 185 wsprintf(FullPathName, "%s\\%s", Path, FindData.cFileName); 186 // 输出本级的文件 187 printf("\n %s ", FullPathName); 188 189 if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 190 { 191 printf("<Dir>"); 192 DirectoryList(FullPathName,flag,key1,key2,key3); 193 } 194 char *suffix; 195 suffix = strrchr(FullPathName, '.'); 196 if (suffix==0) continue; 197 //如果是.txt、.cpp、.cs、.h结尾的文件后缀,进行文件读取和词频统计 198 if (strcmp(suffix, ".txt") ==0|| strcmp(suffix, ".cpp")==0 || strcmp(suffix, ".cs")==0 || strcmp(suffix, ".h")==0) 199 { 200 if (flag == 1) 201 { 202 ifstream in(FullPathName); 203 char c; 204 int CharacterFlag = 0; 205 int LetterCount = 0; 206 char Letter[LEN]; 207 int i; 208 one temp; 209 while (!in.eof()) 210 { 211 c = in.get(); 212 if (Is_Letter(c)) { Letter[LetterCount] = c; LetterCount++; } 213 else if (Is_Number(c) && LetterCount >= 3) { 214 CharacterFlag = 1; 215 Letter[LetterCount] = c; LetterCount++; 216 } 217 else if (!Is_Letter(c) && !Is_Number(c) && (CharacterFlag == 1 || LetterCount >= 3)) 218 { 219 Letter[LetterCount] = '\0'; 220 for (i = 0; i < int((*key1).size()); i++) 221 { 222 if (Is_OneWord(Letter, (*key1)[i].word)) { 223 if (Letter < (*key1)[i].word) (*key1)[i].word = Letter; 224 (*key1)[i].num++; break; 225 } 226 } 227 if ((*key1).size() == 0 || i == (*key1).size()) { 228 temp.word = Letter; temp.num = 1; 229 (*key1).push_back(temp); 230 } 231 LetterCount = 0; 232 CharacterFlag = 0; 233 } 234 else if (!Is_Letter(c) && !Is_Number(c) && !(LetterCount >= 3)) 235 { 236 LetterCount = 0; 237 CharacterFlag = 0; 238 } 239 else if (Is_Number(c) && !(LetterCount >= 3)) 240 { 241 LetterCount = 0; 242 CharacterFlag = 0; 243 } 244 } 245 in.close(); 246 } 247 if (flag == 2) 248 { 249 ifstream in(FullPathName); 250 char c; 251 int CharacterFlag = 0; 252 int LetterCount = 0; 253 int WordNum = 0; 254 char Letter1[LEN]; 255 char Letter2[LEN]; 256 int i; 257 two temp; 258 while (!in.eof()) 259 { 260 c = in.get(); 261 if (WordNum == 0) 262 { 263 if (Is_Letter(c)) { Letter1[LetterCount] = c; LetterCount++; } 264 else if (Is_Number(c) && LetterCount >= 3) { 265 CharacterFlag = 1; 266 Letter1[LetterCount] = c; LetterCount++; 267 } 268 else if (Is_Number(c) && !(LetterCount >= 3)) 269 { 270 LetterCount = 0; 271 CharacterFlag = 0; 272 } 273 else if (!Is_Letter(c) && !Is_Number(c)) 274 { 275 if (!(LetterCount >= 3)) { 276 LetterCount = 0; 277 CharacterFlag = 0; 278 } 279 else if (LetterCount >= 3 && c == ' ') 280 { 281 Letter1[LetterCount] = '\0'; 282 LetterCount = 0; 283 CharacterFlag = 0; 284 WordNum = 1; 285 } 286 else { 287 LetterCount = 0; 288 CharacterFlag = 0; 289 WordNum = 0; 290 } 291 } 292 } 293 else if (WordNum == 1) 294 { 295 if (Is_Letter(c)) { Letter2[LetterCount] = c; LetterCount++; } 296 else if (Is_Number(c) && LetterCount >= 3) { 297 CharacterFlag = 1; 298 Letter2[LetterCount] = c; LetterCount++; 299 } 300 else if (Is_Number(c) && !(LetterCount >= 3)) 301 { 302 LetterCount = 0; 303 CharacterFlag = 0; 304 WordNum = 0; 305 } 306 else if (!Is_Letter(c) && !Is_Number(c)) 307 { 308 if (!(LetterCount >= 3)) 309 { 310 LetterCount = 0; 311 CharacterFlag = 0; 312 WordNum = 0; 313 } 314 else if (LetterCount >= 3) 315 { 316 Letter2[LetterCount] = '\0'; 317 for (i = 0; i < int((*key2).size()); i++) 318 { 319 if (Is_OneWord(Letter1, (*key2)[i].word1) && 320 Is_OneWord(Letter2, (*key2)[i].word2)) 321 { 322 if (Letter1 < (*key2)[i].word1 || (Letter1 == (*key2)[i].word1&& 323 Letter2 < (*key2)[i].word2)) 324 { 325 (*key2)[i].word1 = Letter1; (*key2)[i].word2 = Letter2; 326 } 327 (*key2)[i].num++; break; 328 } 329 } 330 if ((*key2).size() == 0 || i == (*key2).size()) 331 { 332 temp.word1 = Letter1; temp.word2 = Letter2; temp.num = 1; 333 (*key2).push_back(temp); 334 } 335 LetterCount = 0; 336 CharacterFlag = 0; 337 WordNum = 0; 338 if (c == ' ') 339 { 340 strcpy_s(Letter1, Letter2); 341 WordNum = 1; 342 } 343 } 344 } 345 } 346 } 347 in.close(); 348 } 349 if (flag == 3) 350 { 351 ifstream in(FullPathName); 352 char c; 353 int CharacterFlag = 0; 354 int LetterCount = 0; 355 int WordNum = 0; 356 char Letter1[LEN]; 357 char Letter2[LEN]; 358 char Letter3[LEN]; 359 int i; 360 three temp; 361 while (!in.eof()) 362 { 363 c = in.get(); 364 if (WordNum == 0) 365 { 366 if (Is_Letter(c)) { Letter1[LetterCount] = c; LetterCount++; } 367 else if (Is_Number(c) && LetterCount >= 3) 368 { 369 CharacterFlag = 1; 370 Letter1[LetterCount] = c; LetterCount++; 371 } 372 else if (Is_Number(c) && !(LetterCount >= 3)) 373 { 374 LetterCount = 0; 375 CharacterFlag = 0; 376 WordNum = 0; 377 } 378 else if (!Is_Letter(c) && !Is_Number(c)) 379 { 380 if (!(LetterCount >= 3)) 381 { 382 LetterCount = 0; 383 CharacterFlag = 0; 384 WordNum = 0; 385 } 386 else if (LetterCount >= 3) 387 { 388 WordNum = 0; 389 if (c == ' ') 390 { 391 Letter1[LetterCount] = '\0'; 392 WordNum = 1; 393 } 394 LetterCount = 0; 395 CharacterFlag = 0; 396 } 397 } 398 } 399 else if (WordNum == 1) 400 { 401 if (Is_Letter(c)) { Letter2[LetterCount] = c; LetterCount++; } 402 else if (Is_Number(c) && LetterCount >= 3) 403 { 404 CharacterFlag = 1; 405 Letter2[LetterCount] = c; LetterCount++; 406 } 407 else if (Is_Number(c) && !(LetterCount >= 3)) 408 { 409 LetterCount = 0; 410 CharacterFlag = 0; 411 WordNum = 0; 412 } 413 else if (!Is_Letter(c) && !Is_Number(c)) 414 { 415 if (!(LetterCount >= 3)) 416 { 417 LetterCount = 0; 418 CharacterFlag = 0; 419 WordNum = 0; 420 } 421 else if (LetterCount >= 3) 422 { 423 Letter2[LetterCount] = '\0'; 424 LetterCount = 0; 425 CharacterFlag = 0; 426 WordNum = 0; 427 if (c == ' ') 428 { 429 WordNum = 2; 430 } 431 } 432 } 433 } 434 else if (WordNum == 2) 435 { 436 if (Is_Letter(c)) { Letter3[LetterCount] = c; LetterCount++; } 437 else if (Is_Number(c) && LetterCount >= 3) 438 { 439 CharacterFlag = 1; 440 Letter3[LetterCount] = c; LetterCount++; 441 } 442 else if (Is_Number(c) && !(LetterCount >= 3)) 443 { 444 LetterCount = 0; 445 CharacterFlag = 0; 446 WordNum = 0; 447 } 448 else if (!Is_Letter(c) && !Is_Number(c) ) 449 { 450 if (!(LetterCount >= 3)) 451 { 452 LetterCount = 0; 453 CharacterFlag = 0; 454 WordNum = 0; 455 } 456 else if (LetterCount >= 3) 457 { 458 Letter3[LetterCount] = '\0'; 459 for (i = 0; i < int((*key3).size()); i++) 460 { 461 if (Is_OneWord(Letter1, (*key3)[i].word1) && 462 Is_OneWord(Letter2, (*key3)[i].word2) && 463 Is_OneWord(Letter3, (*key3)[i].word3)) 464 { 465 if (Letter1 < (*key3)[i].word1 || (Letter1 == (*key3)[i].word1&& 466 Letter2 < (*key3)[i].word2) || (Letter1 == (*key3)[i].word1 && 467 Letter2 == (*key3)[i].word2 && Letter3 < (*key3)[i].word3)) 468 { 469 (*key3)[i].word1 = Letter1; (*key3)[i].word2 = Letter2; 470 (*key3)[i].word3 = Letter3; 471 } 472 (*key3)[i].num++; break; 473 } 474 } 475 if ((*key3).size() == 0 || i == (*key3).size()) { 476 temp.word1 = Letter1; temp.word2 = Letter2; temp.word3 = Letter3; 477 temp.num = 1; 478 (*key3).push_back(temp); 479 } 480 LetterCount = 0; 481 CharacterFlag = 0; 482 WordNum = 0; 483 if (c == ' ') 484 { 485 strcpy_s(Letter1, Letter2); 486 strcpy_s(Letter2, Letter3); 487 WordNum = 2; 488 } 489 } 490 } 491 } 492 } 493 in.close(); 494 } 495 } 496 } 497 return 0; 498 } 499 500 int main(int argc, char* argv[]) 501 { 502 int flag=1; 503 char path[LEN]; 504 if (argv[1] == "") return 0; 505 vector<one> first; 506 vector<two> second; 507 vector<three> third; 508 if (argv[1][0] == '-'&&argv[1][1] == 'e'&&argv[1][2] == '2') 509 { 510 flag = 2; 511 DirectoryList(argv[2], flag, &first,&second,&third); 512 Two_Output(&second); 513 } 514 else if (argv[1][0] == '-'&&argv[1][1] == 'e'&&argv[1][2] == '3') 515 { 516 flag = 3; 517 DirectoryList(argv[2], flag, &first, &second, &third); 518 Three_Output(&third); 519 } 520 else if(argc=2) 521 { 522 flag = 1; 523 DirectoryList(argv[1], flag, &first, &second, &third); 524 One_Output(&first); 525 } 526 return 0; 527 }