2020第一次软工编程作业

这个作业属于哪个课程 软件工程
这个作业要求在哪里 第一次编程作业要求
这个作业的目标 进一步熟悉github,对json文件进行解析并查找
学号 031802443

一、psp表格

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

二、解题思路

思路分析

刚看到题目完全不知道在说什么,只好对照示例代码理解题目,通过样例理解了题意,决定使用c++做作业,人菜却要交作业,那只好模仿样例不做优化的解决了,
虽然可能会出现内存溢出,超时,解析错误等等问题,但至少先让程序跑起来

代码组织思维导图

题目主要可以分为五部分

  • 命令行参数解析
    以前写的代码完全没有用过命令行参数,所以不是很了解,通过搜索引擎查询,学习了用getopt方法处理命令行参数
  • json 文件的读取
    调用第三方的cJSON库来解析json文件
  • 数据统计
    利用map统计,将用户名与项目名和事件对应,并记录次数
  • 统计数据的存储
    将统计出的数据转换为json形式分别存储在三份文件中,分别对应三种不同的查询方式。
  • 统计数据的查询
    根据命令行参数决定查询文件,并利用cjson解析存储的json文件,得到事件次数

三、学习与设计过程

1.git使用

首先关注助教的b站账号,学习github的使用并一键三连 点这里学习git使用

2.命令行参数的知识

利用getopt_long来解析命令行参数 (https://www.cnblogs.com/hnrainll/archive/2011/09/15/2176933.html),但我用的win下的vs2019,编译时找不到对应的头文件,上网查询之后在git上找到了xgetopt库,和getopt用法相同,只要把文件放进项目里即可使用xgetopt

3.数据读取

利用_findfirst与_findnext遍历所有json文件,并将它们打开读取数据

4.数据存储与查询

将map键值对写入文件中,查询时打开对应json文件并解析即可

四、代码说明

由于我是菜鸡,所以代码只是勉强写完了而且能运行,速度应该很慢

对于命令行参数的读取

	string actor_login;
	string repo_name;
	string  event_type;
	int opt;
	int longindex;
	char stri[] = "i::u::r::e::";//短参数的值
	char* str = stri;
	int type = 0;//根据type来决定查询类型
	static struct xoption long_options[] =
	{
		{"user", xrequired_argument,NULL, 'u'},
		{"repo", xrequired_argument,NULL, 'r'},
		{"event", xrequired_argument,NULL,'e'},
		{"init", xrequired_argument,NULL,'i'},
	};//长参数的值
	while ((opt = xgetopt_long(argc, argv, str, long_options, &longindex)) != -1)//通过while循环不停地读取参数
	{
		if (opt == 'i')
		{
			initFile(argv);//初始化数据
			return 0;
		}
		else if (opt == 'u')
		{
			type += 1;
			actor_login = xoptarg;
		}
		else if (opt == 'r')
		{
			type += 2;
			repo_name = xoptarg;
		}
		else if (opt == 'e')
		{
			event_type = xoptarg;
		}
	}

初始化方法

	unordered_map<string, int> map_user_event;
	unordered_map<string, int> map_repo_event;
	unordered_map<string, int> map_user_repo_event;
	struct _finddata_t fileinfo;
	string work_path = get_work_path();//得到当前工作路径
	string in_path = work_path + "\\" + argv[2];//得到数据存放路径
	string curr = in_path + "\\*.json";//指定json后缀文件
	intptr_t handle;
	if ((handle = _findfirst(curr.c_str(), &fileinfo)) == -1)
	{
		return;
	}
	else
	{
		ofstream ofile;
		GetLineAndSave(in_path, work_path, fileinfo.name,
			map_user_event, map_repo_event, map_user_repo_event);
//读取并解析json文件,用引用的方式传map,可以在多次调用中使用同一份unordered_map
		while (!(_findnext(handle, &fileinfo)))//如果还有数据文件,继续之前的操作
		{
			GetLineAndSave(in_path, work_path, fileinfo.name,
				map_user_event, map_repo_event, map_user_repo_event);
		}
		ofstr out_file(work_path);//建立输出类
		out_file.write_data(map_user_event, map_repo_event, map_user_repo_event);//调用输出类将解析并处理好的json文件保存到工作目录下,查询时调用这些文件即可
		_findclose(handle);
	}

查询函数

int search(int type, string actor_login, string repo_name, string  event_type)
{
	int count = 0;
	string work_path = get_work_path();
	string in_name;
	string search_object;
      //根据type不同,改变查找的文件与对应json的key
	if (type == 1)
	{
		in_name = work_path + "\\1.json";
		search_object = actor_login + event_type;
	}
	else if (type == 2)
	{
		in_name = work_path + "\\2.json";
		search_object = repo_name + event_type;
	}
	else if (type == 3)
	{
		in_name = work_path + "\\3.json";
		search_object = repo_name + event_type + actor_login;
	}
	else
	{
		return 0;
	}
//开始读取文件
	ifstream fin(in_name);
	if (!fin)
	{
		cerr << "请检查是否初始化且初始化成功" << endl;
		exit(-1);
	}
//读取文件
	fin.seekg(0, fin.end);
	int length = fin.tellg();
	fin.seekg(0, fin.beg);
	char* temp = new char[length];
	fin.read(temp, length);
//解析生成的cjson文件
	cJSON* cJson_test = cJSON_Parse(temp);
	if (cJson_test == NULL)
	{
		cerr << "parse fail" << endl;
		exit(-1);
	}
	else
	{
//得到所查询的事件次数
		cJSON* cJson_type = cJSON_GetObjectItem(cJson_test, search_object.data());
		if (cJson_type != NULL)
		{
			count = cJson_type->valueint;
		}
	}
	cJSON_Delete(cJson_test);
	fin.close();
	delete temp;
	return count;
}

五、遇到的困难

由于我比较菜,对我而言是相当曲折和艰难的一次作业,很多知识都是临时学习并应用的,理解困难,因此整个程序也没有优化,仅仅是最简单的读取、存储、查找json文件,
速度比较慢,整个程序也比较臃肿,很多地方都是面向过程来进行设计,希望在以后的迭代中能够重构,并对算法进行优化,多看同学的博客,利用多线程来进行优化

六、代码规范

https://github.com/huipai/huipai/blob/master/codestyle.txt

七、总结

在这次实践中学到了很多东西,同时也了解了一部分github的使用,虽然仍旧不怎么熟练,但至少有了不小的进步

posted @ 2020-09-16 23:36  晖派  阅读(133)  评论(1编辑  收藏  举报