第一次个人编程作业

https://github.com/chaukiching/personal-project.git

一、PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划
· Estimate · 估计这个任务需要多少时间 30 30
Development 开发
· Analysis · 需求分析 (包括学习新技术) 300 400
· Design Spec · 生成设计文档 20 20
· Design Review · 设计复审 20 15
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 30
· Design · 具体设计 250 300
· Coding · 具体编码 250 300
· Code Review · 代码复审 60 60
· Test · 测试(自我测试,修改代码,提交修改) 200 200
Reporting 报告
· Test Repor · 测试报告 60 60
· Size Measurement · 计算工作量 30 10
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 60 80
· 合计 1310 1505

二、计算模块接口

1.计算模块接口的设计与实现过程。设计包括代码如何组织,比如会有几个类,几个函数,他们之间关系如何,关键函数是否需要画出流程图?说明你的算法的关键(不必列出源代码),以及独到之处。

① 设计要求

本题敏感词检测的要求大致可分为两类:中文敏感词英文敏感词
以下情况为中文敏感词

  • 敏感词中插入除字母数字换行的若干字符,如当山寨为敏感词词汇时,山_寨,山@寨,山 寨等。
  • 敏感词用谐音替换拼音替代拼音首字母替代,如shan寨,栅寨,山Z等。
  • 敏感词为繁体拆分偏旁部首,如氵去工力等。

以下情况为英文敏感词

  • 英文文本不区分大小写,在敏感词中插入若干除换行字母外等其他符号,也属于敏感词,如hello为敏感词时,he_llo,h%ell@o,he llo。

② 因此,我的解题思路就是:

      首先,用read函数读取敏感词文件中的敏感词时,判断敏感词的类型,若为中文,则先利用Utf8ToGbk函数将中文从utf-8编码转换为GBK编码,再利用hanzipinyin函数转换为拼音,并将这些敏感词内容记录。
      其次,利用search函数,按例文每行,每个敏感词进行遍历查找。当敏感词为中文,利用前面存入的中文和拼音查找到敏感词时,添加标记f=1来说明可能找到了敏感词,并将字符记录下来,若不符合要求则f=0,查找到敏感词后记录(谐音替换、拆分偏旁部首较为困难,由于能力有限,思考很久没想出解决方法);当敏感词为英文,方法一样,只要注意英文敏感词的要求即可。
      最后,用print函数将得到的答案在文件中输出。

③ 函数:

  • hanzi():实现中文敏感词的查找功能。
  • yinwen():实现英文敏感词的查找功能。
  • search():作为程序核心,用于读取例文文件,按行对敏感词分类判断,调用hanzi函数及yinwen函数进行查找。
  • read():读取敏感词词汇文件。
  • print():输出答案文件。
  • hanzipinyin():将中文敏感词转换为拼音。
  • Utf8ToGbk():将文件读取的中文由utf-8编码转换为GBK编码。

2.计算模块接口部分的性能改进。记录在改进计算模块性能上所花费的时间,描述你改进的思路,并展示一张性能分析图(由VS 2019、JProfiler或者Jetbrains系列IDE自带的Profiler的性能分析工具自动生成),并展示你程序中消耗最大的函数。

① 性能分析图:

  • 根据性能分析图来看,可以看出程序在打开文件读取数据的时间占了极大比例,由于程序对敏感词以及例文进行遍历查询的操作,多次使用for语句和if语句调用search函数hanzi函数以及yinwen函数来查找例文中的敏感词,因此耗费了大量时间。

② 程序中消耗最大的函数:

int hanzi(string ans, string org,int num,int  n, int j)
{
	for (int i = 0, m = 0, f = 0; i < org.length(); i++)
	{
		if (org[i] == w[n].word[m] && org[i + 1] == w[n].word[m + 1] && org[i + 2] == w[n].word[m + 2])//utf-8汉字占3字节
		{
			f = 1;//作为判断是否遇到敏感词的标志*/
			ans = ans + org[i] + org[i + 1] + org[i + 2];
			m = m + 3;
			if (m > w[n].word.length() - 1 && ans.length() > w[n].word.length() - 1)//超出长度则表示已找到敏感词,并开始继续查找
			{
				m = 0;
				f = 0;
				s[num].words = w[n].word;
				s[num].anss = ans;
				s[num].h = j;
				num++;
				ans = "";
				continue;
			}
			i = i + 2;
			continue;
		}
		if (org[i] >= '0' && org[i] <= '9' || org[i] >= 'A' && org[i] <= 'Z' || org[i] >= 'a' && org[i] <= 'z')
		{
			f = 0;
			ans = "";
			continue;
		}//敏感词中插入字母、数字、换行的若干字符就不属于敏感词
		if (f == 1)
			ans = ans + org[i];
	}
	return num;
}
int yinwen(string ans, string org,int num, int  n, int j)
{
	for (int i = 0, m = 0, f = 0; i < org.length(); i++)
	{
		if ((org[i] >= 'A' && org[i] <= 'Z') || (org[i] >= 'a' && org[i] <= 'z'))
		{
			if (org[i] == w[n].word[m] || org[i] - w[n].word[m] == 32 || w[n].word[m] - org[i] == 32)//英文文本不区分大小写,在敏感词中不能插入换行、字母
			{
				f = 1;//作为判断是否遇到敏感词的标志*/
				ans = ans + org[i];
				m = m + 1;
				if (m > w[n].word.length() - 1)//超出长度则表示已找到敏感词,并开始继续查找
				{
					m = 0;
					f = 0;
					s[num].words = w[n].word;
					s[num].anss = ans;
					s[num].h = j;
					num++;
					ans = "";
				}
			}
			else
			{
				f = 0;
				m = 0;
				ans = "";
			}
			continue;
		}
		if (f == 1)
			ans = ans + org[i];
	}
	return num;
}
int search(int j,int num,int l)
{
	string org;
	cin >> org;
	ifstream ifile;
	ifile.open(org);// 以读模式打开待检测文件
	if (!ifile)
	{
		cout << "open fail" << endl;
	}
	else
	{
		while (getline(ifile, org))// 从文件读取每行例文
		{
			j++;
			for (int n = 0; n < l; n++)//用循环查找每个敏感词
			{
				string ans;
				if (w[n].hanying == 1)//如果敏感词为汉字
					num = hanzi(ans, org, num, n, j);
				if (w[n].hanying == 0)//如果敏感词为英文
					num = yinwen(ans, org, num, n, j);
			}
		}
	}
	ifile.close();// 关闭打开的文件
	return num;
}

3.计算模块部分单元测试展示。展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路。并将单元测试得到的测试覆盖率截图,发表在博客中。

① 中文测试结果:

② 英文测试结果:

4.计算模块部分异常处理说明。在博客中详细介绍每种异常的设计目标。每种异常都要选择一个单元测试样例发布在博客中,并指明错误对应的场景。

① 输入错误的文件路径出现异常

ifstream ifile;
	ifile.open(words);// 以读模式打开敏感词词汇文件
	if (!ifile) cout << "open fail" << endl;
  • 若找不到所要打开的文件,则会报错。

② 读取一行文件内容出现异常

ifstream ifile;
	ifile.open(org);// 以读模式打开待检测文件
	if (!ifile) cout << "open fail" << endl;
	else
		while (getline(ifile, org))
  • 遍历例文时使用ifile>>输入,若遇到一行里的空格则会停止。

  • 因此要使用getline(ifile, )读取整行。

三、心得

在完成本次作业过程的心得体会

  • 在本次作业的过程中,遇到了很多问题,在同学和百度的帮助下也解决了许多问题,例如:C++程序以读模式打开文件读取数据,并经过程序运行后写入其他文件中;了解了github的用法PSP表格的作用,明白了utf-8编码每个汉字占用3个字节等等知识。由于测试的时候是按照传递命令行参数的方式提供文件的位置,因此还学习了如何在程序里接受命令行参数,最后按照命令行参数的要求修改了代码。本次作业做了很久,但结果仍然不令我满意,很多复杂的操作没有完成好,原来的解题思路没有得到完成,做完最大的感受就是发现了自己和别人的差距很大,以及自己能力的不足。希望在本次作业以后,自己能够多学点东西,多请教老师和同学,在实践中提升自我吧。
posted @ 2021-09-16 21:55  Chauuu  阅读(111)  评论(0)    收藏  举报