软工实践寒假作业(2/2)

这个作业属于哪个课程 软件工程2021W班
这个作业要求在哪里 作业要求
这个作业的目标 作业目标
作业正文 ......
其他参考文献 ...

part1:阅读构建之法并提问

问题1

我看了这段文字(市面上有这么多不完美的产品,软件团队为什么还要把这些不完美的软件发布出来呢?为什么不能等到它们完美之后再发布?**软件工程的一个重要任务,就是要决定一个软件在什么时候能“足够好”,可以发布。)有这个问题(如何决定一个软件足够好)我的困惑是(除了确保bug尽可能少之外,还应进行哪些操作)

问题2

我看了这段文字(既然代码复审能发现这么多问题,有这么好的效果,如果我们每时每刻都在代码复审的状态,那不是很好么?事实上,极限编程(Extreme Programming)正是这一思想的体现——为什么不把一些卓有成效的开发方法用到极致(Extreme),让我们无时无刻地使用它们? ——p84页 极限编程对工程师提出了更高的要求。这种要求不关乎技术水平,也不关乎学历水平或工作经验。这种要求是对一个人的心智、道德修养的更高要求。结队编程中,编码不再是私人的工作,而是一种公开的“表演”。程序员的代码、工作方式、技术水平都变得公开和透明,这也许是一些人不喜欢这一方式的原因。 ——P87)有这个问题(极限编程和结对编程是什么,它们有怎样的联系)通过查询资料可知(极限编程是一种轻量级的、灵巧的、简单的软件工程方法。与传统的开发过程不同,极限编程的核心活动体现在需求→测试→编码→设计过程中。因此适用于规模小、进度紧、需求变化大、质量要求严的项目。它希望以最高的效率和质量来解决用户目前的问题,以最大的灵活性和最小的代价来满足用户未来的需求。结对编程,也就是两个人写一个程序,其中,一个人叫Driver,另一个人叫Observer,Driver在编程代码,而Observer在旁边实时查看Driver的代码,并帮助Driver编程。并且,Driver和Observer在一起时可以相互讨论,有效地避免了闭门造车,并可以减少后期的code review时间,以及代码的学习成本。)仍存在的困惑是(它们二者之间有什么联系)

问题3

我看了这段文字(用户体验设计的一个重要目的就是要降低用户的认知阻力(Cog-nitive Friction),即用户对于软件界面的认知(想象某事应该怎么做,想象某操作应该产生什么结果)和实际结果的差异。我们来看一个具体的例子,如果用户(一个生活在中国二线城市,有高中文化水平,有基本计算机基础的成年人)要在一个文稿中写居中的一句话,在下表所列的各种工具中,用户是怎么才能做到的。 倘若认知阻力大,学习曲线就会比较陡;但是经过学习和练习,如果用户适应了新的认知模式,工作效率便会有较大的提高。)我的问题是(如果大多数用户都对某种功能不了解,也不经常用到,是否需要继续用户体验设计)我认为(针对这类功能应该配备简要的使用流程图,进行推广)

问题4

我看了这段文字(单元测试必须由最熟悉代码的人(程序的作者)来写。)提出的问题是(如果程序的作者没有意识到某些问题,是否需要其他人的协助)仍存在的疑惑是(几个人一起完成单元测试,共同商讨会不会更好)

问题5

我看了这段文字(软件团队的人员也会流动,新的成员要尽快读懂已有的程序,了解程序的设计,这叫做程序理解。)我的提问是(如果程序较为复杂,通过何种方式能最大效率的进行程序理解)我认为(不断在写程序的同时,扩展视野,对于加快读懂程序很有帮助)。仍存在的疑惑是(如果只是刚开始涉足某个领域的话,通过什么方法能高效率的进行程序理解)

附加题(大家知道了软件和软件工程的起源,请问软件工程发展的过程中有什么你觉得有趣的冷知识和故事?)

软件工程专业正式开始的标志:1968年和1969年,北约(NATO)科学委员会(NATO Science Committee)赞助了两场关于软件工程的会议(Garmisch,Germany - see conference report),这给了该领域最初的推动力。许多人认为这些会议标志着软件工程专业的正式开始。

part2:WordCount编程

github项目地址

github

PSP表格

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

解题思路描述

将功能划分为统计字符数,统计行数,统计有效单词,统计词频。
对有效单词的判断使用到正则表达式,如果满足正则表达式则让单词数加1.
对词频的统计用到pair(对组).对vector中的第一个数据到最后一个数据排列。因为vector中的数据类型是pair,根据自定义的比较函数,当pair的second(词语出现次数)相等时,first(单词)小的在前面(若有并列,则按递增字典序输出)。

代码规范制定链接

codestyle

设计与实现过程

charNum统计文件中的字符数
lineNum统计行数
wordNum统计有效单词数
wordFre统计词频
WordCount主函数
具体实现
charNum

int charNum(char * filename)//计算字符数,包括(空格,制表符,换行等)
{
	int count = 0;
	char c;
	ifstream file;
	file.open(filename);
	if (!file.is_open())
	{
		cout << "文件打开失败";
	}
	while ((c = file.get()) != EOF)
	{
	    count++;
	}
	file.close();
	return count;
}

lineNum

int lineNum(char *filename)//计算有效行数
{
	ifstream file;
	file.open(filename);
	if (!file.is_open())
	{
		cout << "文件打开失败";
	}
	int count = 0;
	string s;
	while (getline(file, s))
	{
		if (s != "\0")
		{
			count++;
		}
	}
	file.close();
	return count;
}

wordNum

int wordNum(char * filename)//计算符合条件的单词总数
{
	ifstream file;
	file.open(filename);
	if (!file.is_open())
	{
		cout << "文件打开失败";
	}
	int count = 0;
	string s;
	regex r("\\b[a-zA-Z]{4}[a-zA-Z0-9]*", regex::icase);
	while (file >> s) 
	{
		smatch m;
		while (regex_search(s, m, r)) //搜索符合正则表达式的单词
	    {
			count++;
			s = m.suffix().str();
		}
	}
	file.close();

	return count;
}

wordFre

map<string, int> Map;
void wordFre(char *filename)//频率最高的十个单词 
{
	ifstream file;
	file.open(filename);
	if (!file.is_open())
	{
		cout << "文件打开失败";
	}
	string s;
	regex r("\\b[a-zA-Z]{4}[a-zA-Z0-9]*", regex::icase);
	while (file >> s) 
	{
		for (int i = 0; i < s.size(); i++)
		{
			if (s[i] <= 'Z'&&s[i] >= 'A')//不区分大小写,将所有大写字母变成小写
			{
				s[i] = s[i] + 32;
			}
		}
		smatch m;
		while (regex_search(s, m, r)) 
		{
			Map[m[0]]++;
			s = m.suffix().str();
		}
	}
	file.close();
}

WordCount

int main(int argc,char** argv)
{
	int count = 10;
	ofstream fileOutput;
	char filename[105]= "input.txt";
	fileOutput.open("output.txt", ios::app);
	fileOutput << "characters: " << charNum(filename) << endl;
	fileOutput << "lines: " << lineNum(filename) << endl;
	fileOutput << "words: " << wordNum(filename) << endl;
	wordFre(filename);
	vector<pair<string, int> > vec;
	extern map<string, int> Map;
	for (auto u : Map) 
	{
		vec.push_back(u);
	}
	sort(vec.begin(), vec.end(), cmp);
	for (auto u : vec)
	{
		if (count)//输出频率最高的10个单词
		{
			fileOutput << "<" << u.first << ">" << ":" << " " << u.second << endl;
			count--;
		}
		else break;
	}
	return 0;
}

性能改进

原来在有效单词判断时采用一个字符一个字符判断,后来改成用正则表达式判断符合要求的单词。

单元测试

测试了字符,行数,空白文件等输出是否正确。
unittest

异常处理说明

文件打开失败

	if (!file.is_open())
	{
		cout << "文件打开失败";
	}

心路历程与收获

本次实践虽然代码量不大,但是需要注意的细节有很多,稍不注意就会有许多麻烦产生。这更加让我感受到了编写一个程序,一定要专注。
一种功能的实现可以有多种方法,通过本次实践让我学会了一种方法如果存在问题,始终不能解决,要及时寻找其他方法,可能会更轻松。
学会了github的使用,让写好的代码能够有序的保存。
通过单元测试,可以判断自己的代码的准确性,对任何一个程序都十分重要。

posted @ 2021-03-05 15:25  FTDKF  阅读(93)  评论(2编辑  收藏  举报