Github:https://github.com/1561602610/PersonProject-C2
PSP表格:
PSP2.1 | Personal Software Process Stages | 預估耗時(分鍾) | 實際耗時(分鍾) |
---|---|---|---|
Planning | 計划 | ||
• Estimate | • 估計這個任務需要多少時間 | 720 | 1000 |
Development | 開發 | 600 | 900 |
• Analysis | • 需求分析 (包括學習新技術) | 180 | 210 |
• Design Spec | • 生成設計文檔 | 40 | 50 |
• Design Review | • 設計復審 | 30 | 60 |
• Coding Standard | • 代碼規范 (為目前的開發制定合適的規范) | 10 | 30 |
• Design | • 具體設計 | 30 | 50 |
• Coding | • 具體編碼 | 180 | 260 |
• Code Review | • 代碼復審 | 30 | 40 |
• Test | • 測試(自我測試,修改代碼,提交修改) | 120 | 200 |
Reporting | 報告 | 120 | 100 |
• Test Repor | • 測試報告 | 30 | 20 |
• Size Measurement | • 計算工作量 | 30 | 30 |
• Postmortem & Process Improvement Plan | • 事后總結, 並提出過程改進計划 | 60 | 50 |
合計 | 720 | 1000 |
需求分析
-
統計文件的字符數:
- 只需要統計Ascii碼,漢字不需考慮
- 空格,水平制表符,換行符,均算字符
-
統計文件的單詞總數,單詞:至少以4個英文字母開頭,跟上字母數字符號,單詞以分隔符分割,不區分大小寫。
- 英文字母: A-Z,a-z
- 字母數字符號:A-Z, a-z,0-9
- 分割符:空格,非字母數字符號
- 例:file123是一個單詞, 123file不是一個單詞。file,File和FILE是同一個單詞
- 統計文件的有效行數:任何包含非空白字符的行,都需要統計。
- 統計文件中各單詞的出現次數,最終只輸出頻率最高的10個。頻率相同的單詞,優先輸出字典序靠前的單詞。
計算模塊接口的設計與實現過程
實現字符計數:
#include "CharNum.h" #include<fstream> #include<iostream> int CharNum(char * filename) { int count = 0; char ch; FILE *file; fopen_s(&file,filename, "rt"); for (; (ch=fgetc(file)) != EOF;) { if (ch >= 0&&ch <= 255) count++; } fclose(file); return count; }
實現單詞計數:
#include"WordNum.h" int WordNum(char * filename) { map<string, int> Word_Num_map; char ch; FILE *file; fopen_s(&file, filename, "rt"); int flag = 0; int count = 0; for (; (ch = fgetc(file)) != EOF;) { if ((ch >= 97 &&ch <= 122 )|| (ch >= 65 && ch <= 90))//英文字母 { if (flag >= 0)flag++; if (flag < 0)flag--; } else if (ch >= 48 && ch <= 57)//數字 { if (flag >= 4)flag++; else flag = -1; } else //非字母數字符號 { if (flag >= 4) { count++; flag = 0; } else { flag = 0; } } } fclose(file); return count; }
實現行數計數:
#include "LineNum.h" int LineNum(char * filename) { FILE *file; fopen_s(&file,filename, "rt"); int count = 0; char ch; int flag = 0; for (; (ch = fgetc(file)) != EOF;) { if (ch == '\n') { if (flag > 0)count++; flag = 0; } else if (ch != ' '&&ch!='\t') { flag++; } }if (flag > 0)count++; fclose(file); return count; }
實現詞頻統計及輸出前十名:
#include"Word_Fre.h" typedef pair<string, double> PAIR; bool CmpByValue(const PAIR& lhs, const PAIR& rhs) { return (lhs.second != rhs.second) ? lhs.second > rhs.second : lhs.first < rhs.first; } int Word_Fre(char * filename) { map<string, int> Word_Num_map; char ch; string word; int flag = 0; FILE *file; fopen_s(&file, filename, "r"); for (; (ch = fgetc(file)) != EOF;) { if ('A' <= ch && ch <= 'Z') ch = ch + 32; if (ch >= 'a' && ch <= 'z')//英文字母 { if (flag >= 0) { flag++; word = word + ch; } if (flag < 0) { flag = 0; word = ""; } } else if (ch >= 48 && ch <= 57)//數字 { if (flag >= 4) { flag++; word = word + ch; } else { flag = 0; word = ""; } } else //非字母數字符號 { if (flag >= 4) { Word_Num_map[word]++; word = ""; flag = 0; } else { flag = 0; word = ""; } } } if (flag >= 4) { Word_Num_map[word]++; } vector <PAIR> Word_Num_vec(Word_Num_map.begin(), Word_Num_map.end()); sort(Word_Num_vec.begin(), Word_Num_vec.end(), CmpByValue); if (Word_Num_vec.size() < 10) for (int i = 0; i != Word_Num_vec.size(); ++i) { const char *ss = Word_Num_vec[i].first.c_str(); cout << '<' << ss << '>' << ":" <<' '<< Word_Num_vec[i].second << endl; } else for (int i = 0; i != 10; ++i) { const char *ss = Word_Num_vec[i].first.c_str(); cout << '<' << ss << '>' << ":" <<' '<< Word_Num_vec[i].second << endl; } return 0; }
主要解題思路:
設置標志位flag用於判斷該位是否為單詞的組成部分。
測試樣例:
測試文本:
測試結果:
心路歷程與收獲:
在努力完成這次實踐的過程中,遇到了很多問題,首先的問題就是關於文件讀取的問題,在遇到一個個問題的時候四處查找資料、請教同學,感覺確實有在學到東西。
在解決詞頻統計這個問題上花了很長的時間,主要是用於思考記錄單詞及其頻率的方法,后來查找以及問同學相關問題,知道了map這個東東還有一堆奇奇怪怪的函數,實在是后悔沒好好學C++和數據結構。