https://github.com/iwannastay/WcPro/tree/stage3/stage3 git
PSP2.1 | PSP階段 | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 30 | 60 |
Estimate | 估計任務須要多少時間 | 30 | 60 |
Development | 開發 | 180 | 240 |
Analysis | 需求分析 | 20 | 30 |
Design Spec | 生成設計文檔 | 20 | 30 |
Design Review | 設計複審 | 20 | 30 |
Coding Standard | 代碼規範 | 30 | 10 |
Design | 具體設計 | 30 | 50 |
Coding | 具體編碼 | 30 | 40 |
Code Review | 代碼複審 | 30 | 40 |
Test | 測試 | 50 | 10 |
Reporting | 報告 | 70 | 240 |
Test Report | 測試報告 | 30 | 100 |
Size Measurement | 計算工做量 | 20 | 60 |
Postmortem | 總結 | 20 | 80 |
合計 | 340 | 540 |
我負責的模塊是單詞排序,即由外部傳入各單詞詞頻,模塊將其排序並輸出。github
因爲是數目未知的數值元素,故能夠將輸入輸出接口定義爲vector<int>數組;數組的排序能夠選擇多種算法如插入排序、合併排序、基數排序、桶排序、快速排序等,因爲處理的文本可能極大,對算法性能要求較高,故此選擇隨機快排實現該接口;然而本程序包含額外的條件——1.單詞詞頻同步輸出,2.同頻的單詞按照字母順序排列,故不能僅用單詞的詞頻做爲接口,而需將單詞自己的索引輸入,因爲外部數據結構未知,故直接引用單詞自己做爲參數,即便用vector<pair<string,int>>做爲模塊外部接口。算法
因爲外部存儲結構使用map<pair<string,int>>,且map的實現機制是紅黑樹的平衡二叉樹,不支持索引操做,爲了便於排序,需進行map->vector的轉換。編程
//詞頻排序 void WcFile::RankProcess() { int count = 0, size = Word_List.size(); map<string, int>::iterator iter = Word_List.begin(); while (iter != Word_List.end()) { Rank_List.push_back(*iter); iter++; } //隨機快排 Random_Quick_Sort(Rank_List, 0, Rank_List.size() - 1); }
排序算法實現數組
//快速排序分劃程序 int WcFile::Partition(vector<pair<string, int>> &A, int p, int q) { auto x = A[p]; int i = p; for (int j = p + 1; j <= q; j++) { if (ComparePriority(A[j],x)) { i = i + 1; Swap(A[i], A[j]); } } Swap(A[p], A[i]); return i; } //隨機化快速排序分劃程序 int WcFile::Random_Partition(vector<pair<string, int>> &A, int p, int q) { int i = rand() % (q - p) + p; Swap(A[i], A[p]); return Partition(A, p, q); } //隨機化快速排序 void WcFile::Random_Quick_Sort(vector<pair<string, int>> &A, int p, int q) { if (p < q) { int i = Random_Partition(A, p, q); Random_Quick_Sort(A, p, i - 1); Random_Quick_Sort(A, i + 1, q); } } //交換元素 void WcFile::Swap(pair<string, int> &m, pair<string, int> &n) { pair<string, int> tmp; tmp = m; m = n; n = tmp; } //首字母排序 bool WcFile::ComparePriority(pair<string, int> &m, pair<string, int> &n) { if (m.second != n.second) return m.second > n.second ? true : false; else return m.first < n.first ? true : false; }
保證設計的測試用例應至少覆蓋函數中全部的可執行語句,同時主要空數組、最差狀況、詞頻排序、字母排序、二者混合等各類狀況設計測試用例。數據結構
試用測試腳本進行單元測試,過程以下:框架
單元測試效果較好,測試結果均正確,且排序性能較高。dom
咱們小組齊心合力,共克難關,積極討論並指出其餘組員的問題,最終得出個人小組貢獻分爲0.3。函數
我選擇了代碼風格規範中:斷行與空白的{}行、分行、命名、下劃線、大小寫;工具
代碼設計規範中:函數、gogo、錯誤處理、斷言(在其餘大型程序中經常使用,在本次做業中未使用)、析構函數、new和delete、類型繼承。
個人編程習慣與以上附錄中所述規範大體相同,少量部分持不一樣意見。而在其餘如代碼審查等重要規範上有待提升。
我分析了組員17027的代碼,縮進、斷行風格整潔,命名簡單明瞭,邏輯清晰易讀,較好地遵照了設計規範。
//導入文件 bool WcFile::LoadFile(const char *_filename) { File_Name = _filename; File_Stream.open(File_Name); if (!File_Stream) { cout << "Fail to open the source file:" << File_Name << endl; system("exit"); } return true; } //保存結果 void WcFile::SaveResult() { File_Stream.close(); File_Stream.open(ResultFile_Name); if (!File_Stream) { cout << "Fail to open the result file." << endl; system("exit"); } for (int i = 0; i < 100 && i < Rank_List.size(); i++) File_Stream << Rank_List[i].first << "\t" << Rank_List[i].second << endl; File_Stream.close(); }
使用Visual Studio 2015 內置檢測工具,可在微軟官方網站https://www.visualstudio.com/zh-hans/downloads/下載
以上問題說明代碼存在數據丟失以及內存泄漏等問題,應儘可能少使用格式自動轉換。
選擇10kb,20kb,50kb大小的txt文件進行測試,程序處理時長以下:
輸入輸出:13ms,14ms,16ms
單詞統計:740ms,1500ms,3800ms
詞頻排序:11ms,12ms,22ms
單詞統計時間與文件大小呈線性相關,其餘兩個模塊佔比較小,故程序性能主要受到文件大小影響。組內共同對代碼結構和細節進行詳細審查,整理獲得優化思路以下:
1.將統計部分中的大小寫轉換提取成單個模塊,能大幅度減小轉換函數的調用次數,隨着文件越大效果越明顯;
2.增長單次提取字符數量,減小主框架循環次數;
3.將字母排序單獨提取成一個模塊,即將排序算法中的比較函數替換爲純數值比較,減小內存開銷,減小排序時間,最後再遍歷數組從新調整同頻單詞順序,此方法在數組較大時可以提升程序效率。
使用MFC開發環境,設計具備圖形界面的文件選擇工具。
經過基本任務、擴展任務、到高級任務的完成以及中間遇到的許多困難,體現出了軟件測試對於軟件開發的重要性。在開發過程當中,使用靜態測試工具實時地檢測本身的代碼,能夠改正本身不良的編程習慣,更能防患於未然,減小出現bug的可能;對本身的模塊進行單元測試,能夠保障本身代碼的正確性,更是對其餘開發成員和整個任務的負責,使軟件開發可以一步一個腳印地穩定開展;對性能的分析與測試,能使軟件的質量進一步提升,同事能總結開發經驗,使本身設計的模塊更加高效。