PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 60 | 10 |
Estimate | 估計這個任務須要多長時間 | 20 | 20 |
Development | 開發 | 600 | 720 |
Analysis | 需求分析(包括學習新技術) | 300 | 360 |
Design Spec | 設計生成文檔 | 30 | 20 |
Design Review | 設計複審 | 30 | 20 |
Coding Standard | 代碼規範(爲目前開發指定合適的規範) | 20 | 20 |
Design | 具體設計 | 50 | 40 |
Coding | 具體編碼 | 500 | 600 |
Code review | 代碼複審 | 100 | 180 |
Test | 測試(自我測試,修改代碼,提交修改) | 100 | 180 |
Reporting | 報告 | 30 | 60 |
Test Report | 測試報告 | 20 | 50 |
Size Measurement | 計算工做量 | 120 | 30 |
Postmortem & Process Improvement Plan | 過後總結,並提出過程改進計劃 | 200 | 20 |
合計 | 2180 | 1550 |
在剛開始拿到題目的時候,其實對於這種未知的項目仍是很恐慌的,看到後面的各類什麼性能分析報告,代碼覆蓋率等等陌生的名詞很懼怕。可是仔細思考以後,發現實現基本功能也不過如此,分幾個模塊實現還不算很難;要解決如下幾個問題:html
經過百度谷歌搜索引擎查找不熟悉資料複習,另外對於後面的單元測試和代碼覆蓋率是參考趙暢同窗的博客,以及其博客中推薦的博客及插件。(在此謝過 !)git
在設計過程當中,一開始還比較亂,僅僅大概思考了分紅三個不一樣的.h及.cpp文件封裝函數,後面再實現過程不斷完善改進;github
「弱肉強食」算法,單詞越按照使用習慣常常出現,時間複雜度越小;算法
單元測試設計:手動設計測試文件進行測試,考慮多種特殊狀況以及廣泛狀況進行測試;另外針對張棟老師評論文件再大一些狀況,進一步作了更全面,量級更大的測試;數組
最開始選擇的是將全部單詞存入map容器中而後再總體選取頻數前十的十個單詞,花費時間:sort(n)量級,n爲不一樣單詞總數量;函數
改進思路:只維護一個10大小的數組,在存入map容易過程當中實時判斷頻數及字典序是否進入前十決定是否和Top_Ten類型words[9]更換;我的認爲如果計算頻數最高的十位,根據使用單詞習慣及出現規律,已經出現次數在前十的單詞更有多是文件中的前十的單詞(因此,如果常用的單詞常常出現,能夠大幅下降更換及排序次數下降複雜度);工具
對於此次做業的詞頻功能,思考實現過程想到了如今咱們各大流行的輸入法軟件,顯然平時無論咱們是使用九鍵輸入,或者26鍵,那麼在輸入首字母或前幾個拼音時自動爲咱們顯示的那些經常使用字應該就是經過這種詞頻算法,讓咱們用戶體驗更好,效率更高吧?個人思路即是按照常用的單詞(漢字):以前用的越多,之後越可能用,這樣會比較好的將複雜度降下來;性能
下面是測試5000循環main函數總共花費時間34.855秒,根據如下性能分析圖可知大部分時間花在文件的讀取上面,封裝三個接口以後文件讀取從一次變成了三次也在時間上增長了很多。能夠看出消耗最大的函數是Top_Tenwords函數佔比25.73%;單元測試
從中能夠看出是Is_Word()函數消耗較多,可是Is_Word函數中分佈比較平均,所以經過分析工具分析以後只是更改了部分以前使用的C++中輸入輸出cout爲C形式printf優化,其餘部分沒有進一步優化;時間減小到27秒。學習
void Top_Tenwords(Top_Ten words[],char *filename) { fstream f_tmp; string word = ""; char ch; map<string, int > all_words; int i = 0; f_tmp.open(filename); if (!f_tmp) { printf("Can't open file :s% \n Usage:countch filename", filename); exit(0); } while (f_tmp.get(ch)) { if (!Is_Engch(ch) && !Is_Num(ch)) { word = Is_Word(word); if (word.length() >= 4) { all_words[word]++; if (all_words.size() < 10 && all_words[word] == 1) //map中不一樣單詞 數尚未十個 { int tmp = all_words[word]; words[i].number = tmp; words[i].word = word; i++; } else if (all_words.size() == 10) //不一樣單詞數爲10開始對數組sort一次 { int tmp = all_words[word]; words[i].number = tmp; words[i].word = word; sort(words, words + 10, Cmp); } else if(all_words.size() > 10) //不斷判斷words[9]和當前掃描到的單詞是否須要更新替換 { if (all_words[word] > words[9].number) { words[9].word = word; words[9].number = all_words[word]; sort(words, words + 10, Cmp); } else if (all_words[word] == words[9].number) { if (word < words[9].word) { words[9].word = word; words[9].number = all_words[word]; sort(words, words + 10, Cmp); } } } } word = ""; continue; } else { if ((Is_Num(ch) && word.length() > 0) || Is_Engch(ch)) { word += ch; continue; } else if (Is_Num(ch) && word.length() == 0) { continue; } } } f_tmp.close(); }
int Word_Count(char *filename) // { string word=""; char ch; int word_cnt = 0; fstream f_tmp; f_tmp.open(filename); if (!f_tmp) { printf("Can't open file :s% \n Usage:countch filename",filename); exit(0); } while (f_tmp.get(ch)) { if (!Is_Engch(ch) && !Is_Num(ch)) { word = Is_Word(word); if (word.length() >= 4) { word_cnt++; word = ""; continue; } continue; } else { if ((Is_Num(ch) && word.length() > 0)|| Is_Engch(ch)) { word += ch; continue; } else if (Is_Num(ch) && word.length() == 0) { continue; } } } f_tmp.close(); printf("words:%d\n", word_cnt); return word_cnt; } string Is_Word(string word)//判斷字符串是不是合法單詞,如果返回小寫單詞; { int lenth = word.length(); string true_word; if (lenth < 4 || (lenth >= 4 && (!Is_Engch(word[0]) || !Is_Engch(word[1]) || !Is_Engch(word[2]) || !Is_Engch(word[3])))) { return ""; } else { while (!Is_Engch(word[lenth - 1]) && !Is_Num(word[lenth - 1])) //可能存在省略號的狀況,好比This is aaaa test file... { lenth--; } for (int j = 0; j < lenth; j++) { true_word += tolower(word[j]); } return true_word; } }
計算單詞數函數完成了基本功能就基本實現了;註釋確實還有些不夠熟練,因此有些沒有很合理。(另外在幾個.h頭文件中的註釋有參考趙暢同窗的代碼註釋風格,再次重謝!)
單元測試了四個函數Is_Word()、Lines_Count()、Word_Count()、Ch_Count();幾個函數模塊代碼覆蓋率只有85%,能夠看到是異常處理的語句佔用。(這該如何優化?)
單元測試:經過這次我的項目做業,以前看構建之法的對於單元測試的疑問我想在實踐中已經大概明白了是什麼用途和功能,能夠針對某一個函數功能模塊進行測試判斷其是否正確,確保代碼可靠性;
代碼覆蓋率:作了代碼覆蓋率的操做,對於其中的行代碼覆蓋率表層意思理解了,可是不太明白代碼覆蓋率到底具備什麼意義?覆蓋率達到100%又意味着什麼?也有查閱資料,可是仍是理解的不夠透徹,可能須要後續聽柯老闆解釋一下吧...
在每一個功能模塊函數中都須要讀取文件,在文件不存在或者因錯誤沒法打開時會報錯:
異常處理還不是很清楚須要哪些更多的異常處理,還有待學習;
對以前速讀一遍地構建之法一些不太懂得問題有了更清楚的瞭解,其次就是逐漸認識軟工時間的確能夠學到不少。重要的是:你看看如今幾點!
關於代碼規範將在另外一篇博客記錄,和結對做業代碼規範一致官方正式發表;
趙暢同窗博客:http://www.cnblogs.com/ZCplayground/p/9607027.html
[第二屆構建之法論壇] 預培訓文檔(C++版):https://www.cnblogs.com/SivilTaram/p/software_pretraining_cpp.html#part6.%E6%95%88%E8%83%BD%E5%B7%A5%E5%85%B7%E4%BB%8B%E7%BB%8D