首页 > 编程语言 >自动生成小学四则运算题目的命令行程序

自动生成小学四则运算题目的命令行程序

时间:2024-03-25 22:14:11浏览次数:29  
标签:count 题目 命令行 countnum int top 四则运算 ms 分母

这个作业属于哪个课程 软件工程2024 (广东工业大学)
这个作业要求在哪里 结对项目
这个作业的目标 学习完成项目的过程

正文

一、姓名、学号、GitHub

本次项目缺失队友,由个人完成。崔海源3122004779
github地址

二、PSP表格

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

三、效能分析

从效能分析中看,找到消耗最大的分函数为Count,该函数的主要功能计算生成题目的值。计算时,按照题目要求,对小数的数进行输出分母,所以假设每个数都有分母,若为整数则设分母为1,当进行计算时将他们的分母一同计算,最后将数再转化成字符串。计算过程中主要使用后缀表达式进行计算。

四、设计实现过程

该程序分为两种功能,一种是生成题目并计算出答案,另一种是计算给出题目的答案,打印对错结果。
第一种:

第二种:

五、代码说明

随机生成题目代码
string Numandoper(int oper, int bra,int r)//生成具体数字和运算符以及括号 oper个运算符 bra个括号 oper+1个数字
{
	string pro;
	bool mark = true;    //记录上一个运算是否为/,防止分母为0,默认上一个运算不是/
	bool divs = true;		//最多生成一个除号,多个除号太过麻烦
	if (bra == 0)			//不生成括号
	{
		pro += pronum(r,mark) + ' ';          //生成一个数字,r范围
		
		while (oper--)
		{
			pro += Prooper(mark,divs);				//生成一个运算符
			pro += pronum(r,mark) + ' ';          //生成一个数字,r范围
		}

	}
	else if (bra == 1)				//生成一个括号
	{
		int index_l = Randnum(1, oper);			//判断该左括号落在什么位置
		int index_r = Randnum(index_l + 1, oper + 1);		//右括号至少在左括号过两个数的位置
		int beginpro = 1;	//开始生成题目
		while (beginpro <= oper)
		{
			if (index_l == beginpro)		//生成左括号
			{
				pro += '(';
			}
			pro += pronum(r, mark);			//生成一个数字
			if (index_r == beginpro)		//生成右括号
			{
				pro += ") ";
			}
			else
			{
				pro += ' ';
			}
			pro += Prooper(mark, divs);				//生成一个运算符
			beginpro++;
		}
		//出循环还需要加一个数字
		if (index_l == beginpro)		//生成左括号
		{
			pro += '(';
		}
		pro += pronum(r, mark);			//生成一个数字
		if (index_r == beginpro)		//生成右括号
		{
			pro += ") ";
		}
		else
		{
			pro += ' ';
		}

	}
	else                  //生成两个括号,该种情况只有为3个运算符时所有括号才有意义  为避免出现bug,减少了很多种情况
	{
		int index_l = Randnum(1,2);			//左括号位置1
		int index_ls = Randnum(2,3);			//左括号位置2
		int index_r = index_ls==3 ? 4 : Randnum(3, 4);	//右括号位置1
		int index_rs = Randnum(index_r, 4);	//右括号位置2
		int beginpro = 1;	//开始生成题目
		while (beginpro <= oper)
		{
			if (index_l == beginpro|| index_ls == beginpro)		//生成左括号
			{
				if (index_l == index_ls)
				{
					pro += "(( ";
				}
				else
				{
					pro += '(';
				}
				
			}
			pro += pronum(r, mark);			//生成一个数字
			if (index_r == beginpro|| index_rs == beginpro)		//生成右括号
			{
				if (index_r == index_rs)
				{
					pro += ")) ";
				}
				else
				{
					pro += ") ";
				}
			}
			else
			{
				pro += ' ';
			}
			pro += Prooper(mark, divs);				//生成一个运算符
			beginpro++;
		}
		//出循环还需要加一个数字
		if (index_l == beginpro || index_ls == beginpro)		//生成左括号
		{
			if (index_l == index_ls)
			{
				pro += "(( ";
			}
			else
			{
				pro += '(';
			}
		}
		pro += pronum(r, mark);			//生成一个数字
		if (index_r == beginpro || index_rs == beginpro)		//生成右括号
		{
			if (index_r == index_rs)
			{
				pro += ")) ";
			}
			else
			{
				pro += ") ";
			}
		}
		else
		{
			pro += ' ';
		}
	}

	return pro;
}

生成的题目运算符,运算数,是否有括号全由随机数决定。

计算主要代码

void ChangeTosum2(string s, int& a, int& b)    //小数转化成整数
{

	int n1 = -1, n2 = -1, n3 = -1;
	string a1[4];
	int index_ = 0;
	for (int i = 0; i < s.length(); i++)
	{
		string a2;
		for (int j = i; j < s.length(); j++)
		{
			if (s[j] == '\'')
			{

				n1 = ChangeTosum1(a2);   //保存分数'前的数


				i = j;
				break;
			}
			else if (s[j] == '/')
			{
				n2 = ChangeTosum1(a2);			//保存分数的分子
				i = j;
				break;
			}
			else if (j == s.length() - 1)
			{
				a2 += s[j];
				n3 = ChangeTosum1(a2);			//保存分数的分母
				i = j;
				break;
			}
			a2 += s[j];
		}
		
	}
	if (n1 != -1)
	{
		n2 = n1 * n3 + n2;
		
	}
	
	a = n2;
	b = n3;

	return;
}

string ReaCount(string count,int upmul[],int mul[])
{
	stack<char> ms;
	string beh;
	int num = 0;
	for (int i = 0; i < count.length(); i++)			// 转成后缀表达式
	{
		if (count[i] <= '9' && count[i] >= '0')// 改存数字下标
		{
			beh += (num + 48);
			num++;

			for (int j = i+1; j < count.length(); j++)
			{
				if (count[j] >'9' || count[j] < '0')   //不是数
				{
					
					i = j - 1;
					break;
				}
				if (j == count.length() - 1)
				{
					i = j;
				}
			}
		}
		else if (count[i]=='(')
		{
			ms.push(count[i]);
		}
		else if (count[i] == ')')
		{
			while (ms.top() != '(')    //弹出直到左括号
			{
				beh += ms.top();
				ms.pop();
			}
			ms.pop();      //弹出左括号
		}
		else if (count[i] == '+' || count[i] == '-' || count[i] == '*' || count[i] == '/')
		{
			if (ms.empty())
			{
				ms.push(count[i]);
			}
			else if (count[i] == '+' || count[i] == '-')
			{
				while (!ms.empty()&&ms.top()!='(')
				{

					beh += ms.top();
					ms.pop();
				}
				ms.push(count[i]);
			}
			else            //'*'  '/'的情况
			{
				while (!ms.empty()&&ms.top()!='+'&&ms.top()!='-'&& ms.top() != '(')   
				{

					beh += ms.top();
					ms.pop();
				}
				ms.push(count[i]);

			}
		}
	}
	while (!ms.empty())		//栈可能非空,把剩下所有元素送给表达式
	{
		beh += ms.top();
		ms.pop();
	}

	stack<pair<int, int>> countnum;       //第一个数存数值 第二个数 若该数为小数 存分母 否则存0
	for (int i = 0; i < beh.length(); i++)     
	{
		if (beh[i] <= '9' && beh[i] >= '0')
		{
			int index = beh[i]-48;   //数的下标
			countnum.push({ upmul[index] , mul[index]});        //将数存进去
		}
		else
		{
			int b = countnum.top().first;   //第二个入栈
			int b2 = countnum.top().second;		//该数的分母
			countnum.pop();
			int a = countnum.top().first;
			int a2 = countnum.top().second;		//该数的分母
			countnum.pop();


			switch (beh[i])
			{
			case('+'):
			{	
				a = a * b2;			//互相乘分母
				b = b * a2;
				int c = a2 * b2;     //分母合为一起
				{
					countnum.push({ b + a ,c});
				}
				break;
			}
			case('-'):
			{
				a = a * b2;			//互相乘分母
				b = b * a2;
				if (a - b < 0)							//保证计算过程不出现负数
				{
					return "-1";
				}
				int c = a2 * b2;     //分母合为一起
				{
					countnum.push({ a - b ,c });
				}
				break;
			}
			case('*'):
			{
				int c = a2 * b2;     //分母合为一起
				countnum.push({ b * a ,c });
				break;
			}
			case('/'):				//需要将/外的数乘以分母
			{
				b = b * a2;
				a = a * b2;
				countnum.push({a,b});  
				break;
			}
			}
		}
	}
	string ans;
	if (countnum.top().second!=1)
	{
		if (countnum.top().first % countnum.top().second == 0)
		{
			ans = numtostring(countnum.top().first/ countnum.top().second);
		}
		else
		{
			int a = Gcd(countnum.top().first, countnum.top().second);
			ans = ChangeToString(countnum.top().first/a, countnum.top().second / a);          //小数转化为字符串
		}
		
	}
	else
	{
		ans = numtostring(countnum.top().first);       //一个整数转变为字符串
	}
	
	return ans;
}

string Count(string s)			//将表达式转变为全部为整数的运算   计算题目值
{
	string count;
	int mul[4];       //存分母
	int upmul[4];     //存数
	int index_mul = 0;		//分母个数
	int index_num = 0;		//存数的个数
	for(int i = 0; i < s.length(); i++)
	{
		if (s[i] == '(' || s[i] == ')' || s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/')
		{
			count += s[i];
		}
		else if (s[i] == ' ')  //跳过=号
		{
			continue;
		}
		else
		{
			bool flag = false;   //检查是否为小数
			string thenum;
			for (int j = i; j < s.length(); j++)
			{
				if (s[j] == ')')
				{
					i = j - 1;
					break;
				}
				if (s[j] == ' ')
				{
					i = j;
					break;
				}
				if (s[j] == '/')
				{
					flag = true;
				}
				thenum += s[j];
				
				
			}
			if (flag)					//该数为小数
			{
				int a, b;				//上 、下
				ChangeTosum2(thenum,a,b);			//小数转化为int

				upmul[index_num++] = a;        //整数加上

				mul[index_num-1] = b;			//存进该分母  用数的下标

				count += numtostring(a);       //一个整数转变为字符串 存进去
			}
			else
			{
				upmul[index_num++] = ChangeTosum1(thenum);			//整数转化为int
				mul[index_num - 1] = 1;			//分母默认为1
				count += thenum;				//存整数进去
			}
			

		}
	}
	return ReaCount(count, upmul,mul);




}
主要思路为先将题目的小数去除,记录其分母然后利用下标记录数转化成后缀表达式,这种操作可以使表达式存储的数可以发生更改,更加灵活。然后假设每一个整数的分母为0,再进行具体的+-*/,得到答案。再判断答案是否为小数,在转化成题目要求形式。

六、测试运行

功能一:生成题目与答案


功能二:批改答案对错

七、表格实际时间填写

八、项目小结

由于个人能力有限,程序未能完成题目要求的不能生成重复的题目,但由于该程序随机性太大,生成的题目几乎都不重复。该程序还有一定的bug,就是生成题目时有时候生成失败,由于时间有限,难于修改,生成题目的数字范围越大该bug的产生可能性比较小。生成该题目的括号时,由于括号的结合可能情况很多,而且若允许程序在随意位置生成括号,程序会可能生成无意义的括号,即多余的括号,本程序对括号的产生有一定的限制。

标签:count,题目,命令行,countnum,int,top,四则运算,ms,分母
From: https://www.cnblogs.com/galiji1157/p/18095127

相关文章

  • c语言编程题目:水仙花数
    题目:水仙花数是指一个N位正整数(N>=3),它的每位上的数字的N次幂之和等于它本身。例如:153=1^3+5^3+3^3。要求:计算所有N位水仙花数。给出一个正整数N(3<=N<=7),按递增顺序输出所有水仙花数,每个数字占一行。编程思路分析:输入一个正整数N。N为位数,N=3就表明是3位数。判断N位......
  • 每日面经分享(测试开发经典场景题目)
    1.面试测试场景题目,回答的测试点有哪些?a.功能测试点:确保所测试的功能按照设计要求正常工作。例如,对于电影票预订网站的座位选择功能,测试点可能包括选择连续座位、选择非连续座位、座位已售等情况。b.边界测试点:测试输入值的边界情况,以验证系统在极限条件下的表现。例如......
  • cmdline---C++命令行解析库
    cmdline项目托管地址:https://github.com/tanakh/cmdlinehttps://blog.51cto.com/u_15127663/4587654https://www.cnblogs.com/ljbguanli/p/7235424.html//includecmdline.h#inclue<iostream>#include"cmdline.h"intmain(intargc,char*argv[]){......
  • 简单mips题目尝试
    0x01前言mips是另一种不同的架构何指令集,推荐使用ghidra和ida插件进行反汇编,其中的知识我就不多赘述,因为我也一知半解Orz0x02简单的ctf题目尝试[UTCTF2020]babymips首先利用ghidra反汇编一下程序看看,按g可以跳转main函数看看 发现具体逻辑将一段东西赋值给austak_68,然......
  • 华为升级FIT AP示例(通过AC的命令行)
    升级FITAP示例(通过AC的命令行)前提条件从官网下载升级目标版本对应的系统软件包,保存在PC本地。如果下载的文件是压缩文件,则需要解压缩出系统软件包。AP已在WAC上线。背景信息升级的过程是先将系统软件包传到设备上,再将其设置为下次启动的软件包,然后重启设备。本文以......
  • Node.js新手必备:超实用命令行入门教程
    1.安装Node.js和npm首先,我们需要下载并安装Node.js,它自带了npm(NodePackageManager)。安装完成后,在命令行输入:node-vnpm-v这两个命令分别显示已安装的Node.js和npm版本,确认安装成功。2.初始化新项目npminit按照提示填写相关信息后,npm会帮你生成一个package.json......
  • (小实验)理解编译原理:一个四则运算的解释器
    在前面的课程中,我在JavaScript和CSS的部分,多次提到了编译原理相关的知识。这一部分的知识,如果我们从编译原理“龙书”等正规的资料中学习,就会耗费掉不少的时间,所以我在这里设计了一个小实验,帮助你快速理解编译原理相关的知识。今天的内容比较特殊,我们来做一段详细的代码实验,......
  • Java语言程序设计实验题目:编写Java程序统计一篇英文文档中各单词出现的次数,并按单词出
    题目描述编写Java程序统计一篇英文文档中各单词出现的次数,并按单词出现的频率由高到低进行输出。例如:文档“HellowordHello”的统计结果为: Hello:2次 word:1次思路分析1.处理文档:先用nextLine()将文段输入,存储在字符串file,再调用split()方法将字符串分割成一个......
  • 剑指Offer题目笔记15(二叉搜索树)
    面试题52:问题:​给定一棵二叉搜索树,调整节点的指针使每个节点都没有左子节点。解决方案:​使用中序遍历,因为二叉搜索树是左节点的值小于等于根节点,根节点小于等于右节点的值,所以要是向使用每个节点都没有左子树,那么就需要先遍历左节点。源代码:/***Definitionfor......
  • 实现一个自动生成小学四则运算题目的命令行程序
    一.项目作者姓名:陈炜烽麦润泽学号:31220047763122004785Github项目地址:https://github.com/iFortheFuture/teamwork二.PSP表格##PersonalSoftwareProcessStagesPersonalSoftwareProcessStages预估时间(分钟)实际时间(分钟)Planning3030Estimate45......