结对编程—WordsCount
Posted codingbyjusticexu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结对编程—WordsCount相关的知识,希望对你有一定的参考价值。
目录
Part1 Github项目地址
Fork仓库的Github项目地址 | git@github.com:JusticeXu/WordCount.git |
---|---|
结对伙伴GIthub地址 | npc1158947015 |
Part2 PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 18 |
· Estimate | · 估计这个任务需要多少时间 | 900 | 903 |
Development | 开发 | 600 | 633 |
· Analysis | · 需求分析 (包括学习新技术) | 60 | 53 |
· Design Spec | · 生成设计文档 | 20 | 17 |
· Design Review | · 设计复审 (和同事审核设计文档) | 15 | 13 |
· Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
· Design | · 具体设计 | 30 | 30 |
· Coding | · 具体编码 | 360 | 400 |
· Code Review | · 代码复审 | 40 | 40 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 60 |
Reporting | 报告 | 60 | 60 |
· Test Report | · 测试报告 | 20 | 20 |
· Size Measurement | · 计算工作量 | 20 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
合计 | 870 | 903 |
Part3 需求分析
文件统计软件wordCount功能如下:
Core计算模块
? 1.统计文件的字符数函数
? 2.统计文件的单词总数函数
? 3.统计文件的有效行数函数
? 4.统计文件中单词出现的次数,按字典序输出频率最高的10个单词或者词组函数
个性输出模块
? 1.自定义输出:能输入用户指定的前n多的单词与其数量
最终实际的软件,除了核心的计算模块以外,还要让这个Core模块和使用它的其他模块之间要有一定的API交流
通过设计GUI界面进行实现
思维导图:
Part 4 代码框架与接口
代码规范
参考资料:Google C++代码规范
本来觉得自己写的代码其实算是足够规范的,但是在比较分析了结对伙伴的代码后,觉得人和人的代码风格还是存在让人诧异的差异的,因此找到了目前最为规范的Google C++代码规范(李开复鼎力推荐)拿来阅读。整体阅读下来大概花了一个小时左右。给我最大的感觉是,像Google,Tencent这样的技术公司,对于整体框架安全性的追求远远超过对技术中淫技巧术的追求,还有就是对可读性的要求也非常高,下面是一些例子:
1.在任何能够使用const的情况下,都用使用const。
2.?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????? ????????为避免拷贝构造函数、赋值操作的滥用和编译器自动生成,可声明其为private且无需实现。
3.要尽可能得对自己的代码编写注释。
4.代码整体风格要尽量统一:每一行代码字符数不超过80,不使用非ACSII字符,使用时必须使用UTF-8格式等等
但是也有一些东西讲得和老师传授的东西不一样,所以也不能完全地照搬规范,让自己的代码美观可读,整体风格一致,那就是最好看的代码。
计算模块接口的设计与实现过程。设计包括代码如何组织
我们一共实现了6个类,其中包括核心计算类core()和两个异常处理接口。
1.void generate(),用来实现整体功能的耦合;
2.Core();构造函数;
3.bool IsValid();检查每次录入的文本是否符合要求,若满足则返回true,否则返回false;
4.void Copyresult(int result[CELL], int temp[number]);将结果复制到result中;
5.bool TraceBackSolve(int pos);回溯过程是否有正确输出,若有则输出并返回true,否则返回false;
6.void show(int result[CELL]) 自定义输出用户指定的内容;
具体功能函数实现
字符统计函数
#include <iostream>
#include <string>
using namespace std;
int CharacterCount(string sentence);
int main(){
string Mystring;
cout << " Type in the string you would like to use: " << endl;
getline(cin, Mystring); // inputs sentence
cout << " Your string is: " << Mystring << endl;
cout << " The string has " << CharacterCount(Mystring) << " characters " << endl;
system("pause");
return 0;
}
int CharacterCount(string sentence){
int length = sentence.length(); // gets lenght of sentence and assines it to int length
int character = 1;
for (int size = 0; length > size; size++)
{
if (sentence[size]>='A'&&sentence[size]<='Z') character++;
else if (sentence[size]>='a'&&sentence[size]<='a') character++;
else if (sentence[size]>='0'&&sentence[size]<='9') character++;
else character++;
}
if ( sentence[0] == ' '/*space*/ )
character--;
return character;
}
代码自审:这一部分的代码比较简单,一开始就想到了用for循环很快就能解决问题。然后要注意当遇到空文档时,怎么保证输出结果正确,是这个功能中最难想到的一部分。
单词统计函数
#include <iostream>
#include <string>
using namespace std;
int WordCount(string sentence);
int main()
{
string Mystring;
cout << " Type in the string you would like to use: " << endl;
getline(cin, Mystring); // inputs sentence
cout << " Your string is: " << Mystring << endl;
cout << " The string has " << WordCount(Mystring) << " words " << endl;
system("pause");
return 0;
}
// counts the words
int WordCount(string Sentence)
{
int length = Sentence.length(); // gets lenght of sentence and assines it to int length
int words = 1;
for (int size = 0; length > size; size++)
{
if (Sentence[size] == ' '/*space*/)
words++; // ADDS TO words if there is a space
}
if ( Sentence[0] == ' '/*space*/ )
words--;
return words;
}
代码自审:这一部分的功能实现和字符统计类似,无非是当读到空格时,words加1。也算是很简单了。下面的功能也是,当读到 时,行数加1。代码如下。
有效行数统计函数
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int CountLines(char *filename)
{
ifstream ReadFile;
int n=0;
string tmp;
ReadFile.open(filename,ios::in);//ios::in 表示以只读的方式读取文件
if(ReadFile.fail())//文件打开失败:返回0
{
return 0;
}
else//文件存在
{
while(getline(ReadFile,tmp,'
'))
{
n++;
}
ReadFile.close();
return n;
}
}
int main()
{
char filename[]="inFile.txt";
cout<<"该文件行数为:"<<CountLines(filename)<<endl;
return 0;
}
词频统计函数
该项目的核心任务分为两部分,一是在文本中识别出不同的单词,二是统计所有单词并将这些单词按照词频进行排序。可以将这个部分分为四个模块:输入模块,状态模块,统计模块,输出模块。
识别文本中的单词,我使用的是一个有限状态机模型。
假如文本中没有连词符 ‘-‘ ,那么问题十分简单,只有两个状态,一个是单词内部,一个是单词外部,相互转换的条件则是在单词内部的状态下检测到一个非字母字符,或者在单词外部的状态下检测到一个字母字符。
当文本中出现了连词符,那么情况会复杂一些,不过仍然不会太复杂。我们增加了一个临界状态,当读入一串字母之后突然检测到了一个连词符,则会进入到这个状态。这个状态不会持续,一旦读入下一个字符,就会根据它是字母或者非字母字符,进入到单词内部或单词外部的状态。
使用这一个3状态7过程的状态机模型,可以完美地满足需求。
添加单词:
int p_index = Hash(word); //利用单词计算哈希索引
WordIndex* pIndex = index[p_index];
while (pIndex != nullptr) {
Word *pWord = pIndex->pWord;
if (!strcmp(word, pWord->word)) { //在哈希索引对应的几个单词中,找到我们需要找到的单词
pWord->num++; //如果找到了,首先把这个单词的词频+1
//接着根据词频调整单词的位置
Word *qWord = pWord->previous;
while (qWord->num < pWord->num) {
if (qWord == pWordHead)
return;
shiftWord(pWord);
qWord = pWord->previous;
}
//然后再在同一词频下根据单词在字典中的顺序调整位置
while (strcmp(qWord->word, pWord->word) > 0) {
if (qWord->num > pWord->num) return;
shiftWord(pWord);
qWord = pWord->previous;
}
return;
}
pIndex = pIndex->next;
}
遇到首次遇到的单词,添加索引:
// Copyright[2018]<Star>
#include "WordList.h"
WordList::WordList() {
for (int i = 0; i < MAX_INDEX_NUM; i++) index[i] = nullptr;
wordNum = 0;
}
WordList::~WordList() {
Word *temp;
for (int i = 0; i < MAX_INDEX_NUM; i++) {
for (Word *p = index[i]; p != nullptr;) {
temp = p;
p = p->next;
delete temp;
}
}
}
void WordList::addWord(char word[]) {
// Add the word to the WordList (or word frequency +1)
int p_index = Hash(word);
if (index[p_index] == nullptr) {
index[p_index] = new Word(word, 1, index[p_index]);
return;
}
Word* pWord = index[p_index];
while (pWord->next!= nullptr) {
if (!strcmp(word, pWord->word)) {
pWord->num++;
return;
}
pWord = pWord->next;
}
if (!strcmp(word, pWord->word)) {
pWord->num++;
return;
}
pWord->next = new Word(word, 1, nullptr);
//index[p_index] = pWord;
wordNum++;
}
void WordList::outPut() {
// 100 words are all output via cout
if (wordNum <= 0) return;
if (wordNum > 100) wordNum = 100;
//开辟一片连续的空间以排序(使用最小堆)
Word **word = new Word*[wordNum + 2];
word[0] = word[wordNum + 1] = nullptr;
int iIndex = 0;
Word *pWord;
for (int iWord=1; iIndex < MAX_INDEX_NUM; iIndex++) {
//将索引中的所有结点放入开辟的空间中准备排序
pWord = index[iIndex];
while (pWord != nullptr) {
word[iWord] = pWord; //上滤
upFilter(word, iWord);
pWord = pWord->next;
//如果有一百个以上结点,可以进行取舍,因为总共只需要输出100个结点
if (++iWord > 100) break;
}
if (iWord > 100) break;
}
for (; iIndex < MAX_INDEX_NUM; iIndex++) {
if(pWord==nullptr) pWord = index[iIndex];
while (pWord != nullptr) {
if (word[1]->equal(pWord) == -1) {
word[1] = pWord;
downFilter(word, 50); //下滤
}
pWord = pWord->next;
}
}
heapSort(word, wordNum); //堆排序
//输出100个单词及词频
cout << word[2]->word << ' ' << word[2]->num;
for (int i = 3; i < wordNum + 2; i++) cout << endl << word[i]->word << ' ' << word[i]->num;
delete[]word;
}
int WordList::Hash(char* word) {
int HashVal = 0;
while (*word != '