PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 30 |
· Estimate | · 估计这个任务须要多少时间 | 60 | 30 |
Development | 开发 | 1680 | 2320 |
· Analysis | · 需求分析 (包括学习新技术) | 120 | 100 |
· Design Spec | · 生成设计文档 | 30 | 30 |
· Design Review | · 设计复审 (和同事审核设计文档) | 30 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
· Design | · 具体设计 | 60 | 120 |
· Coding | · 具体编码 | 1200 | 1680 |
· Code Review | · 代码复审 | 30 | 40 |
· Test | · 测试(自我测试,修改代码,提交修改) | 180 | 300 |
Reporting | 报告 | 390 | 510 |
· Test Report | · 测试报告 | 180 | 200 |
· Size Measurement | · 计算工做量 | 30 | 10 |
· Postmortem & Process Improvement Plan | · 过后总结, 并提出过程改进计划 | 180 | 300 |
合计 | 2130 | 2860 |
In computing and systems design a loosely coupled system is one in which each of its components has, or makes use of, little or no knowledge of the definitions of other separate components. Subareas include the coupling of classes, interfaces, data, and services.[1] Loose coupling is the opposite of tight coupling.git
——引用自维基百科程序员
void InputHandler(int argc, char* argv[], bool &enable_loop, int &word_or_char, char &head, char &tail, string &Filename); void ReadFile(string FileName, vector<string> &words); void DFS_Length(Graph G, int v, vector<string> words, char tail);
之前作过相似的题,输入的全部单词可否所有首尾相连造成链。因为单词首尾相连有多种链接方式,故基本的数据结构为图。
建图有两种方式,一种是以单词为节点,若是单词间正好能够首尾链接,则添加一条边,该边即为链接的字母。另外一种建图方式是以字母为节点,以单词为边,出现一个单词,即把首字母节点向尾字母节点添加一条边,边的值即为该单词。
对于这道题目而言,因为单词须要输出,加之对第二种建图方式掌握并不熟练,所以选择的是第一种建图方式。
模型确立后,问题就能够简化成“求图中的最长链”,即最长路径问题,显然问题是多源最长路径问题。github
数据结构为图,存储方式为邻接矩阵,理由是能更契合floyd算法。
对于无环状况,因为为多源最长路径问题,联想到最短路径问题,能够肯定为floyd算法。
而对于有环状况,因为出现了正值环,floyd算法再也不适用。在找不到更有解决方法的状况下,只能适用DFS深度优先搜索求解。算法
ReadFile: 读取文件的模块,将文件中的单词提取进入容器vector中。
Graph: 图的定义。
InputHandler:处理输入的模块,读取命令行并处理参数。
FindLongestWordList: 计算模块,内含计算接口。计算出单词中的最长链。编程
首先须要判断有无环,对于没有-r参数的输入来讲,若是有环须要报错。这里也是用到DFS的染色算法。每一个点有三种状态:未遍历过,遍历过,当前序列正在遍历。若是一次DFS中一个点与正在遍历中的点相连了,说明DFS回到了以前的点,即图中有环。
另外一问题是因为无环状况最多可有10000个单词,而floyd算法时间复杂度为O(n^3),暴力的计算显然是不行的。考虑到对于无环的状况,有以下特性:对于单词element和elephant,因为无环,这两个单词最多只有一个会出如今链中。(不然会出现element, t..., ..., ....e, elephant / element,这样必定是有环的),而若是要知足字母最多,显然这时候须要选择elephant加入链中。所以咱们能够对于全部首尾字母相同的单词,保留首尾字母组合中,最长的一个单词。这样的操做以后,最多的单词数目为351,即便是时间复杂度O(n^3)的算法也能很快得出结果。另外能够计算得,最长链的长度最大为51。数组
——优缺点引用自维基百科数据结构
TEST_METHOD(TestMethod3) { // TODO: normal_test3 char* words[101] = { "element", "heaven", "table", "teach", "talk"}; char* answer[101]; for (int i = 0; i < 101; i++) { answer[i] = (char*)malloc(sizeof(char) * 601); } int l = gen_chain_word(words, 5, answer, 0, 0, true); Assert::AreEqual(l, 4); Assert::AreEqual("table", answer[0]); Assert::AreEqual("element", answer[1]); Assert::AreEqual("teach", answer[2]); Assert::AreEqual("heaven", answer[3]); for (int i = 0; i < 101; i++) { free(answer[i]); } }
TEST_METHOD(TestMethod6) { // TODO: normal_test6 char* words[101] = { "apple", "banane", "cane", "a", "papa", "erase" }; char* answer[101]; for (int i = 0; i < 101; i++) { answer[i] = (char*)malloc(sizeof(char) * 601); } int l = gen_chain_char(words, 6, answer, 'a', 'e', false); Assert::AreEqual(l, 3); Assert::AreEqual("a", answer[0]); Assert::AreEqual("apple", answer[1]); Assert::AreEqual("erase", answer[2]); for (int i = 0; i < 101; i++) { free(answer[i]); } }
TEST_METHOD(TestMethod2) { // 正确_2 int argc = 6; char* argv[101] = { "Wordlist.exe", "-r", "-h", "a", "-c", "test_1.txt" }; char head; char tail; bool enable_loop; int word_or_char = 0; string Filename; InputHandler(argc, argv, enable_loop, word_or_char, head, tail, Filename); Assert::AreEqual(enable_loop, true); Assert::AreEqual(word_or_char, 2); Assert::AreEqual(head, 'a'); Assert::AreEqual(tail, char(0)); Assert::AreEqual(Filename, (string)"test_1.txt"); }
单元测试覆盖率截图(因为C++没有找到直接测试单元测试覆盖率的插件,这里用的方法是将单元测试代码移至main函数中用OpenCppCoverage插件获得的覆盖率,部分异常测试没有放进来,因此覆盖率没有达到100%)app
TEST_METHOD(TestMethod3) { // 错误_1 int argc = 5; char* argv[101] = { "Wordlist.exe", "-r", "-r", "-c", "test_1.txt" }; char head; char tail; bool enable_loop; int word_or_char = 0; string Filename; try { InputHandler(argc, argv, enable_loop, word_or_char, head, tail, Filename); Assert::IsTrue(false); } catch (myexception1& e) { Assert::IsTrue(true); } catch (...) { Assert::IsTrue(false); } }
这个单元测试是‘-r’出现了两次,错误的参数组合。函数
TEST_METHOD(TestMethod7) { // 错误_5 int argc = 6; char* argv[101] = { "Wordlist.exe", "-r", "-h", "1", "-c", "test_1.txt" }; char head; char tail; bool enable_loop; int word_or_char = 0; string Filename; try { InputHandler(argc, argv, enable_loop, word_or_char, head, tail, Filename); Assert::IsTrue(false); } catch (myexception2& e) { Assert::IsTrue(true); } catch (...) { Assert::IsTrue(false); } }
这个单元测试是‘-h’指定首字母为‘1’,明显是错误的。oop
TEST_METHOD(TestMethod9) { // 错误_7 int argc = 5; char* argv[101] = { "Wordlist.exe", "-b", "-r", "-c", "test_1.txt" }; char head; char tail; bool enable_loop; int word_or_char = 0; string Filename; try { InputHandler(argc, argv, enable_loop, word_or_char, head, tail, Filename); Assert::IsTrue(false); } catch (myexception3& e) { Assert::IsTrue(true); } catch (...) { Assert::IsTrue(false); } }
这个单元测试是输入参数‘-b’显然是不符合规定的。
TEST_METHOD(TestMethod2) { // 错误 vector <string> words; try { ReadFile("normal_test3.txt", words); // 不存在的文件 Assert::IsTrue(false); } catch (myexception4& e) { Assert::IsTrue(true); } catch (...) { Assert::IsTrue(false); } }
这个单元测试是测试了一个在此路径下不存在的文件。
TEST_METHOD(TestMethod2) { // 错误 vector <string> words; try { ReadFile("long_word_test.txt", words); Assert::IsTrue(false); } catch (myexception4& e) { Assert::IsTrue(true); } catch (...) { Assert::IsTrue(false); } }
这个单元测试是文件中存在长度超过600的单词。
TEST_METHOD(TestMethod2) { // 错误 vector <string> words; try { ReadFile("more_words_test.txt", words); Assert::IsTrue(false); } catch (myexception4& e) { Assert::IsTrue(true); } catch (...) { Assert::IsTrue(false); } }
这个单元测试是所测试文件中单词数超过了10000。
TEST_METHOD(TestMethod10) { // wrong_test2 char* words[101] = { "alement", "oeaven", "tabla", "teaco", "talk" }; char* answer[101]; for (int i = 0; i < 101; i++) { answer[i] = (char*)malloc(sizeof(char) * 601); } try { int l = gen_chain_char(words, 5, answer, 0, 'n', false); Assert::IsTrue(false); } catch (myexception7& e) { Assert::IsTrue(true); } catch (...) { Assert::IsTrue(false); } }
这个单元测试是传入单词能够造成环,且用户没有传入参数‘-r’。
TEST_METHOD(TestMethod11) { // wrong_test3 char* words[101] = { "alement", "oeaven", "tabla", "teaco", "talk" }; char* answer[101]; for (int i = 0; i < 101; i++) { answer[i] = (char*)malloc(sizeof(char) * 601); } try { int l = gen_chain_word(words, 5, answer, 'b', 'n', true); Assert::IsTrue(false); } catch (myexception8& e) { Assert::IsTrue(true); } catch (...) { Assert::IsTrue(false); } }
这个单元测试是规定了首尾字母后,单词链中没有用户所要求的单词链。