GitHub鏈接WordCount.
一、PSP表格記錄下估計將在程序的各個模塊的開發上耗費的時間。
二、計算模塊接口的設計與實現過程。
1、項目分析
剛開始看到這個代碼,我就開始構思整個代碼的框架,大致將其功能分為三個模塊實現,字符類,行類,單詞類。字符的判斷可根據字符的ASCII碼值判斷,行數的計算可按行讀取,將文本文件中的字符逐個抽取,對字符進行處理可以獲取單詞,第三個類使用的數據結構較多,包含了雙向鏈表結構,鏈表排序算法,hash散列用於快速匹配單詞,我計划將這三個功能各自獨立起來,分別用結構體封裝,這只是一些大致的想法,具體的實現細節后面解釋。
下面兩天我有空閑時間就在做代碼編寫的預備知識學習工作,包括輸入輸出流,hash散列,結構體的雙向鏈表結構,還有一些庫函數,此外,我將c++一書又瀏覽了一遍,因為在剛開始寫代碼時,我發現一些基本的c++知識都忘記了。
2、實現細節
1)字符統計
利用c++輸入輸出流函數逐個讀取字符,判斷字符ASCII碼值是否在ASCII碼表范圍內,我對字符的輸入輸出流不太了解,剛開始出現了亂碼,讀取字符不完整等情況,所以這方面花費時間很長,下面給出代碼以作記錄:
fstream inFile;
inFile.open(fileName);//讀取文件
if (inFile.fail()) //讀取文件失敗
{
cout << "Could not find the file\n";
cout << "Program terminating\n";
exit(EXIT_FAILURE);
}
inFile >> noskipws;
inFile >> c;
2)
利用getline()函數計算行數
while (getline(inFile, tmp, '\n'))
{
linecount.linenum++;
}
原本的想法是想將單詞類獨立封裝在一個結構體內,但是后來實現起來太繁瑣,所以我將單詞數和詞頻統計分成兩個模塊,先用一段簡單的代碼實現單詞數的統計,下面主要考慮詞頻統計,在實現詞頻統計時,遇到分隔符且首部至少四個字母,即可判斷此為一個單詞,用word結構體存儲單詞,使用鏈表結構將這些單詞串接起來
struct Word {
char word[MAX_WORD_LENGTH];
int num;
Word *next;
Word *previous;
Word() {
word[0] = 0;
num = 0;
next = nullptr;
previous = nullptr;
}
Word(char* theWord, int theNum) {
strcpy_s(word, theWord);
num = theNum;
next = nullptr;
previous = nullptr;
}
//如果使用了指針,在析構函數中釋放
~Word() {
delete next;
next = nullptr;
}
};
3、計算模塊接口部分的性能改進。
1)在進行單詞匹配的時候,用hash散列快速匹配,模設置為128,這樣可以大大節省查找單詞的時間:
int WordList::Hash(char* word) {
int HashVal = 0;
while (*word != '\0')
HashVal += *word++;
return HashVal & 127;
}
2)我用一個WordList結構體用於處理單詞提取,詞頻排序,字母序排列,結果輸出等功能
struct WordList
{
private:
int Hash(char *word); //哈希函數
void shiftWord(Word * pWord); //使word前移一格
Word* pWordHead; //指向Word的指針
Word* pWordTail;
WordIndex* index[128]; //哈希索引
public:
WordList();
~WordList();
void addWord(char word[]);
void wordCount(string fileName, WordList &wordList);
void outPut();
};
4、結果測試
運行程序
數據文本
結果文本
5、總結
我認為我的計算機基礎比較薄弱,說實話,這次作業真的很吃力,但是在這個過程中我學習到很多東西,軟件工程實踐雖然辛苦,但是比起能收獲到那么多知識,我覺得值了。