福大软工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>记录单词以及其出现的频数,最后用vectorunordered_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++基础知识再看看。

posted @ 2018-09-12 20:40  Yasin_cxh  阅读(195)  评论(1编辑  收藏  举报