小学算术系统

  1. 小学算术能力训练系统
    设计并实现一个进行小学程度的四则混合运算的算术能力训练系统,能够生成运
    算对象为 100 以内的四则混合运算题,要进行合法性检查,即保证除数不为 0。用户
    在输入答案后,可显示答案正确或错误。该系统应实现以下基本功能:
    (1)随机出题,并判定答案是否正确。
    (2)设置两种可选的答题模式:练习模式和考试模式。
    (3)练习模式不断的循环出题,直到用户要求终止。并且每答完一题,还应显示
    当前的正确率(已答对题数/已答题数)。
    (4)考试模式可由用户指定题目总数量(如 10、50、100),在答完全部题目后
    显示总题数、答对题数、和正确率。
    (5)每一次进入考试模式的考试结果(总题数、答对题数、正确率)都应写入文
    件保存,用户可随时查看过去的考试结果。
    (6)合理组织排列各项功能,界面可使用键盘操作。
    运行结果(输入流已经被我关了)
    在这里插入图片描述

出题过程
先看流程图吧
在这里插入图片描述
就拿一个数组装题目

do
	{
		t = 0;
	memset(m, 0, sizeof(m));
	set_title_1st(m);
	mans=getans(m);
	while (t < 2||getrand_mod_unpasstime(2)||t>10 )//保底也生成两个符号的算式,当然生成更多就听天由命了
	{
		set_title_next(m, mans);
		mans=getans(m);
		t++;
	}
	if (mans <= 10 || mans >= 90&&mans!=1&&mans!=100)
		time++;
	else time = 0;
	} while (mans>=MOD||mans<=1||mans!=(int)mans||time ==1);//这里一堆条件全是因为我菜,生成ans=1和100的概率加起来有25了,生成ans《10和ans》90的概念加起来有50

题目生成

void set_title_1st(char* ti)//生成第一个式子
{
	int a, b, c;
	a = getrand_mod(MOD);
	b = getrand_mod(MOD);
	while (a < b)
	{
		a = a + 100 - b;
	}
	c = getrand_mod_unpasstime(6);
	xiuzheng(&a,& b, &c);
	int len = strlen(ti);
		len = fillint(a, ti, len);
		*(ti + len) = c + '*'; len++;
		len = fillint(b, ti, len);
}
void set_title_next(char* ti,double ans)//生成接下来的题
{
	int b, c;
	int a = (int)ans;
	c = getrand_mod(6);
	b = getrand_mod(MOD);
	xiuzheng(&a,&b,&c);
	int len = strlen(ti);
	*(ti + len++) = c + '*';
	len = fillint(b, ti, len);
}

括号生成
直接把一个数拆成两个数就行了

int fillint(int  a, char* ti, int len)
{
		if (a > 27 && getrand_mod_unpasstime(4)==1)
		{
				int b = getrand_mod_unpasstime(a);
				*(ti + len) = '('; len++;
				sprintf(ti + len, "%d", b);
				len = strlen(ti);
				*(ti + len) = '+'; len++;
				sprintf(ti + len, "%d", a - b);
				len = strlen(ti);
				*(ti + len) = ')'; len++;
				return len;
		}//在往题目字符串组中存a的时候,把a拆成两个数相加,并且带上括号
		else if (a > 7&&a<80&& getrand_mod_unpasstime(4)==1)
		{
			int b = MOD;
			while (a + b >= MOD)
			{
				b=getrand_mod_unpasstime(a);
			}
				*(ti + len) = '('; len++;
				sprintf(ti + len, "%d", a+b);
				len = strlen(ti);
				*(ti + len) = '-'; len++;
				sprintf(ti + len, "%d", b);
				len = strlen(ti);
				*(ti + len) = ')'; len++;
				return len;
		}//改成相减,带括号
		else
		{
			sprintf(ti + len, "%d", a);
			return strlen(ti);
		} //正常生成
}

怎么从一个字符串式子中获得答案呢?
用栈就行了

double  getans(char* t)//用的是栈的原理
{
	double ans = 0;
	double temp[1000];
	memset(temp, 0, sizeof(temp));
	int len = strlen(t);
	int top = 0;
	int i = 0;
	if (*(t + i) == '(')
	{
		i++;
		temp[++top] = getemp(t, &i, len);
		if ((*(t + i) - '*') == 1)
		{
			i++;
			temp[top] += getemp(t, &i, len);
		}
		else
		{
			i++;
			temp[top] -= getemp(t, &i, len);
		}
		i++;
	}
	else
	{
		temp[top] = getemp(t, &i, len);
	}
	for (; i < len; )
	{
		{
			if (*(t + i) - '*' == 1)
			{
				i++;
				if (*(t + i) == '(')
				{
					i++;
					temp[++top] = getemp(t, &i, len);
					if ((*(t + i) - '*') == 1)
					{
						i++;
						temp[top] += getemp(t, &i, len);
					}
					else
					{
						i++;
						temp[top] -= getemp(t, &i, len);
					}
					i++;
				}
				else
				{
					temp[++top] = getemp(t, &i, len);
				}
			}
			if (*(t + i) - '*' == 3)
			{
				i++;
				if (*(t + i) == '(')
				{
					i++;
					temp[++top] -= getemp(t, &i, len);
					if ((*(t + i) - '*') == 1)
					{
						i++;
						temp[top] -= getemp(t, &i, len);
					}
					else
					{
						i++;
						temp[top] += getemp(t, &i, len);
					}
					i++;
				}
				else
				{
					temp[++top] -= getemp(t, &i, len);
				}
			}
			if (*(t + i) =='*' )
			{
				i++;
				if (*(t + i) == '(')
				{
					double tt=0;
					i++;
					tt = getemp(t, &i, len);
					if ((*(t + i) - '*') == 1)
					{
						i++;
						tt += getemp(t,& i, len);
					}
					else
					{
						i++;
						tt -= getemp(t, &i, len);
					}
					i++;
					temp[top] *= tt;
				}
				else
				{
					temp[top] *= getemp(t, &i, len);
				}
			}
			if (*(t + i) - '*' == 5)
			{
				i++;
				if (*(t + i) == '(')
				{
					double tt = 0;
					i++;
					tt = getemp(t, &i, len);
					if ((*(t + i) - '*') == 1)
					{
						i++;
						tt += getemp(t,& i, len);
					}
					else
					{
						i++;
						tt -= getemp(t, &i, len);
					}
					i++;
					temp[top] /= tt;
				}
				else
				{
					temp[top] /= getemp(t, &i, len);
				}
			}
		}
	}
	for (int i = 0; i <=top; i++)
	{
		ans += temp[i];
	}
	return ans;
}

源代码

/*2. 小学算术能力训练系统
设计并实现一个进行小学程度的四则混合运算的算术能力训练系统,能够生成运
算对象为 100 以内的四则混合运算题,要进行合法性检查,即保证除数不为 0。用户
在输入答案后,可显示答案正确或错误。该系统应实现以下基本功能:
(1)随机出题,并判定答案是否正确。
(2)设置两种可选的答题模式:练习模式和考试模式。
(3)练习模式不断的循环出题,直到用户要求终止。并且每答完一题,还应显示
当前的正确率(已答对题数/已答题数)。
(4)考试模式可由用户指定题目总数量(如 10、50、100),在答完全部题目后
显示总题数、答对题数、和正确率。
(5)每一次进入考试模式的考试结果(总题数、答对题数、正确率)都应写入文
件保存,用户可随时查看过去的考试结果。
(6)合理组织排列各项功能,界面可使用键盘操作。*/
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#include<windows.h>
#define MOD 100
int chumod = -1;
int zhuobi = 0;
double mans;
char hihi[20] = "liuquanzhuishuai";//作弊码:刘权最帅
int issusu(int n)//定义函数 判断一个数是否为素数
{
	if (n == 0 || n == 1) return 1;
	int i = 0;//定义参数 控制循环
	for (i = 2; i <=n/2; i++)
	{
		if (n % i == 0)//判断这个数与2至本身相模 是否有为零的数
			return 0;//有模为零的数 直接返回-1
	}
	return 1;//执行完循环还没有模为零的数 则是个素数 返回0
}
int ma(int a, int b)
{
	return a > b ? a : b;
}
int mi(int a, int b)
{
	return a < b ? a : b;
}
int  getrand_mod(int mod)
{
	int b = 0;
	srand((unsigned)clock());
	b = rand() * 91;//随便乘一个数
	b %= mod;
	Sleep(3);//随便经过一段时间
	return b;
}//耗时随机生成器
int   getrand_mod_unpasstime(int mod)
{
	srand((unsigned)clock());
	int a = rand();
	a %= mod;
	return a;
}//无耗时随机生成器
int setchu(int a)//随机生成a的因数作为除数
{
	int temp[100] = { 0 }; int j = 0;
	int i = 2;
	while (j == 0)
	{
		i = 2;
		for (; i <a; i++)
		{
			if (a % i == 0)
			{
				temp[j] = i; 
				j++;
			}
		}
	}
	int time = 0;
	do {
		i = getrand_mod_unpasstime(j);//给i付个在0~j-1的随机数
		time++;
	} while (time < 2 && (temp[i] == 2 || temp[i] == a / 2));//减少除数=2,或=a/2的概率
	return temp[i];
}
void xiuzheng(int *a, int * b, int *c)//只是堆abc的合法性进行修正而已
{
	if (*(c) == 2) { if (getrand_mod_unpasstime(2)) *(c) = 3; else  *(c) = 0; }
	if (*(c) == 4) { if (getrand_mod_unpasstime(2)) *(c) = 1; else *(c) = 5; }
	if (issusu( *(a) ) )
	{
		if (*(c) == 5)
		{
			*(c) = getrand_mod_unpasstime(4);
			if (*(c) == 2)  *(c) = 1;
		}
	}
	if (*(c) == 5 && *(b) == 0)
	{
		while (*(b) == 0)
		{
			*(b) = getrand_mod(MOD);
		}//若除 b!=0
	}
	if (*(c) == 0)//*c!=*(c)
	{
		if (*(a) > MOD / 2)
			*(c) =3;
		else
		{
			while (*(a) * *(b) >= MOD)
			{
				*(b)/=2;
				if (*(b) == 0)
					*(b) = getrand_mod(MOD);//  保证乘数不为0或1,不让也太简单了吧 ;
			}//  若乘大于100,转化一下
		}
	}
	if (*(c) == 1)
	{
		if ((*(b)+*(a)) > MOD)
		{
			*(b) = *(b) / 2;
		}
	}
	if (*(c) == 3)
	{
		if (*(a) < *(b))
		{
			if (*(a)<=8)
			{
				*(b) = getrand_mod_unpasstime(90);
				*(c) = 1;
			}
			else 
			{
				while (*(b) >= *(a))
				{
					*(b) /= 2;
				}
			}
		}
		//防止ans小于0
	}
	if (*(c) == 5)
	{
		if (chumod == 1);
		else
		{
			*(b) = setchu(*(a));
		}
	}
}//对于c的修正,由于在ASCLL码中加减乘除不是连续的,将非加减乘除的转成加和减,减少点难度;
int fillint(int  a, char* ti, int len)
{
		if (a > 27 && getrand_mod_unpasstime(4)==1)
		{
				int b = getrand_mod_unpasstime(a);
				*(ti + len) = '('; len++;
				sprintf(ti + len, "%d", b);
				len = strlen(ti);
				*(ti + len) = '+'; len++;
				sprintf(ti + len, "%d", a - b);
				len = strlen(ti);
				*(ti + len) = ')'; len++;
				return len;
		}//在往题目字符串组中存a的时候,把a拆成两个数相加,并且带上括号
		else if (a > 7&&a<80&& getrand_mod_unpasstime(4)==1)
		{
			int b = MOD;
			while (a + b >= MOD)
			{
				b=getrand_mod_unpasstime(a);
			}
				*(ti + len) = '('; len++;
				sprintf(ti + len, "%d", a+b);
				len = strlen(ti);
				*(ti + len) = '-'; len++;
				sprintf(ti + len, "%d", b);
				len = strlen(ti);
				*(ti + len) = ')'; len++;
				return len;
		}//改成相减,带括号
		else
		{
			sprintf(ti + len, "%d", a);
			return strlen(ti);
		} //正常生成
}
//存下单个数据
double getemp(char* te, int *i,int len)//获得数字
{
	double temp = 0;
	while (isdigit(te [*(i)])&&*i<len) 
	{
		temp *= 10;
		temp += *(te + *(i)) - '0';
		( *i)++;
	}
	return temp;
}
//从字符组中得到数据
void set_title_1st(char* ti)//生成第一题
{
	int a, b, c;
	a = getrand_mod(MOD);
	b = getrand_mod(MOD);
	while (a < b)
	{
		a = a + 100 - b;
	}
	c = getrand_mod_unpasstime(6);
	xiuzheng(&a,& b, &c);
	int len = strlen(ti);
		len = fillint(a, ti, len);
		*(ti + len) = c + '*'; len++;
		len = fillint(b, ti, len);
}
//向题中存a数据,生成题目
void set_title_next(char* ti,double ans)//生成接下来的题
{
	int b, c;
	int a = (int)ans;
	c = getrand_mod(6);
	b = getrand_mod(MOD);
	xiuzheng(&a,&b,&c);
	int len = strlen(ti);
	*(ti + len++) = c + '*';
	len = fillint(b, ti, len);
}
double  getans(char* t)//用的是栈的原理
{
	double ans = 0;
	double temp[1000];
	memset(temp, 0, sizeof(temp));
	int len = strlen(t);
	int top = 0;
	int i = 0;
	if (*(t + i) == '(')
	{
		i++;
		temp[++top] = getemp(t, &i, len);
		if ((*(t + i) - '*') == 1)
		{
			i++;
			temp[top] += getemp(t, &i, len);
		}
		else
		{
			i++;
			temp[top] -= getemp(t, &i, len);
		}
		i++;
	}
	else
	{
		temp[top] = getemp(t, &i, len);
	}
	for (; i < len; )
	{
		{
			if (*(t + i) - '*' == 1)
			{
				i++;
				if (*(t + i) == '(')
				{
					i++;
					temp[++top] = getemp(t, &i, len);
					if ((*(t + i) - '*') == 1)
					{
						i++;
						temp[top] += getemp(t, &i, len);
					}
					else
					{
						i++;
						temp[top] -= getemp(t, &i, len);
					}
					i++;
				}
				else
				{
					temp[++top] = getemp(t, &i, len);
				}
			}
			if (*(t + i) - '*' == 3)
			{
				i++;
				if (*(t + i) == '(')
				{
					i++;
					temp[++top] -= getemp(t, &i, len);
					if ((*(t + i) - '*') == 1)
					{
						i++;
						temp[top] -= getemp(t, &i, len);
					}
					else
					{
						i++;
						temp[top] += getemp(t, &i, len);
					}
					i++;
				}
				else
				{
					temp[++top] -= getemp(t, &i, len);
				}
			}
			if (*(t + i) =='*' )
			{
				i++;
				if (*(t + i) == '(')
				{
					double tt=0;
					i++;
					tt = getemp(t, &i, len);
					if ((*(t + i) - '*') == 1)
					{
						i++;
						tt += getemp(t,& i, len);
					}
					else
					{
						i++;
						tt -= getemp(t, &i, len);
					}
					i++;
					temp[top] *= tt;
				}
				else
				{
					temp[top] *= getemp(t, &i, len);
				}
			}
			if (*(t + i) - '*' == 5)
			{
				i++;
				if (*(t + i) == '(')
				{
					double tt = 0;
					i++;
					tt = getemp(t, &i, len);
					if ((*(t + i) - '*') == 1)
					{
						i++;
						tt += getemp(t,& i, len);
					}
					else
					{
						i++;
						tt -= getemp(t, &i, len);
					}
					i++;
					temp[top] /= tt;
				}
				else
				{
					temp[top] /= getemp(t, &i, len);
				}
			}
		}
	}
	for (int i = 0; i <=top; i++)
	{
		ans += temp[i];
	}
	return ans;
}
//得到答案
int core()//核心代码
{
	char m[10000];
	int time = 0;
	int t = 0;
	do
	{
		t = 0;
	memset(m, 0, sizeof(m));
	set_title_1st(m);
	mans=getans(m);
	while (t < 2||getrand_mod_unpasstime(2)||t>10 )//保底也生成两个符号的算式,当然生成更多就听天由命了
	{
		set_title_next(m, mans);
		mans=getans(m);
		t++;
	}
	if (mans <= 10 || mans >= 90&&mans!=1&&mans!=100)
		time++;
	else time = 0;
	} while (mans>=MOD||mans<=1||mans!=(int)mans||time ==1);//这里一堆条件全是因为我菜,生成ans=1和100的概率加起来有25了,生成ans《10和ans》90的概念加起来有50
	char cr='\n';
	puts(m);
	double ans = 1;
	if (zhuobi == 1)
	printf("ans:%lf\n", mans);
	rewind(stdin);
	t = 1;
//	t = scanf("%lf%c", &ans, &cr);
	if (t == 0) { return 2; }
	else {
		if (cr != '\n') { return 2; }
		if (fabs(ans - mans) <= 0.001)//浮点误差
		{
			return 1;
		}
		else { return 0; }
	}
}
void ininin(double a, double b, double c)
{
	FILE* p;
	p = fopen("t.txt", "ab+");
	//  fseek(p,-1,2);
	fprintf(p, "%lf ", a);
	fprintf(p, "%lf ", b);
	fprintf(p, "%lf ", c);
	fclose(p);
}//存数据
void  practice()//练习模式
{
	int t = 0;
	double r = 0, w = 0;
	printf("练习模式启动,输入非数字结束\n");
	while (1)
	{
		t = core();
		if (t == 2) { printf("练习模式结束\n"); break; }
		if (t == 1) { printf("回答正确,正在生成下一题\n"); r++; }
		if (t == 0) { printf("回答错误,正确答案:%.0lf,正在生成下一题\n",mans); w++; }
		printf("正确率:%2.1f%%\n", (r / (w + r)) * 100);
	}
}
void text()
{
	int sum;
	printf("考试模式启动,请输入考试的题目数:");
	scanf("%d", &sum);
	int bn = 0;
	double r = 0, w = 0;
	int t;
	while (bn < sum)
	{
		printf("第%d题:\n", bn + 1);
		t = core();
		if (t == 2) { printf("请不要输入无关的字符\n"); w++; }
		if (t == 1) r++;
		if (t == 0) w++;
		bn++;
	}
	printf("考试结束,本次考试总题数:%.0f,答对题数:%.0f,正确率:%2.1f%%\n", w + r, r, (r / (w + r)) * 100);
	ininin(w + r, r, (r / (w + r)) * 100);
}//考试模式
void vi()
{
	FILE* p;
	if (!(p = fopen("t.txt", "r")))
	{
		printf("您没进行过考试\n");
	}
	int n = 1;
	double a, b, c;
	while (fscanf(p, "%lf %lf %lf\n", &a, &b, &c) != EOF)
	{
		printf("第%d次考试: 总题数:%.0f,答对题数:%.0f,正确率:%2.1f%%\n", n, a, b, c);
		n++;
	}
	fclose(p);
}//查看考试数据
char al[5]= "alll";
void de()
{
	char in[30];
	printf("您确定要删除考试数据吗?确定输入1,否则输入0\n");
	int t;
	scanf("%d", &t);
	vi();
	printf("请输入要删除第几次考试数据,如果全要删除,输入'all'\n");
	scanf("%s", in);
	if (t)
	{
		if (strcmp(in,al)==0)
		{
			remove("t.txt");
			printf("考试数据已经删除\n");
		}
		else if(isdigit(in[0]))
		{
			int tt;
			tt = atoi(in);
			FILE* p;
			FILE* q;
			double te1, te2, te3;
			p = fopen("t.txt", "r");
			q = fopen("e.txt", "w");
			int i = 1;
			while (~fscanf(p, "%lf %lf %lf", &te1, &te2, &te3))
			{
				if (i != tt)
					fprintf(q, "%lf %lf %lf ", te1, te2, te3);
				i++;
			}
			fclose(p);
			fclose(q);
			remove("t.txt");
			rename("e.txt", "t.txt");
			printf("考试数据已经删除\n");
		}
		else
		{
			printf("您未删除任何考试数据,删除模式结束\n ");
		}
	}
}
int main()
{
	char mode[100];
	while (1)
	{
		printf("---------------------------------------------------------\n输入'p'开启练习模式\n输入't'开启考试模式\n输入'v'查看历史考试情况\n输入'd'删除考试数据\n");
		 printf("保证结果是整数\n");
		printf("输入'e'退出程序\n---------------------------------------------------------\n");
		rewind(stdin);
		scanf("%s", mode);
		if (mode[0] == 'p')
		{
			practice();
		}
		else if (strcmp(hihi, mode) == 0)
		{
			if (zhuobi == 0)
			{
				printf("作弊系统激活\n"); zhuobi = 1;
			}
			else
			{
				printf("作弊系统关闭\n"); zhuobi = 0;
			}
		}
		else if (mode[0] == 'e')
			break;
		else if (mode[0] == 't')
		{
			text();
		}
		else if (mode[0] == 'v')
		{
			vi();
		}
		else if (mode[0] == 'd')
		{
			de();
		}
		else
		{
			printf("无效输入\n");
		}
	}
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值