c++求助:这题应该鸡兔同笼类型题怎么做做?


去年做的课程设计,命令行,没有可视化。
题目这个问题是建立一个小学生测验答题系统,对于该系统有如下几个要求:1.能够输入数据,做 n 个试题;2.系统可以随机产生需要做的题目;3.在运行程序后显示“欢迎”信息,以及提示输入学号,并等待输入学号的信息;4.在用户选择一共做几道题后,随机抽取题目让用户回答,回答过程中系统会判断用户的答案是否正确;5.在全部题目回答完毕后,系统会为用户显示答题分数,并将分数存入相应文件,且可与之前的历史分数进行比较,再进行评价;6.在需要退出时可以退出程序。
#include <iostream>
#include <cstring>
#include <stdlib.h>//调用其中随机函数
#include <time.h>
#include <stdio.h>
#include <fstream>
using namespace std;
#pragma warning( disable : 4996)
int N = 100; //定义全局变量,表示试题库试题数量
//试题类型
class Shiti
{
public:
char a[100];//定义一个数组
int result;//记录每一道题的结果
};
//数字栈类(用于存数字栈的指针)
class Num
{
public:
int *base, *top;//栈顶和栈底指针
int size;//栈大小
};
//运算符栈类(存运算符栈的指针)
class Oper
{
public:
char *base, *top;//栈顶栈底
int size;//栈大小
};
//构造函数(数字)
int NumInitStack(Num *S1)
{
S1->base = new int(100);
if (!S1->base)//申请内存失败情况
{
cout << "申请内存失败!" << endl;
return 0;
}
S1->top = S1->base;//栈顶栈底相同
S1->size = 100;//大小为100
return 1;
}
int OperInitStack(Oper *S2) //构造运算符栈(跟上面相同)
{
S2->base = new char[100];
if (!S2->base)
{
cout << "申请内存失败!" << endl;
return 0;
}
S2->top = S2->base;
S2->size = 100;
return 1;
}
//得到数字栈栈顶元素
int NumGetTop(Num *S1)
{
int e1;
if ((*S1).top == (*S1).base)
return 0;
e1 = *((*S1).top - 1);
return e1;
}
//得到运算符栈栈顶元素
char OperGetTop(Oper *S2)
{
char e2;
if ((*S2).top == (*S2).base)
return 0;
e2 = *((*S2).top - 1);
return e2;
}
//数字和运算符压栈
void NumPush(Num *S1, int e1)
{
*(*S1).top++ = e1;
}
void OperPush(Oper *S2, char e2)
{
*(*S2).top++ = e2;
}
int NumPop(Num *S1) //数字栈弹栈
{
int e1;
//栈为空的情况
if ((*S1).top == (*S1).base)
return 0;
e1 = *--(*S1).top;
return e1;
}
char OperPop(Oper *S2) //运算符栈弹栈
{
char e2;
//栈为空的情况
if ((*S2).top == (*S2).base)
return 0;
e2 = *--(*S2).top;
return e2;
}
char Precede(char a, char b) //判断运算符优先级
{
int i, j;
char Table[8][8] = { {' ','+','-','*','/','(',')','='},
{'+','>','>','<','<','<','>','>'},
{'-','>','>','<','<','<','>','>'},
{'*','>','>','>','>','<','>','>'},
{'/','>','>','>','>','<','>','>'},
{'(','<','<','<','<','<','=',' '},
{')','>','>','>','>',' ','>','>'},
{'=','<','<','<','<','<',' ','='} }; //优先级表格
for (i = 0; i < 8; i++)
if (Table[0][i] == a) //纵坐标寻找
break;
for (j = 0; j < 8; j++) //横坐标寻找
if (Table[j][0] == b)
break;
return Table[j][i];
}
//计算二元表达式的值
int Operate(int a, char theta, int b)
{
int c;
if (theta == '+')
c = a + b;
else if (theta == '-')
c = a - b;
else if (theta == '*')
c = a * b;
else
c = a / b;
return c;
}
//判断输入的字符ch是否为运算符
int IsOper(char ch)
{
char ptr[7] = { '+','-','*','/','(',')','=' };
int i;
for (i = 0; i < 7; i++)
{
if (ch == ptr[i])
return 1;
}
return 0;
}
//计算表达式的结果
int Result(char a[], Num *num, Oper *oper)
{
char theta;
int b, d, k = 0, i = 0, j = 0, num2 = 0;
NumInitStack(num);
//构造数字栈
OperInitStack(oper);
//构造运算符栈
OperPush(oper, '=');
//将“=”压到栈底(作为一个计算完毕的条件)
while (a[i] != '='
OperGetTop(oper) != '=')
{
//对表达式a进行计算
if (a[i] >= '0'&&a[i] <= '9')
{
//字符是数字
k++;
if (k <= j)
{
num2 = a[i] - 48;
i++;
}
if (k > j)
{
num2 = num2 * 10 + (a[i] - 48);
k = j = 0;
i++;
}
if (!IsOper(a[i]))
k++;
if (k == j)
//如果k等于j,说明下一个字符是运算符,即数字字符结束,压进数字栈
NumPush(num, num2);
}
else if (IsOper(a[i]))
{
//字符是运算符
switch (Precede(a[i], OperGetTop(oper)))
//←获取该运算符和栈顶运算符优先级
{
//该运算符和栈顶运算符进行优先级比较并做相关处理
case '<':
OperPush(oper, a[i++]);
if (a[i] != '('&&a[i] != ')')
j++;
break;
case '=':
OperPop(oper);
i++;
break;
case '>':
theta = OperPop(oper);
//运算符栈弹栈
d = NumPop(num);
//数字栈弹栈
b = NumPop(num);
NumPush(num, Operate(b, theta, d));
//计算结果并压栈
break;
}
}
}
return (NumGetTop(num));
//返回最终计算结果
}
char getOp(bool innerIsZero)
{
char ops[] = { '+','-','*','/' };
return innerIsZero ? ops[rand() % 3] : ops[rand() % 4];//判定括号内数字是否为0,为零则左括号前符号不能为除号
}
char getOd(bool preIsDiv)
{
char ods[] = { '1','2','3','4','5','6','7','8','9','0' };
return preIsDiv ? ods[rand() % 8] : ods[rand() % 9];
}
int FunOpes(string c)
{
int a, b;
char op;
char str[3];
c.copy(str, 3, 0);
a = str[0] - 48;
b = str[2] - 48;
op = str[1];
if (op == '+')return a + b;
if (op == '-')return a - b;
if (op == '*')return a * b;
if (op == '/')return a / b;
}
//产生试题库
void Build()
{
string b(9, ' ');//随机产生表达式长度最大为9
ofstream out1("d:\\shitikudifficult.txt");
if (!out1.is_open())cout << "难易程度为困难的试题库打开失败";
srand((unsigned)time(NULL));
for (int i = 0; i < N; i++) {
int left = 2;//随机产生左括号位置,最大下标4
int right = left + 4;
b[left] = '(';
b[right] = ')';
b[(left + right) / 2] = getOp(false);
b[left + 1] = getOd(true);
b[right - 1] = getOd(true);
if ((b[left + 1] - 48) % (b[right - 1] - 48) != 0 && (b[(left + right) / 2] == '/')) { i--; continue; }
string inner = b.substr(3, 3);//子串,括号内容
bool innerIsZero = FunOpes(inner) == 0 ? true : false;//FunOpes计算string表示的式子,返回计算结果
b[left - 1] = getOp(innerIsZero);
b[0] = getOd(false);
if (b[left - 1] == '/' && ((b[0] - 48) % FunOpes(inner) != 0)) { i--; continue; }
b[7] = getOp(innerIsZero);
bool preIsDiv = b[7] == '/' ? true : false;
b[8] = getOd(true);
if (b[7] == '/' && (FunOpes(inner) % (b[8] - 48) != 0)) { i--; continue; }
out1 << b << "=" << "\n";
}
out1.close();
return;
}
//随机选取n个题目,将题号保存在数组a中
void Select(int n, int a[])
{
srand((int)time(0));
int i, j, t;
a[0] = rand() % N;
//产生0-N之间的随机数并记录
for (i = 1; i < n; i++)
{
t = rand() % N;
for (j = 0; j < i; j++)
{
if (a[j] == t)
break;
}
if (j == i)
a[i] = t;
else
i--;
}
}
//求平均成绩
void Avescore()
{
FILE *fp1, *fp2;
int sum = 0, i = 0, s, a;
if (!(fp1 = fopen("d:\\score.txt", "r")))
{
cout << "无法打开成绩信息文件!";
exit(-1);
}
//读出所有的历史成绩并求和
while (!feof(fp1))
{
fscanf(fp1, "%d", &s);
sum += s;
i++;
//记录成绩个数
}
fclose(fp1);
a = sum / i;
if (!(fp2 = fopen("d:\\average.txt", "w")))
{
cout << "无法创建或者无法打开平均成绩文件!" << endl;
exit(-1);
}
fprintf(fp2, "%d", a);
//将平均值写入文件中
fclose(fp2);
}
void DoExercise(Shiti a[])
//做题
{
system("cls");
cout << "\t\t******好好学习 天天向上******\n\n";
int n, i, r, k = 0, score, ave;
FILE *fp, *fp1;
cout << "请输入要做几道题:";
cin >> n;
int t[100];
Select(n, t);
//调用Xuanti函数从试题库中随机抽取n道题目
for (i = 0; i < n; i++)
{
cout << endl << "第" << i + 1 << "道题:";
cout << a[t[i]].a;
cin >> r;
if (a[t[i]].result == r)
{
k++;
cout << "答案正确!" << endl;
}
else
{
cout << "答案错误!正确答案为:" << a[t[i]].result;
}
}
score = 100 * k / n;
cout << endl << "本次得分:" << score << endl;
//输出本次做题所得的分数并进行评价
if (score >= 90)
cout << "优秀,继续保持!" << endl;
else if (score >= 80)
cout << "良好,还需努力!" << endl;
else if (score >= 70)
cout << "一般,继续加油!" << endl;
else if (score >= 60)
cout << "及格,多多努力!" << endl;
else
cout << "糟糕,不及格,该好好学习了!" << endl;
if (!(fp = fopen("d:\\score.txt", "a")))
{
cout << "无法建立或者无法打开成绩信息文件!" << endl;
exit(-1);
}
fprintf(fp, " %d", score);
//将本次成绩写入文件
fclose(fp);
Avescore();
if (!(fp1 = fopen("d:\\average.txt", "r")))
{
cout << "无法创建或者无法打开平均成绩文件!" << endl;
exit(-1);
}
fscanf(fp1, "%d", &ave);
//读出之前成绩的平均成绩
fclose(fp1);
if (score > ave)
cout << endl << "成绩较以前相比有所进步,继续努力!" << endl;
else if (score < ave)
cout << endl << "成绩较以前相比退步了,要多多练习,不要气馁!!" << endl;
else
cout << endl << "成绩与以前持平" << endl;
}
void History()
//输出历史成绩
{
FILE *fp, *fp1;
int s, a;
if (!(fp = fopen("d:\\score.txt", "r")))
{
cout << "无法打开成绩信息文件!" << endl;
exit(-1);
}
cout << "历史成绩显示如下:" << endl;
while (!feof(fp))
{
fscanf(fp, "%d", &s);
cout << s << endl;
}
fclose(fp);
if (!(fp1 = fopen("d:\\average.txt", "r")))
{
cout << "无法打开平均成绩文件!" << endl;
exit(-1);
}
fscanf(fp1, "%d", &a);
cout << "平均为:" << a << endl << endl;
fclose(fp1);
}
int menu()
//菜单函数
{
int a;
do
{
system("cls");//清屏
cout << "\t\t******好好学习天天向上******\n\n";
cout << "\t\t
1.做题\n";
cout << "\t\t
2.查看历史成绩\n";
cout << "\t\t
3.退出系统\n\n";
cout << "\t\t****************************\n";
cout << "\t\t请选择:";
cin >> a;
} while (a < 1
a>3);
return a;
}
int main()
{
FILE *Fp;
int i;
char c;
Shiti s[100 + 1];
Num num;
Oper oper;
if (!(Fp = fopen("d:\\shitiku.txt", "r")))
//如果试题库文件不存在,则建立试题库
{
cout << "\t******欢迎使用******\n\n";
cout << "\t程序第一次运行,尚无试题库,请先建立试题库!\n\n\t";
system("pause");
Build();
cout << "成功建立试题库!";
system("pause");
}
while (1)
{
switch (menu())
{
case 1:
do {
Fp = fopen("d:\\shitiku.txt", "r");
for (i = 0; i < N; i++)
{
fscanf(Fp, "%s", s[i].a);
s[i].result = Result(s[i].a, &num, &oper);
}
fclose(Fp);
DoExercise(s); break;
cout << "\n是否继续做题?y-是,n-否:";
cin >> c;
} while (c != 'n'&&c != 'N');
break;
case 2:
History();
//输出成绩
system("pause");
break;
case 3:
cout << "\n\t欢迎使用,再见!\n\n\t";
exit(0);
//退出系统
}
}
return 0;
}
1 试题库生成模块
提示欢迎用户并输入学号。用户电脑 D 盘无相关文件时,自动产生一个文件
并由系统自动生成一定数目的数学四则运算式,并将运算式存入相应文件中。
2 栈计算试题答案模块
通过输入的试题,用栈来计算各个表达式的答案并存入相应的数组中。
3 用户菜单模块
用于调用各个模块、调节其关系。主函数调用用户菜单模块后先提示输入学
号信息,再提示构建试题库,接着跳转至答题\查看历史成绩\退出界面,由用
户选择相应功能。
4 用户答题模块
包含判定是否建立试题库、用户选择界面、答题界面等。进入该模块后,系
统先提示用户输入需要答题的答题数目,系统从试题库中选择相应数目题目进
行显示,用户作答。系统将用户输入的答案与系统存储的答案进行比较,提示
用户正误判断,显示本次答题分数并保存本次分数到文件中。
5 答题数据分析存储模块
用于存储用户成绩信息并存储,对于用户历史成绩可进行分析和评价的功能
模块。
推荐阅读更多精彩内容
开发答题微信小程序详细记录(附源码)前言:这几天在公司闲闲无事,恰好团队有通过在线考试的需求,于是自发撸了一个简单的考试类微信小程序。 纯前端,数据写...呆毛和二货阅读 31,613评论 22赞 38
python-day3字符串 1.什么是字符串 使用单引号或者双引号括起来的字符集就是字符串。 引号中单独的符号、数字、字母等叫字符。 ...mango_2e17阅读 7,122评论 1赞 7

我要回帖

更多关于 鸡兔同笼类型题怎么做 的文章

 

随机推荐