2018軟工實踐第二次做業

Github項目地址 :https://github.com/comeony/personal-project/tree/master/Cplusplusgit


PSP 表格

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

環境

  • 操做系統 :Windows 10
  • IDE : Visual Studio Community 2017
  • 開發語言 :C++

解題思路

  • 統計文件中的字符:這個功能利用文件流讀取計數便可。代碼詳見:CharNum.cpp
  • 統計文件中的有效行數:行數的標誌就是換行符(‘\n’),考慮到空白符的問題,不能簡單的計算換行符的數量。個人方法是先讓flag=0,遇到非空白符就讓flag=1,讀到換行符以後看flag是否爲1就能夠了,flag==1則行數加一。以後都將flag=0用於判斷下一行。代碼詳見:LineNum.cpp
  • 統計文件的單詞總數:在這以前應該先對字符進行處理,因爲題目要求大寫當作小寫,因此應該先把大寫字母轉換後小寫,固然這個很簡單。主要是判別單詞,利用有窮自動機能有效的解決這個問題。代碼詳見:WordNum.cpp狀態轉換圖以下:
    github

  • 統計文件中各單詞的出現次數,而且輸出頻率最高的10個:用第三點的方法來判別單詞,經過map<string,int>能夠有效的記錄單詞的頻率,再將map複製到vector後,進行sort排序便可,按順輸出便可。代碼詳見:Word_Fre.cpp函數

具體設計

爲了獨立每一個功能,我將上述對應的4個功能分別封裝到不一樣的cpp文件中,同時在main()函數中調用調用這個4個函數。性能

函數關係以下

關鍵代碼

判別單詞及統計單詞頻率(模擬有窮自動機)

設置一個flag變量,經過flag從0到4的變換來模擬自動機的4個狀態。初始狀態爲flag=0單元測試

設置一個string類型的變量word來記錄讀到的單詞,初始狀態word=「」爲空。學習

  • 一開始flag=0(表示位於P0狀態),讀到一個字母,就讓flag=1(表示進入P1狀態),同時把word +=char(表示把這個字母鏈接到word後)測試

  • flag=1(表示此時爲狀態P1)時,讀到一個字母,就讓flag=2(表示進入P2狀態),同時把word +=char(表示把這個字母鏈接到word後),若是讀到的不是字母就將flag=0(迴歸狀態P0),同時把Word清空。優化

  • flag=2flag=3與上面相似,就不重複了編碼

  • flag=4時,讀到字母或者數字就在這個狀態停留,同時把word +=char,若是讀到是其餘字符就將flag=0(迴歸狀態P0),map[word]++(儲存到map中)同時把Word清空。操作系統

    代碼以下:

    for (; (ch = fgetc(file)) != EOF;)        //Determine the word and insert map
      {
          if ('A' <= ch && ch <= 'Z')
              ch = ch + 32;
          if (flag == 0) {
              if (ch >= 'a'&&ch <= 'z') { flag = 1;   word = word + ch; }
          }
          else if (flag == 1) {
              if (ch >= 'a'&&ch <= 'z') { flag = 2;   word = word + ch; }
              else { flag = 0; word = ""; }
          }
          else if (flag == 2) {
              if (ch >= 'a'&&ch <= 'z') { flag = 3;   word = word + ch; }
              else { flag = 0; word = ""; }
          }
          else if (flag == 3) {
              if (ch >= 'a'&&ch <= 'z') { flag = 4;   word = word + ch; }
              else { flag = 0; word = ""; }
          }
          else if (flag == 4) {
              if (ch >= 'a'&&ch <= 'z' || (ch >= '0'&&ch <= '9')) { word = word + ch; }
              else {
                  Word_Num_map[word]++;
                  word = "";
                  flag = 0;
    
              }
          }
      }

單詞頻率排序

排序用sort函數,可是咱們發現map不能直接用sort,因而現將map複製到vector,在用sort排序,如何大於10個單詞就輸出前10個,反之所有輸出。

具體代碼以下:

struct CmpByValue {             //排序用的
    bool operator()(const PAIR& lhs, const PAIR& rhs) {
        return lhs.second > rhs.second;
    }
};
map<string, int> Word_Num_map;  //定義map
typedef pair<string, int> PAIR;
vector <PAIR> Word_Num_vec(Word_Num_map.begin(), Word_Num_map.end()); //map複製
sort(Word_Num_vec.begin(), Word_Num_vec.end(), CmpByValue()); //排序

分析與改進

測試文本

aaa123123 df aa df

123aaa AAaa123123 ffff
FFff qqq7789 123 dddd
DDdd dddd fffff sadqwe 
/
abcabc ABCabc
8888
        fff

CPU性能分析

  • 採用VS自帶的CPU性能分析

  • 選用的測試文本如上

  • 在測試以前將main()函數循環10000次

  • 總時間消耗了30.978s

    結果以下:

  • 能夠看到主要耗時在Word_Fre.cpp,具體發現主要耗費在文件打開和輸出,咱們將輸出函數改成fprintf同時改進優化了有窮自動機,能夠看到性能有不錯的提高,時間降到了13.848s

單元測試

設定了3個單元測試,分別測試3個模塊,以下

測試名 單元測試內容 測試模塊 結果
UnitTestCharNum 統計字符數量 CharNum.cpp 經過
UnitTestLineNum 統計行數量 LineNum.cpp 經過
UnitTestWordNum 統計單詞數量 WordNum.cpp 經過

代碼覆蓋率

  • 代碼不能全覆蓋的主要出如今WordNum.cppWord_Fre.cpp中,主要是由於自動機和輸出if else的判斷。

異常處理

  • 輸入文件爲空異常提醒
  • 輸入文件不能打開或不存在提醒
if (argv[1] == NULL)
    {
        
        printf("please input file!\n");
        return -1;

    }
    std::fstream file;
    file.open(argv[1]);
 if (!file) {
        
        printf("the file cannot open or no exist!\n");
        return -1;
    }

總體運行結果

總結和感想

  • 先構思在下筆寫代碼,效率會提升不少
  • 空想和實踐仍是有很大差距的,剛拿到題目的時候感受這題不難,可是動筆的時候才發現有太多知識欠缺,又自學了map和vector
  • 第一次學習git,感覺到了github的好處。
  • 本次收穫最大的是寫代碼更有條理,體會了一次軟件工程的設計開發流程
  • 本次仍有不少不足,要注重提升效率
相關文章
相關標籤/搜索