福大软工1816 · 第二次作业 - 个人项目
GitHub地址:https://github.com/Yasin-cxh/personal-project
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) | 
|---|---|---|---|
| Planning | 计划 | 20 | 30 | 
| · Estimate | · 估计这个任务需要多少时间 | 30 | 120 | 
| Development | 开发 | ||
| · Analysis | · 需求分析 (包括学习新技术) | 400 | 540 | 
| · Design Spec | · 生成设计文档 | 20 | 30 | 
| · Design Review | · 设计复审 | 20 | 0 | 
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 120 | 140 | 
| · Design | · 具体设计 | 30 | 20 | 
| · Coding | · 具体编码 | 240 | 360 | 
| · Code Review | · 代码复审 | 60 | 70 | 
| · Test | · 测试(自我测试,修改代码,提交修改) | 60 | 40 | 
| Reporting | 报告 | ||
| · Test Repor | · 测试报告 | 20 | 40 | 
| · Size Measurement | · 计算工作量 20 | 20 | |
| · Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 70 | 60 | 
| 合计 | 1130 | 1500 | 
需求分析
- 实现一个名为WordCount的命令行程序
 - 输入文件名以命令行参数传入,并统计以下几个指标:
- 统计文件的字符数:
 - 只需要统计Ascii码,汉字不需考虑
 - 空格,水平制表符,换行符,均算字符
 
 - 统计文件的单词总数,单词:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。
- 英文字母: A-Z,a-z
 - 字母数字符号:A-Z, a-z,0-9
 - 分割符:空格,非字母数字符号
例:file123是一个单词, 123file不是一个单词。file,File和FILE是同一个单词 
 - 统计文件的有效行数:任何包含非空白字符的行,都需要统计。
 - 统计文件中各单词的出现次数,最终只输出频率最高的10个。频率相同的单词,优先输出字典序靠前的单词。
按照字典序输出到文件result.txt:例如,windows95,windows98和windows2000同时出现时,则先输出windows2000- 输出的单词统一为小写格式
 - 输出的格式为
 
 
characters: number
words: number
lines: number
<word1>: number
<word2>: number
文件流程图

思路分析
- 
int CharCount(char* argv)
字符统计函数,读入文件,每次读入一个字符并计数,文件读入完后,输出字符数。 - 
int LineCount(char* argv)
行数统计函数,读入文件,每次读入一行并计数,直到文件末尾,输出行数。 - 
int WordCount(char *argv)
统计单词数并输出词频前十的单词。用unordered_map<string, int>记录单词以及其出现的频数,最后用vector将unordered_map<string, int>按频数降序排列,最后输出词频前十的单词。
代码如下: 
int WordCount(char *argv)
{
	//读入文档
	fstream file2;
	string strfile, stmp;
	file2.open(argv);
	int numWordCount = 0;
	while (getline(file2, strfile))
	{
		strfile.append(stmp);
		stmp.clear();
		
		//去除间隔符,单词统计
		for (int i = 0; i < strfile.length(); i++)
		{   
			//小写处理
			strfile[i] = tolower(strfile[i]);
			if (ispunct(strfile[i]))
			{
				strfile[i] = ' ';
				numWordCount++;
			}
		}
		//统计字符频率
		stringstream ss(strfile);
		string strTmp;
		while (ss >> strTmp)
		{
			unordered_map<string, int>::iterator it = strMap.find(strTmp);
			if (it == strMap.end())//strMap中如果不存在当前单词则插入一个新键值对,出现频率为1
			{
				strMap.insert(unordered_map<string, int>::value_type(strTmp, 1));
			}
			else //如果存在则出现频率加1
				strMap[strTmp]++;
		}
		//CountWordFrequency(ss);
	}
	//单词数等于分隔符+1
	if (numWordCount > 0)
		numWordCount++;
	file2.close();
	return numWordCount;
}
                        **函数输出部分**
//Output(strMap);
	ofstream OutputFile("result.txt");
	if (OutputFile.is_open())
	{
		unordered_map<string, int>::const_iterator it;
		OutputFile << "characters: " << numCharCount << endl;
		OutputFile << "words: " << numWordCount << endl;
		OutputFile << "lines: " << numLineCount << endl;
		//排序
		vector<pair<string, int>>vtMap;
		for (auto it = strMap.begin(); it != strMap.end(); it++)
			vtMap.push_back(make_pair(it->first, it->second));
		sort(vtMap.begin(), vtMap.end(),
			[](const pair<string, int> &x, const pair<string, int> &y) -> int {
			return y.second < x.second; });
		int count = 1;
		for (auto it = vtMap.begin(); it != vtMap.end(); it++)
		{
			if (count > 10)
				break;
			OutputFile << it->first << ':' << it->second << endl;
			count++;
		}
		//cout << count << endl;
	}
性能分析

单元测试
单元测试一直完成不了,IDE老是报异常,百度了也不知道为什么,只好手动测试。
这是测试前写的简单测试用例:
namespace UnitTest1
{		
	TEST_CLASS(UnitTest1)
	{
	public:
		
		TEST_METHOD(TestMethod1)
		{
			char file[] = "D:\\1.txt";
			int num = Tool::CharCount(file);
			Assert::IsTrue(num == 1);// TODO: 在此输入测试代码
		}
	};
}
namespace UnitTest2
{
	TEST_CLASS(UnitTest1)
	{
	public:
		TEST_METHOD(TestMethod1)
		{
			char file[] = "D:\\1.txt";
			int num = Tool::LineCount(file);
			Assert::IsTrue(num == 1);// TODO: 在此输入测试代码
		}
	};
}
- 
测试没有字符
![]()
 - 
测试统计Hamlet
![]()
 
异常处理
if(argv == NULL)
	{
		cout << "error: you do not put a file " << endl;
	}
	if (argc > 2)
	{
		cout << "error: you put too many files" << endl;
	}
心得体会
从看到这次作业使用C++或Java来写之后我就觉得凉了,Java 0基础,C++基础差而且忘的差不多了。还是头铁的选择用C++来写。分析完题目,脑中充满了疑惑。这概念是什么?不懂,那概念是什么?也不懂。在这次个人项目中,相比于敲代码,我花了更多的时间去查找资料。这一周的时间让我学会了不少新知识。Learn by doing的概念确实很有效果,但对于基础太差的人来说,有时候会陷入learn的死循环。刚开学这段时间白天工作比较忙,只好深夜激情学习。但有时候花了两三个小时就为了解决一个基本步骤,真让人感叹当初没有好好学习。熬了几个晚上之后,基础功能算是完成了吧。不过遗憾的是单元测试一直不能用,请教了舍友,他们也无能为力,不知道是我操作有问题还是IDE有问题,很疑惑。接口封装只是把一部分函数封装在了.h头文件中,没有全部实现函数接口封装。暑假看《构建之法》,知道对一个软件项目不仅仅是写代码这么简单,等到亲身实践才懂得代码之外的事还有很多,甚至比代码本身更重要,这一点在这次作业中深有体会。养成在分析问题中记录问题的习惯,按照这些问题估计时间,需要查找哪些资料等。有时间把C++基础知识再看看。
                    
                


                
            
        
浙公网安备 33010602011771号