福大軟工1816 · 第二次作業 - 個人項目
一、Github項目位址
Github項目位址
二、PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | 20 | |
· Estimate | · 估計這個任務需要多少時間 | ||
Development | 開發 | 670 | 1120 |
· Analysis | · 需求分析 (包括學習新技術) | 120 | 300 |
· Design Spec | · 生成設計文檔 | 15 | |
· Design Review | · 設計複審 | ||
· Coding Standard | · 代碼規範 (為目前的開發制定合适的規範) | 30 | |
· Design | · 具體設計 | 40 | |
· Coding | · 具體編碼 | 360 | |
· Code Review | · 代碼複審 | 50 | 60 |
· Test | · 測試(自我測試,修改代碼,送出修改) | ||
Reporting | 報告 | 100 | |
· Test Repor | · 測試報告 | ||
· Size Measurement | · 計算工作量 | ||
· Postmortem & Process Improvement Plan | · 事後總結, 并提出過程改進計劃 | 80 |
| | 合計 |790 |1260|
三、解題思路描述
解題思路描述。即剛開始拿到題目後,如何思考,如何找資料的過程。
1、首先,題目要求在程式中對指定檔案進行讀寫操作,并且輸入檔案名以指令行參數傳入。之前有稍微接觸過檔案讀寫和指令行傳參的相關内容,是以對這部分的要求并未太過糾結。
2、題目的具體要求是統計檔案的字元數、有效行數、合法單詞數,并字典序輸出詞頻最高的10個合法單詞。
- 統計檔案的字元數。可以從檔案中依次讀取字元,通過判斷讀取到的字元是否為ASCII碼進行字元統計。
- 統計檔案的有效行數。題目要求“任何包含非空白字元的行,都需要統計。”我的了解是如果一行中隻包含空格或制表符,則将其視為空白行,不予統計。可以用getline()函數從檔案中逐行讀取,去除行中的空格和制表符,如果處理後的字元串的長度仍大于0,則将其視為有效行。思路參考部落格1。
- 統計檔案中的合法單詞數,并字典序輸出詞頻最高的10個合法單詞。考慮這個功能的實作花費了我最多的時間和精力。題目對單詞的形式提出了要求,即“單詞:至少以4個英文字母開頭,跟上字母數字元号,單詞以分隔符分割,不區分大小寫。”另外,題目中提到了單詞的分隔符是非字母數字元号,是以就不能簡單的根據空格提取單詞,提取單詞的過程中還要進行對單詞格式的檢查。是以,我用邏輯判斷截取合法單詞,用map進行詞頻統計,最後借助vector輸出詞頻最高的10個合法單詞。思路和實作參考部落格2。
四、設計實作過程
設計實作過程。設計包括代碼如何組織,比如會有幾個類,幾個函數,他們之間關系如何,關鍵函數是否需要畫出流程圖?單元測試是怎麼設計的?
1、代碼組織
我把程式的主要功能:統計字元數、統計有效行、統計合法單詞數和按字典序輸出詞頻最高的10個合法單詞封裝成了一個Statistics類,沒有将檔案的操作單獨封裝成類,在主函數中進行檔案的打開和關閉,将檔案參數傳給類中的統計功能函數,實作統計功能。關系如下:
2、關鍵函數流程圖
int words(ifstream& in)統計單詞數及詞頻流程圖:
補充:在i=str.length()-1時,情況1:str[i]為字母,此時若flag>=3,截取合法單詞;情況2:str[i]為數字,此時若flag>=4,截取合法單詞;情況三:str[i]為非數字字母字元,無特殊處理。
補充2:在進行截取前,如果所標明截取部分的前一個字元為數字,判斷為不合法單詞,放棄截取。
3、單元測試
我在這一步折騰了很久,先是找資料學習如何進行單元測試,之後在實踐中也遇到了很多的問題,特别是沒有把測試用的文檔放在正确的地方導緻測試結果老是失敗。
為了更友善地進行單元測試,我對原先程式的封裝進行了改動,實施了單元測試之後切實感受到了它的好處,利用單元測試可以很好的檢測程式中的功能,我在進行單元測試的過程中就找到了我程式中的幾個bug,如果将來要進行大的項目的建設,單元測試帶來的友善應該會更加顯著。
我設計的單元測試有:回車字元的統計、字元數的統計、有效行數的統計、單詞數的統計、合法單詞的提取、是否轉換為小寫字母、詞頻統計是否正确、單詞是否按字典序排列、空文檔的統計、僅含空格、制表符、回車的文檔的統計。
單元測試部分代碼:
namespace UnitTest4//測試單詞數的計算
{
TEST_CLASS(UnitTest1)
{
public:
TEST_METHOD(TestMethod1)
{
ifstream in;
in.open("test4.txt", ios::in);
Statistics s;
Assert::IsTrue(s.words(in) == 3);
}
};
}
單元測試結果如下:
單元測試得到的測試覆寫率截圖:
主函數裡未被覆寫部分為錯誤處理代碼。
五、性能分析和改進
記錄在改程序式性能上所花費的時間,描述你改進的思路,并展示一張性能分析圖(由VS2017的性能分析工具自動生成),并展示你程式中消耗最大的函數。
選擇33.6M的txt文檔進行性能分析。
性能分析圖:
消耗最大的函數:
消耗最大的函數是Statistics類裡統計單詞數及詞頻的函數words(),其中,消耗主要在對map的操作以及檔案的讀取上。
六、代碼說明
展示出項目關鍵代碼,并解釋思路與注釋說明。
1、統計行數
去除一行中的空格和制表符,如果該行長度仍大于0,說明其為有效行數。
主要代碼:
while (getline(in, str))
{
str.erase(std::remove(str.begin(), str.end(), ' '), str.end());//删除一行中的空格
str.erase(std::remove(str.begin(), str.end(), '\t'), str.end());//删除一行中的制表符
if (str.length() > 0) //如果删除制表符和空格之後的一行資料還有其他字元就算有效行
{
line++;
}
}
2、按字典序輸出詞頻最高的10個單詞
借助vector輸出:将儲存于map中的各單詞的詞頻導入vector,接着對vector從大到小排序,最後将vector中排在前十的數字依次與map中記錄的詞頻比對,輸出最先比對到的單詞和詞頻,置輸出的單詞的詞頻為0。
map<string, int>::iterator it;
for (it = word.begin(); it != word.end(); it++)
{
int t = (*it).second;
a.push_back(t);
}
sort(a.begin(), a.end(), cmp);
if (wnum == 0)
{
out << "該文檔不存在合法單詞!" << endl;
}
else
{
for (int i = 0; i < wnum && i < 10; i++)
{
int t = a[i];
for (it = word.begin(); it != word.end(); it++)
{
if ((*it).second == t)
{
out << "<" << (*it).first << "> :" << t << endl;
(*it).second = 0;
break;
}
}
}
}
3、錯誤處理部分
處理指令行輸入參數錯誤
if (argc != 2)//檢測輸入的指令行參數是否正确
{
cout << "輸入參數錯誤!" << endl;
exit(1);
}
處理輸入輸出檔案打開失敗
infile.open(argv[1], ios::in);
if (infile.fail())
{
cout << "輸入檔案打開失敗!" << endl;
exit(1);
}
outfile.open("result.txt", ios::out);
if (outfile.fail())
{
cout << "輸出檔案打開失敗!" << endl;
exit(1);
}
七、心路曆程與收獲
結合在建構之法中學習到的相關内容與個人項目的實踐經曆,撰寫解決項目的心路曆程與收獲。
這次的作業花費了我很多的時間和精力,我的能力比我想象中的還要不足,作業中列出了一項項具體的要求,是以我在實踐中就按照這一項項要求去思考、搜尋、學習,在搜尋過程中我找到了很多比我原先想的要友善得多的解決方法,見識了很多新知識和新技術,可以說,我在這次個人項目裡做的最多的就是學習,學習新知識,比如軟工的流程和規範、字元串處理、STL的應用,學習新技術,比如vs的單元測試、性能分析等等,這些新知識和新技術算是我這次最大的收獲了吧。另外,寫部落格一直是很讓我頭疼的一件事,我在寫部落格上也花費了相當多的時間和精力,怎麼在部落格中清楚地表達自己的想法和經曆,展現自己的成果和收獲是一個很重要的能力,我在這方面有很大的欠缺,有待加強,希望以後寫部落格能成為一項我喜歡的事。
參考資料:
部落格1:https://blog.csdn.net/haomingzidoumeilea/article/details/8977012
部落格2:https://blog.csdn.net/hisfox/article/details/80013414#t3