結對第二次—文獻摘要熱詞統計及進階需求

這個做業屬於哪一個課程 軟件工程1916|W(福州大學)
這個做業要求在哪裏 結對第二次—文獻摘要熱詞統計及進階需求
結對學號 221600117|221600122
這個做業的目標 實現一個可以對文本文件中的單詞的詞頻進行統計的控制檯程序。
Github倉庫地址 基礎部分github|進階部分github

1.Github的代碼簽入記錄

2.具體分工

​ 咱們兩個在此次做業中一塊兒實現了基礎部分的實現,每一個人寫了兩個功能,我主要負責基礎部分代碼的編寫和單元測試部分,還有git的使用方法的學習,基礎部分博客編寫。java

隊友主要負責進階部分的代碼編寫與相關部分的博客。c++

3.PSP表格

PSP2.1 Personal Software Process Stages 預估耗時(分鐘) 實際耗時(分鐘)
Planning 計劃
• Estimate • 估計這個任務須要多少時間 480
Development 開發
• Analysis • 需求分析 (包括學習新技術) 120 150
• Design Spec • 生成設計文檔 15 20
• Design Review • 設計複審 10 5
• Coding Standard • 代碼規範 (爲目前的開發制定合適的規範) 5 1
• Design • 具體設計 20 10
• Coding • 具體編碼 180 240
• Code Review • 代碼複審 30 10
• Test • 測試(自我測試,修改代碼,提交修改) 60 60
Reporting 報告
• Test Report • 測試報告 20 15
• Size Measurement • 計算工做量 10 5
• Postmortem & Process Improvement Plan • 過後總結, 並提出過程改進計劃 10 5
合計 480 521

4.解題思路

​ 首先拿到題目後,看完了整個題目後,感受基礎部分實現起來並非特別困難,咱們就準備次日開始着手解決基礎部分的代碼。我先學習了git的使用方法,經過百度找一些別人寫的博客瞭解了git的基本使用方法。這部分花了一上午的時間。git

​ 在接下來就是對於代碼實現題目的思考。看到題目要求對字符進行處理統計,就決定使用C++來實現,由於C++對字符的操做更加簡單,也不須要特別複雜的操做。github

​ 找資料的過程就是經過在網上搜索一些c++中對字符處理的函數方法,距離上次使用C++已經有一段時間了,此次正好複習了一下C++。算法

​ 看到需求中有要求對代碼進行單元測試,還有進行性能分析。這些之前都沒有作過,因此學起來也花了一部分時間。網上對於這兩部分的講解資料並非特別多。框架

5.設計實現過程

由於題目中有要求對接口的封裝:函數

你們的代碼都各有特點,若是如今咱們要把這個功能放到不一樣的環境中去(例如,命令行,Windows圖形界面程序,網頁程序,手機App),就會碰到困難:代碼散落在各個函數中,很難剝離出來做爲一個獨立的模塊運行以知足不一樣的需求。性能

幾個功能獨立出來,成爲一個獨立的模塊(class library, DLL, 或其它),這樣的話,命令行和GUI的程序都能使用同一份代碼。爲了方便起見,咱們稱之爲計算核心"Core模塊",這個模塊至少能夠在幾個地方使用:單元測試

  1. 命令行測試程序使用
  2. 在單元測試框架下使用
  3. 與數據可視化部分結合使用

因此就決定使用四個函數,分別來實現對文章字符數量的統計,對文章單詞數的統計和對文章行數的統計,以及前十高詞頻的單詞統計。學習

如圖,在需求一種,countChar,countLine,countWord,sortWord分別對應四個功能,在主程序Word Count中能夠直接調用。在設計函數的時候並無設計流程圖,由於他們都是獨立的單元,先實現了最簡單的功能,而後後面的函數構造都按第一個實現好的函數的形式寫就能夠。

單元測試的部分經過對各個函數進行了測試,每一個函數用了三組不一樣的輸入數據。一共設計了四個測試函數,對一下狀況進行了測試:

  • 測試字符數是否正確
  • 統計單詞數是否正確
  • 測試行數是否正確
  • 測試若是是不存在的文件
  • 測試若是是空文件

算法設計過程

需求一


這是統計單詞數量的算法流程圖,題目中要求統計文件的單詞總數,單詞:至少以4個英文字母開頭,跟上字母數字符號,單詞以分隔符分割,不區分大小寫。因而就須要記錄單詞開頭的字母數量,來進行判斷。若是超過了四個以上的字母,說明該字符串爲單詞,若是讀到了分隔符,單詞數就加一。開頭字母數從頭開始計算,讀到數字若是已經不構成單詞,就把標誌位設爲-1。

這是對詞頻進行排序的流程圖。由於沒法直接對map直接進行排序,因此用到了vector中的pair,把map加入到vector中來進行排序再進行輸出。

統計單詞數的代碼

while((ch = fgetc(file)) != EOF)
    {
        if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')
        {
            if (f >= 0)//單詞前四位是字母
                f++;
            else//單詞前字母不足四位,後面字母不記錄
                f = -1;
        }
        else if (ch >= '0' && ch <= '9' && f < 4)//開頭不足四位字母,不算單詞
        {
            f = -1;
        }
        else//讀到分隔符
        {
            if (f >= 4)
                cnt++;
            f = 0;
        }
    }
    //若最後一個單詞符合條件且到文件末尾
    if (f >= 4)
        cnt++;

統計行數的代碼

while ((ch = fgetc(file)) != EOF)
    {
        //遇到換行符
        if (ch == '\n')
        {
            //本行內容爲非空字符
            if (f > 0)
                cnt++;
            f = 0;
        }
        //遇到非空字符
        else if(ch != ' ' && ch != '\t')
            f++;
    }
    //最後一行不含回車符,特殊判斷
    if (f > 0)
        cnt++;

統計字符數的代碼

while(fgetc(file) != EOF)
    {
        cnt++;
    }

排出前十詞頻的單詞代碼

while ((ch = fgetc(file)) != EOF)
    {
        if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')
        {
            if (ch >= 'A' && ch <= 'Z')
            {
                ch += ('a' - 'A');
            }
            if (f >= 0)//單詞前四位是字母
            {
                f++;
                temp += ch;
            }
            else//單詞前字母不足四位,後面字母不記錄
                f = -1;
        }
        else if (ch >= '0' && ch <= '9')//開頭不足四位字母,不算單詞
        {
            if (f < 4)
                f = -1;
            else
                temp += ch;
        }
        else//讀到分隔符
        {
            if (f >= 4)
            {
                cnt++;
                wmap[temp]++;               
            }
            f = 0;
            temp = "";
        }
    }
    if (f >= 4)
    {
        cnt++;
        wmap[temp]++;
    }
    MapSortOfValue(vec, wmap);

需求二


​ 爬蟲:使用javajsoup庫爬取HTML文檔,而後生成DOM文檔。在DOM樹上,尋找到每一篇論文中的href連接發送請求,對於收到的文本中,解析出須要的Title和Abstract內容。

除了統計詞組相對於需求一有比較大的變化,其餘都是在需求一上作更多的判除操做,對於序號以及論文中的Title與Abstract要不加入計算,因此統計字符時也要加入單詞的判斷,這些與需求一大體相同,就很少加贅述。

​ 統計詞組方面,主要難點是解決規定的詞組長度截取以及注意不能跨越兩個欄目,解決思路是:利用一個向量來模擬隊列。規定隊列長度爲詞組長度,新單詞進入加入隊尾,超過長度則拋出隊頭,當隊伍長度等於詞組長度時,隊列就是保留一個合法詞組。當遇到Title與Abstract時,隊列清空,就能夠作到不跨越兩個欄目。剩下排序就和需求一相同。核心部分流程圖以下:

核心代碼以下:

//......
while ((ch = fgetc(file)) != EOF)
    {
        if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')
        {
            if (ch >= 'A' && ch <= 'Z')
            {
                ch += ('a' - 'A');
            }
            if (f >= 0)//單詞前四位是字母
            {
                f++;
                temp += ch;
            }
            else//單詞前字母不足四位,後面字母不記錄
                f = -1;
        }
        else if (ch >= '0' && ch <= '9')//開頭不足四位字母,不算單詞
        {
            if (f < 4)
                f = -1;
            else
                temp += ch;
        }
        else//讀到分隔符
        {
            //當趕上title或者abstract時,模擬隊列清空
            if (temp == "title" && temp == "abstract")
                que.clear();

            if (f >= 4 && temp != "title" && temp != "abstract")
            {
                que.push_back(temp);
                //維持詞組的規定長度
                if (que.size() > Len)
                    que.erase(que.begin());
                //符合長度,加入詞組map中
                if (que.size() == Len)
                {
                    tt = "";
                    k = 0;
                    for (vt = que.begin(); vt != que.end(); vt++)
                    {
                        k++;
                        tt += *vt;
                        if (k < Len)
                            tt += " ";
                    }
                    wmap[tt]++;
                }
            }
            f = 0;
            temp = "";
        }
    }
//......

6.須要改進的地方

​ 在計算詞頻出現的時候,須要判斷是否爲單詞,這部分和在統計單詞數量的時候的代碼有部分重合了,也就是說須要重複的計算相同的部分,會花掉一部分時間,這部分代碼的設計存在着問題。

7.單元測試部分

部分代碼以下

TEST_METHOD(TestMethod1)//測試字符數是否正確
{
    FILE *file;
    char* fn = "input1.txt";
    fopen_s(&file, fn, "r");
    int count = 102;
    Assert::AreEqual(countChar(fn), count);
}

這是一段測試字符數是否正確的代碼,經過input1.txt的文件傳入數據,而後驗證字符數是否與預計數相等。

通過測試,10個測試點均經過測試。測試代碼的思路上面已經提到。

8.性能分析

經過圖片能夠明顯看出,在統計詞頻或者詞組頻率(後面的提升部分)中所須要的運算量更大,因此更加耗費計算機資源。

9.遇到的困難

​ 關於單元測試和性能分析,是之前歷來沒有接觸過的,只能在網上查找資料來學習。可是相關的資料很是的很差找。因此資料就花掉了不少時間。還有git的使用,不過還好有Linux使用的基礎,學起來也還相對輕鬆。

​ 剩下的困難就是在代碼方面的困難了。理解題目需求花了不少時間,常常寫着寫着發現好像不符合題目的要求,而後就又從新改。

​ 解決辦法就是必定要先理解了需求,再開始着手。否則後期會很麻煩,前面努力都白費了。

10.評價隊友

隊友的寫代碼能力很強,進階功能基本都靠他來實現了。原本都要放棄了進階功能的部分,他說想試一下就作了。

不怕困難,值得學習!

相關文章
相關標籤/搜索