我在结对编程的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(" %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] = '