小学算术加减法练习生成器 v2.0(代码附详细注释)

/*加减法算式生成器 v2.0
**By obertys 2020/08/06
**使用说明:
**	定义ARITHMETIC_COUNT宏为需要打印的算式数量
**	定义NUMERAL_COUNT常量作为算式操作数个数
**	定义MIN_NUM及MAX_NUM常量作为生成算式操作数及结果值的取值范围(整数区间[MIN_NUM,MAX_NUM])
**注意事项:
**	允许MAX_NUM值及MIN_NUM值为负数,但必须满足MIN_NUM<MAX_NUM
**	若ARITHMETIC_COUNT值过大且(MAX_NUM-MIN_NUM)值过小且NUMERAL_COUNT值过小,则可能造成死循环
**	在生产环境中不建议NUMERAL_COUNT值大于5;在测试环境中不建议NUMERAL_COUNT值过大
**编译支持:
**	C++11编译器
*/

#include<set>
#include<array>
#include<tuple>
#include<ctime>
#include<random>
#include<iostream>
#include<functional>

using namespace std;

#define ARITHMETIC_COUNT 100	//生成的算式个数
constexpr unsigned short NUMERAL_COUNT=4;	//每条算式的数字个数
constexpr short MIN_NUM=10;	//算式允许的最小值
constexpr short MAX_NUM=99;	//算式允许的最大值
enum class Op:char {plus='+',minus='-'};	//定义加减法操作

static_assert(NUMERAL_COUNT>=2&&NUMERAL_COUNT<=10000,"非法的算式操作数个数");	//算式的数字个数必须在整数区间[2,10000]
static_assert(MAX_NUM>MIN_NUM,"必须满足MAX_NUM>MIN_NUM");	//否则造成死循环

int evaluation(const array<short,NUMERAL_COUNT>& numeral,const array<Op,NUMERAL_COUNT-1>& op)	//返回"操作数数组+操作符数组"所表示的算式的结果值
{
	int res=numeral.front();	//取第一个操作数为计算结果的初始值
	for(unsigned short i=0; i<NUMERAL_COUNT-1; ++i)
		if(op[i]==Op::plus)
			res+=numeral[i+1];	//结果加上下一个操作数
		else if(op[i]==Op::minus)
			res-=numeral[i+1];	//结果减去下一个操作数
		else
		{
			cerr<<"错误的枚举值:"<<static_cast<int>(op[i])<<endl;
			throw -1;
		}
	return res;
}

int main(void)
{
	/*初始化*/
	using Arithmetic=tuple<array<short,NUMERAL_COUNT>,array<Op,NUMERAL_COUNT-1>,short>;	//定义Arithmetic类型为"操作数数组+操作符数组+结果"
	set<Arithmetic> AriSet;	//存贮生成算式的集合
	auto rand=bind(uniform_int_distribution<short>(MIN_NUM,MAX_NUM),default_random_engine(time(nullptr)));	//定义伪随机数发生器(绑定以[MIN_NUM,MAX_NUM]为区间的标准分布+以当前时刻为种子值的默认引擎)
	/*生成算式*/
	while(AriSet.size()<ARITHMETIC_COUNT)	//当集合中算式数量达到ARITHMETIC_COUNT时退出循环
	{
		array<short,NUMERAL_COUNT> numeralArray;
		for(auto& x:numeralArray)	//随机生成NUMERAL_COUNT个数值,作为算式操作数
			x=rand();
		array<Op,NUMERAL_COUNT-1> opArray;
		for(auto& x:opArray)	//随机确定(NUMERAL_COUNT-1)个算式操作
			x=rand()%2==0?Op::plus:Op::minus;
		int result=evaluation(numeralArray,opArray);	//算式求值
		if(result>MAX_NUM||result<MIN_NUM)	//结果值必须在整数区间[MIN_NUM,MAX_NUM]中
			continue;
		AriSet.insert(Arithmetic(move(numeralArray),move(opArray),result));	//存贮当前算式及算式结果,若已有重复则忽略
	}
	/*打印*/
	cout<<"算式:\n";
	for(const auto& x:AriSet)	//遍历集合,打印生成的算式
	{
		for(unsigned short i=0; i<NUMERAL_COUNT-1; ++i)
			cout<<get<0>(x)[i]<<' '<<static_cast<char>(get<1>(x)[i])<<' ';
		cout<<get<0>(x).back()<<" =\n";
	}
	cout<<"\n对应的答案:\n";
	for(const auto& x:AriSet)
		cout<<get<2>(x)<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值