第二次软件作业

GIT地址 我的GIT地址
GIT用户名 1945680782-wind
学号后五位 61216
博客地址 我的博客
作业链接 作业

博客内容:

Part1.请以博客记录的方式,体现环境配置过程(包括遇到了哪些问题,你是如何解决的)

1.配置环境

(1)先进入官网下载:点击下载链接,浏览器将自动开始下载

(2)勾选c++,然后在选择自己喜欢的主题就行了
在这里插入图片描述

2.Git

(1)进入阿超的四则运算的网站点击图片所指位置

在这里插入图片描述
(2)安装好git之后,将蓝色那部分网址克隆下来在这里插入图片描述
(3)在 我的电脑 中任意找一个目录,打开 Git 命令行软件(Windows上可在空白处右键打开 Git Bash ),输入 git clone 地址,地址即我们刚刚复制的项目地址然后就可以接下来的操作了(详细操作后面会做说明)
(4)遇到的问题:

  • 问题
就是在使用github的时候,由于第一次用,里面很多不是很熟系用起来也很不顺手,操作流程不是很清楚
  • 解决办法
再上网查询资料和咨询同学之后使用并且不断测试慢慢了解了许多,也比之前用的更加顺手

Part2.代码设计的思路

在这里插入图片描述

这次作业我将它分为了三个板块1.随机产生四则运算2.计算四则运算的答案这(当时为了优化代码量费了不少时间最后选择用栈来计算)3.输出和打印。首先呢我用到了以下头文件
#include "pch.h"
#include <iostream>
#include <ctime>
#include <fstream>
#include<stack>
#include<string>
#include<sstream>
#include<time.h>
#include<iomanip>
现在我来讲述我的代码思路首先是第一部分随机产生四则运算,因为题目要求不能有非整数,而且不能出现非整数于是我就想到了用个函数bool Judge()判断是否符合阿超的要求,这个函数呢我是将总体模块化了,将一个表达式从左到右分成两个数来进行判断是否符合条件,这样做的好处是1.无论这个表达式多长都可以很好的判断,不需要因表达式的长度不同而在分布进行讨论优化了代码量2.因为我们是随机产生的表达式并不知道里面计算顺序怎样(乘除法优先级高于加减),而这种分步就把每一种计算顺序都检查了一遍保证了我们式子一定符合要求
using namespace std;
int question_num;//从用户端输入的问题个数
char option[5] = { '+', '-', '*', '/' };//将四则运算符号放在option里
int arr[4];//一个存放四则运算数字数组
char op[3];//一个存放四册运算符号数组
double calculate1(string str4);
void dayin(int op_cnt, ofstream &阿超的四则运算);
bool Judge(int op_cnt);
bool calculate(int num1, char op_1, int num2);
void CreateQuestion(int question_num, ofstream &阿超的四则运算)//创造question_num个四则运算
{
	for (int i = 0; i < question_num; )
	{
		int op_cnt = rand() % 2 + 2;//从rand中选出2-3个符号,op_cnt即符号个数
		for (int j = 0; j < op_cnt; j++)
		{
			arr[j] = rand() % 100;//从0-99中随机选出一个数放在arr[j]里
			int temp = rand() % 4;//从0-3中取出一个数作为option的下标,这一步实现了化简减少了代码量
			op[j] = option[temp];//option[temp]里的符号存放在op[j]里
		}
		arr[op_cnt] = rand() % 100;//最后一个数(因为数字数始终比字符数大一个)
		if (Judge(op_cnt) == true)//判断这个表达式是否满足阿超的要求
		{
			dayin(op_cnt, 阿超的四则运算);//若满足要求,则打印表达式
			i++;//若满足要求,继续下一个表达式
		}
	}
}
bool Judge(int op_cnt)//判断这个表达式是否满足阿超的要求
{
	for (int i = 0; i < op_cnt; ++i)
	{
		bool judge = calculate(arr[i], op[i], arr[i + 1]);
		if (judge == false)
			return false;
	}
	return true;
}
bool calculate(int num1, char op_1, int num2)//判断单个表达式是否满足要求
{
	int ans;
	switch (op_1)
	{
	case '+':
		ans = num1 + num2;
		break;
	case '-':
		ans = num1 - num2;
		if (ans < 0)
			return false;
		break;
	case '*':
		ans = num1 * num2;
		break;
	case '/':
		if (num2 == 0 || num1 % num2 != 0)//判断分母不为零并计算是否是分数
			return false;
		break;
	default:
		cout << "发生错误" << endl;
	}
	return true;
}
现在就是第二部分,这部分我当时花了很多时间,因为计算答案的话虽然可以用if或者switch将每种可能性一一列出来然后把值输入进去但是这代码量就太大了,虽然我后面用栈来进行四则运算代码量也没减少多少。但是如果我们用if或者switch这种枚举法将每种可能性依依列出来,现在可能没感觉因为运算符最多也只有3个,一一列出来也64+16(两个运算符的)种可能但是如果运算符变成4个,5个甚至更多的时候一一列出来可就是以4的阶乘倍在增长了,因为代码越多犯错的概率越大,我就选择了用栈来计算因为就算后期运算符再增加几个也只用改下代码输入就可以实现,这时候代码优化的就不是一点点了。
string change(int num0)//将表达式转换为字符串类型
{
	char str[100];
	_itoa_s(num0, str, 10);
	string str1 = str;
	return str1;
}


int judge1(char c1, char c2)//设置+.-.*./.(.)的优先等级
{
	int a1, a2;
	if ('+' == c1 || '-' == c1) a1 = 3;
	if ('*' == c1 || '/' == c1)a1 = 5;
	if ('(' == c1) a1 = 1;
	if (')' == c1) a1 = 7;
	if ('#' == c1) a1 = 0;
	if ('+' == c2 || '-' == c2)a2 = 2;
	if ('*' == c2 || '/' == c2)a2 = 4;
	if ('(' == c2) a2 = 6;
	if (')' == c2) a2 = 1;
	if ('#' == c2) a2 = 0;
	if (a1 > a2) return 1;
	if (a1 == a2) return 0;
	if (a1 < a2) return -1;
}
//符号运算函数
double run1(char c, double d1, double d2)//计算四则运算
{
	switch (c)
	{
	case '+':
		return d1 + d2;
		break;
	case '-':
		return d1 - d2;
		break;
	case'*':
		return d1 * d2;
		break;
	case '/':
		return d1 / d2;
		break;
	default:
		return 0.0;
		break;
	}
}
double calculate1(string str4)//计算表达式的值
{
	char  op1[6] = { "+-*/#" };
	//给表达式字符串str添加'#'结束标识符
	str4.append(1, '#');
	stack<char> OPTR;//运算符栈
	stack<double> OPND;//操作数栈
	int a = -1;
	//先将#符号入栈
	OPTR.push('#');
	while (true)
	{
		int b = a + 1;
		a = str4.find_first_of(op1, a + 1);
		if (a == string::npos) break;
		if (a != b)
		{
			string ss(str4, b, a - b);
			double d = atof(ss.c_str());
			//数据先入栈
			OPND.push(d);
		}
		//运算符优先级比较
		int ju = judge1(OPTR.top(), str4[a]);
		if (-1 == ju)//栈外优先级大直接入栈
		{
			OPTR.push(str4[a]);
		}
		if (0 == ju)//栈内外优先级相等则出栈
		{
			OPTR.pop();
		}
		if (1 == ju)//栈内优先级大,出栈进行运算
		{
			double d1 = OPND.top();
			OPND.pop();
			double d2 = OPND.top();
			OPND.pop();
			d1 = run1(OPTR.top(), d2, d1);
			//运算结果入栈
			OPND.push(d1);
			OPTR.pop();
			a--;
		}
	}
	//删除表达式最后的'#'结束标识符
	str4.erase(str4.length() - 1, 1);
	return  OPND.top();
}
四则运算有优先级,比如乘和除都需要先算,如果把符号入栈就可以入一次检查一次什么符号,下一个入栈的时候就判断谁更优先,就出栈进行运算,把这个符号入栈。于是我就加了int judge1()设置+.-.*./.()的优先等级当时由于看教材忘了不需要判断括号优先级导致把括号也加进去了
现在到了第三部分打印,我设置了个void dayin()函数,为了方便记忆我采取了用拼音来命名这个函数,打印函数的功能有两个1.将式子输出到屏幕上(不输出答案)2.将式子和答案输入到文件(文件上有答案)。
void dayin(int op_cnt, ofstream &阿超的四则运算)//打印表达式
{
	string str1;
	for (int i = 0; i < op_cnt; i++)
	{
		cout << arr[i];
		cout << op[i];
		阿超的四则运算 << arr[i];
		阿超的四则运算 << op[i];
	}
	if (op_cnt == 2)
	{
		str1 = change(arr[0]) + op[0] + change(arr[1]) + op[1] + change(arr[2]);
	}
	else
	{
		str1 = change(arr[0]) + op[0] + change(arr[1]) + op[1] + change(arr[2]) + op[2] + change(arr[3]);
	}
	cout << arr[op_cnt] << "=" << endl;
	阿超的四则运算 << arr[op_cnt] << "=" << calculate1(str1) << endl;
}
int main()
{
	srand((unsigned int)time(NULL));//让伪随机数真的的随机
	ofstream 阿超的四则运算;
	阿超的四则运算.open("阿超的四则运算.txt");
	cout << "你需要产生题目的个数为" ;
	cin >> question_num;
	CreateQuestion(question_num, 阿超的四则运算);
	return 0;
}

问题: 用栈运算来计算随机产生式子答案的时候,碰到了一个棘手的问题,因为但是写的时候是模块化写的,每个函数都有一个特定功能测试的时候也是每个函数分开写的,但最后将栈运算整合到一起的时候就出现了问题,就是栈的输入端是string,而我产生的符号和数字都是以char和int存储的,导致表达式很难输入到栈运算
解决办法: 当时查阅资料发现了itoa, 能将将整数转换为字符串。char * itoa ( int value, char * buffer, int radix );它包含三个参数:value, 是要转换的数字;buffer, 是存放转换结果的字符串;radix, 是转换所用的基数,2-36。如,2:二进制,10:十进制,16:十六进制;然后我用他构建了string change()将表达式转换为字符串类型,最终将这个问题解决
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190922190958427.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dpbmR4Z2w=,size_16,color_FFFFFF,t_70)

在这里插入图片描述

Part3.记录你使用github克隆项目以及提交代码的整个过程(包括遇到的问题,你是如何解决的)

1.首先作业的项目放在了源代码管理github上,所以我们需要登录github(如果没有账号的就注册一个github账号)

2.项目的克隆找到班级仓库地址:班级仓库地址然后我们进入页面后再按 推荐参考教程这里面的步骤

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.使用GitGui上传在这里插入图片描述

在这里插入图片描述
问题

开始按照Gitbash上传不成功 ,总是提示有错误

解决办法:

最后我通过Gitgui把代码上传上去了

Part4.记录你对项目进行单元测试和回归测试的过程(包括你遇到的问题,解决的方法是什么)

1、新建一个VS项目:备注:

本例中创建的是win32 的控制台工程
创建工程时,推荐在属性设置中,c/c++ ——>代码生成配置为下图:
在这里插入图片描述

备注:

本例中创建的是win32 的控制台工程
创建工程时,推荐在属性设置中,c/c++ ——>代码生成配置为下图:
在这里插入图片描述
2、新项目调试通过之后,右键解决方案,选择:新建项目,添加--->测试项目
在这里插入图片描述
3、在测试项目上右键添加引用,选择刚才构建的工程
在这里插入图片描述
4、在原工程上右键,选择属性--将属性的默认值修改为.lib
在这里插入图片描述
最后,在生成的测试文件app总的TEST_METHOD 函数体内添加测试代码,可在测试资源管理器中进行调试
5、点生成之后,点击测试

在这里插入图片描述

结果显示:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

问题:开始遇到一些小问题
解决办法:上网查阅资料按照网上的步骤再试一次就解决了

Part5.总结

这次学习也算是一大进步吧让我从边写边改的模型过渡到了原型模型。不断的优化代码量,让我对于上个学期栈的知识进行了回顾,对入栈和出栈还有栈的优先级又加深了一遍,还有就是掌握了char * itoa ( int value, char * buffer, int radix ),懂得了怎么写函数来转化成字符串,掌握的过程虽然是费力的但辛苦也得到了回报,让我掌握新的知识让我很开心。本次的学习让我对GitHub新工具的使用有了一定的了解,开始使用的时候确实很痛苦,用起来也不是很顺手,但慢慢的学习使我掌握了一些基本的使用方法,我以后也会多加练习更好的去掌握GitHub。这次使用了很多函数,我将它们功能依依分开然后嵌套相互调用,虽然在拼装在一起的时候出了一些问题,也费了我很多时间去解决,但我从中学到了新的知识并且使我模块化的编程能力又提升了。在网上的查找了单元测试,单元测试也是我这次活动的巨大收获。

posted on 2019-09-21 20:09  诗芯  阅读(251)  评论(2编辑  收藏  举报

导航