軟工實踐第二次做業之我的項目

1. Github地址

PSP表格:

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爲不一樣單詞總數量;函數

時間複雜度:nlog(n);

改進思路:只維護一個10大小的數組,在存入map容易過程當中實時判斷頻數及字典序是否進入前十決定是否和Top_Ten類型words[9]更換;我的認爲如果計算頻數最高的十位,根據使用單詞習慣及出現規律,已經出現次數在前十的單詞更有多是文件中的前十的單詞(因此,如果常用的單詞常常出現,能夠大幅下降更換及排序次數下降複雜度);工具

最差時間複雜度:10(n-10)*log(10);
拓展思考(各大輸入法):

對於此次做業的詞頻功能,思考實現過程想到了如今咱們各大流行的輸入法軟件,顯然平時無論咱們是使用九鍵輸入,或者26鍵,那麼在輸入首字母或前幾個拼音時自動爲咱們顯示的那些經常使用字應該就是經過這種詞頻算法,讓咱們用戶體驗更好,效率更高吧?個人思路即是按照常用的單詞(漢字):以前用的越多,之後越可能用,這樣會比較好的將複雜度降下來;性能

性能分析報告:

下面是測試5000循環main函數總共花費時間34.855秒,根據如下性能分析圖可知大部分時間花在文件的讀取上面,封裝三個接口以後文件讀取從一次變成了三次也在時間上增長了很多。能夠看出消耗最大的函數是Top_Tenwords函數佔比25.73%;單元測試

從中能夠看出是Is_Word()函數消耗較多,可是Is_Word函數中分佈比較平均,所以經過分析工具分析以後只是更改了部分以前使用的C++中輸入輸出cout爲C形式printf優化,其餘部分沒有進一步優化;時間減小到27秒。學習


Top_Tenwords函數展現:
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%又意味着什麼?也有查閱資料,可是仍是理解的不夠透徹,可能須要後續聽柯老闆解釋一下吧...

異常處理說明

在每一個功能模塊函數中都須要讀取文件,在文件不存在或者因錯誤沒法打開時會報錯:

Can't open file :yourfilename \n Usage:countch filename

異常處理還不是很清楚須要哪些更多的異常處理,還有待學習;

我的項目感想:

對以前速讀一遍地構建之法一些不太懂得問題有了更清楚的瞭解,其次就是逐漸認識軟工時間的確能夠學到不少。重要的是:你看看如今幾點!

關於代碼規範將在另外一篇博客記錄,和結對做業代碼規範一致官方正式發表;

參考博客:

趙暢同窗博客: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

相關文章
相關標籤/搜索