標籤:style blog http 使用 java strong 檔案 資料 2014
實現一個控制台應用程式,來統計一個檔案夾下的單詞頻率
要求
1.遞迴地進行統計
2.統計的檔案格式為 .txt , .cpp , .h , .cs
3.單詞定義:開頭有至少3個英文字母,後面可以追加英文字母或數字
4.分隔字元定義:空白符,非英文數位字元
5.大小寫:同一個單詞大小寫不同不區分開統計
6.輸出:輸出到 "郵件地址.txt"中
7.輸出格式:每一條都形如"單詞:出現次數",其中"單詞"需要是檔案夾下出現過的同一個單詞中字典序最靠前的那個(基於ASCII),各條之間按照出現次數降序排序,如果出現次數相同,按單詞字典序排序
8.模式:簡單模式--在控制台使用程式,輸入檔案夾路徑參數,輸出簡單的詞頻統計
擴充模式--(1):在控制台使用程式,輸入兩個參數,第一個是-e2,第二個是檔案夾路徑,輸出出現次數最頻繁的前10個雙詞片語,雙詞片語形如: 單詞+單個空格+單詞
(2):在控制台使用程式,輸入兩個參數,第一個是-e3,第二個是檔案夾路徑,輸出出現次數最頻繁的前10個三詞片語,三次片語形如: 單詞+單個空格+單詞+單個空格+單詞
程式設計
程式分為以下部分:
模式判斷部分:判斷命令列參數的正確性,並確定程式運行模式
遍曆部分:遞迴地遍曆檔案夾
文檔分詞部分:分隔出文檔中的單詞,並記錄每個單詞與相鄰單詞之間的間隔符號情況
文檔單詞片語統計部分:統計一個文檔中各單詞出現的頻率,並記錄各單詞出現過的字母表排序最靠前的形式
統計匯總部分:將單個文檔的統計資料匯總到總統計中
排序部分:將總統計中的單詞按照字典序排序
輸出部分:按照參數給予不同的輸出
預計時間
1.學習C++語言,尋找需要用到的工具函數:6~8小時
2.遍曆部分:2小時
3.文檔分詞部分:2小時
4.文檔單詞片語統計部分:2小時
5.統計匯總部分:1小時
6.排序+輸出:1小時
總計:16小時
實際時間
1.學習C++語言,尋找需要用到的工具函數: 10小時
2.遍曆部分:半小時左右
3.文檔分詞部分:3小時
4.文檔單詞片語統計部分:3小時
5.統計匯總部分:1小時
6.排序+輸出:1小時
7.代碼最佳化: 3小時
總計:21小時左右
代碼品質分析
分析過程中,報出2個警告:
第一個警告是提醒在調用string的size()方法時返回的是不帶正負號的整數. 我直接將其賦值給整形了,發現後進行了類型轉換,消除了警告
第二個警告是提醒數組可能讀取越界. 原因是我判斷跳出迴圈的條件中對計數器的限制條件放在了與運算式的後面,而前面的條件中要訪問計數器所指元素,發現後將限制條件提至最前,消除了警告.
效能分析
剛剛調試好程式後,就使用程式掃描了某軟體的目錄,效能分析報表如下:
完成整個統計過程大概用了4分鐘.
由於並沒有使用雜湊,二叉樹搜尋效率較高的結構,所以速度相對慢很多.
所以嘗試著將單詞的儲存結構轉變為了二叉樹,以期提高一些效率.
將儲存結構轉變為二叉樹後,統計同樣的檔案夾,效能分析報表如下:
這次大約花費2分30秒的時間,就此例來看,大約節省了30%~40%的時間.
測試案例
1.空檔案夾和空檔案: 統計路徑是一個空檔案夾,輸出了空的txt檔案.
統計路徑下是一個空檔案夾和一個空txt檔案,輸出了空的txt檔案.
2.大小寫單詞的合并: 路徑下建立了一個cs檔案,內容為:
"Morning moRning MoRnIng MOrNiNG MoRNING MORning"
程式輸出為:
MORning是基於ASC2碼字典序最靠前的,輸出正確
3.單詞的識別:路徑下建立一個cpp檔案,內容為:
"qwehs4f;r1if2233usdas3rs4sss4dshadssf4ui[qasasdw[shue"
程式輸出為:
分詞格式是正確的.
4.雙詞三詞的識別: 路徑下建立了一個h檔案,內容為:
"good morning afternoon evening , have a good great awesome 123time asdf "
使用-e2模式,程式輸出為:
可見,程式能正確的判斷雙詞片語,多個空格或者是中間隔著不是單詞的字串的相鄰兩個詞都會被排除,連續的雙詞片語也能正確地統計.
使用-e3模式,程式輸出為:
good great awesome:1
三詞片語也是可以正確判斷的.
5.單詞的頻率排序:路徑下建立了一個txt檔案,內容為:
"green red gray gray orange orange blue orange red blue blue orange gray gray purple black white gray white blue white black pink"
程式輸出為:
詞頻是降序的,輸出正確.
6.同頻率單詞的字典序:路徑下建立了一個txt檔案,內容為
"Disk OpeN alert computer apple water light heaVy"
程式輸出為:
同頻率單詞是按字典序排序的,輸出正確.
7.遞迴能力:在路徑下建立檔案夾1和2個內容同上的txt檔案,檔案夾1內建立檔案夾2和2個內容同上的txt檔案,檔案夾2內是2個內容同上的txt檔案.
輸出如下:
單詞出現次數均為6,證明所有檔案都被統計到了,遞迴正確.
8.測試非法命令:輸入命令列參數"hsdfiudsd",輸出"參數不正確!",輸入命令列參數"-e2 iaufoq",輸出"路徑不存在" (均輸出在控制台).
9.測試檔案格式:上述用例的檔案格式包含所有支援的格式,運行結果正確
10.測試資料較多的檔案夾:統計VS2012下的Common7檔案夾
結果的前段,產生了一個110kb的txt輸出檔案.
感想
這次的編程經曆是比較難得的 , 這是我第一次用不熟悉的語言直接編寫一個幾百行的程式.
雖然在編寫之前看了很多函數和類型用法 , 但實際使用的時候還是很生疏 , 編的時候甚至有一種迷茫的感覺 , 因為沒有辦法校準函數的參數和傳回值 , 不知道接下來要用的東西在跟哪個函數有關.
因為生疏 , 所以要不停地百度 , 在編寫程式的過程中大概在網上看了四五十篇文章 , 才算初步的掌握了這個程式中使用的函數.
在翻閱文章的過程中 , 我開始覺得 , 現代程式語言還遠沒有想象中的那麼方便 .
在尋找所需函數時 , 我發現了這樣一個事實 : 之前在JAVA編程中一直都在使用的方法在C++中基本都沒有完美的替代品 .
讀過的好幾篇文章也都出現了 "重複造輪" , "不方便" , "反人類" 等等詞語 . 很遺憾 , 它們都是用來形容C++的 .
看來如果想用的方便 , 唯一的方法就是讓自己足夠熟悉這門語言了.
完成這個程式後 , 我開始考慮我編寫程式的過程 , 我發現我的構思過程一直都不怎麼注重程式效率 , 每次都是先想好怎麼解決問題 , 程式效率的問題就被逐漸地忽略掉了.
其實程式的效率與構思的關係是密不可分的 , 解決問題優先的演算法無論怎麼最佳化也不如那些一開始就兼顧正確性與效率的演算法好 , 以後的程式構思我還是從最開始就考慮效率的問題吧.
還有一點 , C++提供的類和函數真的很重要 , 如果能基於一些十分優秀的類與函數構思演算法 , 能起到事半功倍的效果 , 以後編程構思之前不妨先翻翻協助文檔.
軟體工程基礎/個人項目1