码迷,mamicode.com
首页 > 编程语言 > 详细

c/c++:四则运算题目生成器3

时间:2016-03-19 11:11:56      阅读:272      评论:0      收藏:0      [点我收藏+]

标签:

题目要求:

  1.学生写的程序必须能判定用户的输入答案是否正确

  2.程序必须能处理四种运算的混合算式

  3.要求两人合作分析,单独编程,单独撰写博客

团队成员:杜文星,张邵佳(http://www.cnblogs.com/me-tts/)

我的代码:

head.h

 1 #pragma once
 2 #include<iostream>
 3 #include<ctime>
 4 #include<strstream>
 5 #include<stdlib.h>
 6 #include<vector>
 7 #include<string>
 8 #include<cstdio>
 9 #include<cmath>
10 #define random(l,h) (rand()%(h-l+1)+l)//宏定义
11 #define maxsize 1000
12 using namespace std;
13 extern int flag;
14 /*stack.cpp*/
15 struct Fraction
16 {
17     int up, down;
18     string high, low;
19 };
20 void trans(string exp, char postexp[]);
21 Fraction compvalue(char postexp[]);//计算后缀表达式的值
22 /*fraction.cpp*/
23 int gcd(int a, int b);//求a,b的最大公约数
24 int max(int a, int b);
25 int min(int a, int b);
26 Fraction fraction(int up, int down);//生成分数
27 Fraction fra(int d, int u);//生成真分数;
28 Fraction reduction(Fraction result);//分数的化简
29 Fraction add(Fraction f1, Fraction f2);//分数的加法
30 Fraction minus1(Fraction f1, Fraction f2);//分数的减法
31 Fraction multi(Fraction f1, Fraction f2);//分数的乘法
32 Fraction divide(Fraction f1, Fraction f2);//分数的除法
33 void ShowResult(Fraction f);//输出分数
34 string FraToString(Fraction f);//将分数转换为string类型
35 /*yunsuan.cpp*/
36 int suiji(int down, int up);//随机生成1至n的整数
37 bool is_unique(string str, vector <string> s);//判断生成的运算式是否重复
38 void yunsuan(int time, int low, int high, int fl1, int fl2, int fl3);

fraction.cpp

  1 #include"head.h"
  2 int gcd(int a, int b)//求a,b的最大公约数
  3 {
  4     if (b == 0) return a;
  5     else return gcd(b, a%b);
  6 }
  7 
  8 int max(int a, int b)//返回两个整数中较大的整数
  9 {
 10     int h = a >= b ? a : b;
 11     return h;
 12 }
 13 int min(int a, int b)//返回两个整数中较小的整数
 14 {
 15     int l = a <= b ? a : b;
 16     return l;
 17 }
 18 Fraction fraction(int up, int down)//生成分数
 19 {
 20     Fraction result;
 21     result.up = up;
 22     result.down = down;
 23     strstream ss, kk;
 24     ss << result.up; ss >> result.high;
 25     kk << result.down; kk >> result.low;
 26     return result;
 27 }
 28 Fraction fra(int d,int u)//生成真分数
 29 {
 30     Fraction result;
 31     int temp1 = suiji(d, u);//调用function函数随机生成两个随机整数
 32     int temp2 = suiji(d, u);
 33     result.up = min(temp1, temp2);
 34     result.down = max(temp1, temp2);
 35     strstream s1, s2;
 36     s1 << result.up; s1 >> result.high;
 37     s2 << result.down; s2 >> result.low;
 38     return result;
 39 }
 40 Fraction reduction(Fraction result)//分数的化简
 41 {
 42     if (result.down < 0)
 43     {
 44         result.up = -result.up;
 45         result.down = -result.down;
 46     }
 47     if (result.up == 0)
 48     {
 49         result.down = 1;
 50     }
 51     else
 52     {
 53         int d = gcd(abs(result.up), abs(result.down));
 54         result.up /= d;
 55         result.down /= d;
 56     }
 57     strstream s3, s4;
 58     s3 << result.up; s3 >> result.high;
 59     s4 << result.down; s4 >> result.low;
 60     return result;
 61 }
 62 Fraction add(Fraction f1, Fraction f2)//分数的加法
 63 {
 64     Fraction result;
 65     result.up = f1.up*f2.down + f1.down * f2.up;
 66     result.down = f1.down*f2.down;
 67     return reduction(result);
 68 }
 69 Fraction minus1(Fraction f1, Fraction f2)//分数的减法
 70 {
 71     Fraction result;
 72     result.up = f1.up*f2.down - f1.down*f2.up;
 73     result.down = f1.down*f2.down;
 74     return reduction(result);
 75 }
 76 Fraction multi(Fraction f1, Fraction f2)//分数的乘法
 77 {
 78     Fraction result;
 79     result.up = f1.up*f2.up;
 80     result.down = f1.down*f2.down;
 81     return reduction(result);
 82 }
 83 Fraction divide(Fraction f1, Fraction f2)//分数的除法
 84 {
 85     Fraction result;
 86     result.up = f1.up*f2.down;
 87     result.down = f1.down*f2.up;
 88     return reduction(result);
 89 }
 90 void ShowResult(Fraction f)//输出分数
 91 {
 92     f = reduction(f);
 93     if (f.down == 1) cout << f.up;
 94     else cout << f.up << "\\" << f.down;
 95 }
 96 string FraToString(Fraction f)//将分数转换为string类型
 97 {
 98     string result;
 99     if (f.down == 1) result = f.high;
100     else result = f.high + "\\" + f.low;
101     return result;
102 }

stack.cpp

  1 #include"head.h"
  2 struct
  3 {
  4     char data[maxsize];//存放运算符
  5     int top;//栈顶指针
  6 }op;//定义运算符栈
  7 void trans(string exp, char postexp[])//exp[]为算数表达式,postexp[]为后缀表达式
  8 {
  9     char ch;
 10     int i = 0, j = 0;//i作为exp的下标,j作为postexp的小标
 11     op.top = -1;
 12     ch = exp[i];
 13     i++;
 14     while (ch != \0)//exp表达式未扫描完时循环
 15     {
 16         switch (ch)
 17         {
 18         case[://判定为左括号
 19         {
 20             op.top++;
 21             op.data[op.top] = ch;
 22         }break;
 23         case]://判定为右括号,此时将’[‘之前的运算符依次出栈并存放到postexp中
 24         {
 25             while (op.data[op.top] != [)
 26             {
 27                 postexp[j] = op.data[op.top];
 28                 j++;
 29                 op.top--;
 30             }
 31             op.top--;//将’[‘删除
 32         }break;
 33         case+://为’+‘或’-‘时,其优先级不大于栈顶的任何运算符,直到’]‘为止
 34         case-:
 35         {
 36             while (op.top != -1 && op.data[op.top] != [)
 37             {
 38                 postexp[j] = op.data[op.top];
 39                 j++;
 40                 op.top--;
 41             }
 42             op.top++;
 43             op.data[op.top] = ch;
 44         }break;
 45         case*://为’*‘或’/’时,其优先级不大于栈顶为‘*’或‘/‘的优先级,直到’[‘
 46         case/:
 47         {
 48             while (op.top != -1 && op.data[op.top] != [ && (op.data[op.top] == * || op.data[op.top] == /))
 49             {
 50                 postexp[j] = op.data[op.top];
 51                 j++;
 52                 op.top--;
 53             }
 54             op.top++;
 55             op.data[op.top] = ch;
 56         }break;
 57         case :break;//过滤掉空格
 58         case(://将分数当成一个整体放到postexp中
 59         {
 60             while (ch != ))
 61             {
 62                 postexp[j]=ch;
 63                 j++;
 64                 ch = exp[i];
 65                 i++;
 66             }
 67             postexp[j]=ch; j++;//将‘)‘放到postexp中
 68         }break;
 69         default:
 70         {
 71             while (ch >= 0&&ch <= 9)//判定为数字
 72             {
 73                 postexp[j] = ch;
 74                 j++;
 75                 ch = exp[i];
 76                 i++;
 77             }
 78             i--;
 79             postexp[j] = #;//用#标示一个数值的结束
 80             j++;
 81         }
 82         }
 83         ch = exp[i];
 84         i++;
 85     }
 86     while (op.top != -1)//此时exp扫描完毕,栈不空时出栈并存放到postexp中
 87     {
 88         postexp[j] = op.data[op.top];
 89         j++;
 90         op.top--;
 91     }
 92     postexp[j] = \0;//给postexp表达式添加结束标识
 93 }
 94 struct
 95 {
 96     Fraction data[maxsize];//存放数值
 97     int top;//栈顶指针
 98 }st;
 99  Fraction compvalue(char postexp[])//计算后缀表达式的值
100 {
101     double d;
102     char ch;
103     int i = 0;//postexp的下标
104     st.top = -1;
105     ch = postexp[i];
106     i++;
107     while (ch != \0)//postexp字符串未扫描完事完成循环
108     {
109         switch (ch)
110         {
111         case+:
112         {
113             st.data[st.top - 1] = add(st.data[st.top - 1], st.data[st.top]);
114             st.top--;
115         }break;
116         case-:
117         {
118             st.data[st.top - 1] = minus1(st.data[st.top - 1], st.data[st.top]);
119             st.top--;
120         }break;
121         case*:
122         {
123             st.data[st.top - 1] = multi(st.data[st.top - 1], st.data[st.top]);
124             st.top--;
125         }break;
126         case/:
127         {
128             st.data[st.top - 1] = divide(st.data[st.top - 1], st.data[st.top]);
129             st.top--;
130         }break;
131         case(:
132         {
133             double high = 0, low = 0;
134             ch = postexp[i]; i++;//删除‘(‘
135             while (ch != \\)
136             {
137                 high = 10 * high + ch - 0;
138                 ch = postexp[i];
139                 i++;
140             }
141             ch = postexp[i]; i++;//删除’\’
142             while (ch != ))
143             {
144                 low = 10 * low + ch - 0;
145                 ch = postexp[i];
146                 i++;
147             }
148             st.top++;
149             Fraction re = fraction(high, low);
150             st.data[st.top] = re;
151         }break;
152         default:
153         {
154             d = 0;
155             while (ch >= 0&&ch <= 9)//将数字字符转化为对应的数值存放到d中
156             {
157                 d = 10 * d + ch - 0;
158                 ch = postexp[i];
159                 i++;
160             }
161             st.top++;
162             Fraction re = fraction(d, 1);
163             st.data[st.top] = re;
164         }
165         }
166         ch = postexp[i];
167         i++;
168     }
169     return st.data[st.top];
170 }

yunsuan.cpp

  1 #include"head.h"
  2 int flag = 1;
  3 int suiji(int down, int up)//随机生成1至n的整数
  4 {
  5     int low = down, high = up;
  6     if (flag)
  7     {
  8         flag = 0;
  9         srand((unsigned)time(NULL));//种子
 10     }
 11     int result = random(down, up);
 12     return result;
 13 
 14 }
 15 bool is_unique(string str, vector <string> s)//判断生成的运算式是否重复
 16 {
 17     int count = 0;
 18     for (int i = 0; i < s.size(); i++)
 19     {
 20         if (str!=s[i])
 21         {
 22             count++;
 23         }
 24         else break;
 25     }
 26     bool flag0 = count == s.size() ? true : false;
 27     return flag0;
 28 }
 29 void yunsuan(int time, int low, int high, int fl1, int fl2, int fl3)//根据参数要求生成四则运算式
 30 {
 31     int integer1, integer2;
 32     int ch1, ch2, ch3, ch4;//switch语句的选项
 33     char sign;//运算符号
 34     int times = time;//题目数
 35     vector <string> str;//str用来保存生成的题目
 36     int right = 0, wrong = 0;
 37     for (int i = 1; i <= times;)
 38     {
 39         int flag4 = 1;//flag4用来标记运算式是否是刚开始生成
 40         string first, second, cal;//四则运算的第一个运算数和第二个运算数
 41         int number = suiji(1, 9);//number为参与运算的参数个数
 42         for (int j = 1; j <= number;)
 43         {
 44             //-------------------------------------------------------------------------------------
 45             if (fl1 == 1)//允许乘除发参与运算的情况
 46             {
 47                 ch1 = suiji(1, 4);//随机生成运算符号
 48                 switch (ch1)
 49                 {
 50                 case 1:sign = +; break;
 51                 case 2:sign = -; break;
 52                 case 3:sign = *; break;
 53                 case 4:sign = /; break;
 54                 default:cout << "有错误!" << endl; break;
 55                 }
 56             }
 57             else//不允许乘除法参与运算的情况
 58             {
 59                 ch1 = suiji(1, 2);//随机生成运算符号
 60                 switch (ch1)
 61                 {
 62                 case 1:sign = +; break;
 63                 case 2:sign = -; break;
 64                 default:cout << "有错误!" << endl; break;
 65                 }
 66             }
 67             //-------------------------------------------------------------------------------------
 68             if (fl3 == 1)//允许真分数参与运算
 69             {
 70                 ch2 = suiji(1, 3);//四则运算题目的三种情况
 71                 switch (ch2)
 72                 {
 73                 case 1://整数和整数
 74                 {
 75                     strstream si, so;
 76                     integer1 = suiji(low, high);
 77                     si << integer1; si >> first;
 78                     integer2 = suiji(low, high);
 79                     so << integer2; so >> second;
 80                 }break;
 81                 case 2://整数和真分数
 82                 {
 83                     strstream ss;
 84                     integer1 = suiji(low, high);
 85                     ss << integer1; ss >> first;
 86                     Fraction f = reduction(fra(low, high));
 87                     second = "(" + f.high + "\\" + f.low + ")";
 88                 }break;
 89                 case 3://真分数和真分数
 90                 {
 91                     Fraction f1 = reduction(fra(low, high));
 92                     Fraction f2 = reduction(fra(low, high));
 93                     first = "(" + f1.high + "\\" + f1.low + ")";
 94                     second = "(" + f2.high + "\\" + f2.low + ")";
 95                 }break;
 96                 default:cout << "有错误!" << endl; break;
 97                 }
 98             }
 99             else//不允许真分数参与运算
100             {
101                 strstream si, so;
102                 integer1 = suiji(low, high);
103                 si << integer1; si >> first;
104                 integer2 = suiji(low, high);
105                 so << integer2; so >> second;
106             }
107             //-------------------------------------------------------------------------------------
108             if (fl2 == 1)//允许括号(【】)参与运算
109             {
110                 ch4 = suiji(1, 4);
111                 switch (ch4)
112                 {
113                 case 1:
114                 {
115                     if (flag4 == 1)//flag4为1表示运算式还未生成前两个运算数
116                     {
117                         cal = first + sign + second;
118                         flag4 = 0;
119                     }
120                     else
121                     {
122                         cal = cal + sign + first;//将以生成的运算式个新生成的运算数连接起来
123                     }
124                 }break;
125                 case 2:
126                 {
127                     if (flag4 == 1)
128                     {
129                         cal = second + sign + first;
130                         flag4 = 0;
131                     }
132                     else
133                     {
134                         cal = second + sign + cal;
135                     }
136                 }break;
137                 case 3:
138                 {
139                     if (flag4 == 1)
140                     {
141                         cal = "[" + first + sign + second + "]";//添加括号【】的情况
142                         flag4 = 0;
143                     }
144                     else
145                     {
146                         cal = "[" + cal + sign + first + "]";
147                     }
148                 }break;
149                 case 4:
150                 {
151                     if (flag4 == 1)
152                     {
153                         cal = "[" + second + sign + first + "]";
154                         flag4 = 0;
155                     }
156                     else
157                     {
158                         cal = "[" + second + sign + cal + "]";
159                     }
160                 }break;
161                 default:cout << "有错误!" << endl; break;
162                 }
163             }
164             else//不允许括号(【】)参与运算
165             {
166                 ch4 = suiji(1, 2);//输出的两种情况
167                 switch (ch4)
168                 {
169                 case 1:
170                 {
171                     if (flag4 == 1)
172                     {
173                         cal = first + sign + second;
174                         flag4 = 0;
175                     }
176                     else
177                     {
178                         cal = cal + sign + first;
179                     }
180                 }break;
181                 case 2:
182                 {
183                     if (flag4 == 1)
184                     {
185                         cal = second + sign + first;
186                         flag4 = 0;
187                     }
188                     else
189                     {
190                         cal = second + sign + cal;
191                     }
192                 }break;
193                 default:cout << "有错误!" << endl; break;
194                 }
195             }
196             j++;
197         }
198         //------------------------------------------------------------------------------
199         if (str.empty())//若sr为空,则将第一个生成的运算式添加到vector中
200         {
201             str.push_back(cal);
202             cout << "(" << i << ")." << cal << "=";
203 
204             string answer;
205             cin >> answer;
206             char postexp[maxsize];
207             trans(cal, postexp);
208             Fraction re = compvalue(postexp);
209             string result = FraToString(re);
210             if (answer == result)
211             {
212                 cout << "正确!" << endl;
213                 right++;
214             }
215             else
216             {
217                 cout << "错误!,正确答案为:" << result << endl;
218                 wrong++;
219             }
220             i++;
221         }
222         if (is_unique(cal, str))//判断生成的运算式和之前已经生成的运算式是否重复
223         {
224             str.push_back(cal);//将生成的运算式添加到str中
225             cout << "(" << i << ")." << cal << "=";
226             string answer;
227             cin >> answer;
228             char postexp[maxsize];
229             trans(cal, postexp);
230             Fraction re = compvalue(postexp);
231             string result = FraToString(re);
232             if (answer == result)
233             {
234                 cout << "正确!" << endl;
235                 right++;
236 
237             }
238             else
239             {
240                 cout << "错误!,正确答案为:" << result << endl;
241                 wrong++;
242             }
243             i++;
244         }
245         else {}
246     }
247     cout << "**********************************************************************************" << endl;
248     cout << "你做对了" << right << "道题,做错了" << wrong << "道题" << endl;
249 }

main.cpp

 1 #include"head.h"
 2 int main()
 3 {
 4     cout << "请输入题目数(1~100):";
 5     int times, down, up, flag1, flag2, flag3, flag4;
 6     cin >> times;//times至题目数
 7     cout << "请输入数值绝对值范围:";
 8     cin >> down >> up;//[down,up]为运算数范围
 9     cout << "是否允许乘除发参与运算(y/n):";
10     char yn1;
11     cin >> yn1;
12     yn1 == y || yn1 == Y ? flag1 = 1 : flag1 = 0;
13     cout << "是否允许括号([])参与运算(y/n):";
14     char yn2;
15     cin >> yn2;
16     yn2 == y || yn2 == Y ? flag2 = 1 : flag2 = 0;//flag2判断是否允许括号参与运算
17     cout << "是否允许真分数参与运算(y/n):";
18     char yn3;
19     cin >> yn3;
20     yn3 == y || yn3 == Y ? flag3 = 1 : flag3 = 0;//flag3判断是否允许真分数参与运算
21     cout << "**********************************************************************************" << endl;
22     yunsuan(times, down, up, flag1, flag2, flag3);
23     system("pause");
24     return 0;
25 }

结果截图:

技术分享

技术分享

技术分享技术分享

设计思路:

本次程序由于代码量相对较大,故将代码分写在不同的文件中;

head.h:在头文件head.h中,将其他.cpp文件中所需要的头文件(如<iostream>等)、全局变量的声明、函数的声明都写在此文件中

fraction.cpp:此文件中主要定义了一些与分数有关的函数,如分数的生成化简、加减乘除、分数的输出、分数转字符串等

stack.cpp:此文件中的主要功能是将所给的运算式的结果计算出来,主要思路是利用栈先将运算时转化为后缀式,然后再利用栈将后缀式的结果求出,这里的重难点是转化后缀式                  时如何将真分数当做一个整体,我们的解决方法是通过识别“(”和“)”来识别;同时在计算时即使是整数我们也将其转化为分数处理,故调用了fraction中的一些方法来        进行加减乘除

yunsuan.cpp:次文件的主要功能是实现运算式的生成,并判断使用者输入的结果和题目的答案是否相同来判断对错,并输出正确数与错误数

main.cpp:主函数所在的头文件,主要功能是和用户进行交互

工作照:

技术分享

周活动日志:

  听课 编写程序 阅读课本 日总计
周一 100 120 0 220
周二 0 120 0 120
周三 0 120 0 120
周四 100 0 50 150
周五 0 160 0 160
周六 0 300 0 300
周日        
周总计 200 820 50 1070

时间记录日志:

日期 开始时间 结束时间 中断时间 净时间 活动 备注
3月14日 14:00 15:50 10 100 上课  
  18:00 21:30 0 210 编程 软件工程作业
3月15日 8:00 12:00 20 220 上课  
  18:30 21:30 0 180 自习  
3月16日 8:00 12:00 20 220 上课  
  18:30 21:30 0 180 自习  
3月17日 14:00 18:00 20 220 上课  
  19:00 21:30 0 150 自习(阅读)  
3月18日 8:00 10:00 0 120 自习(阅读)  
  18:00 21:30 0 210 编程 软件工程作业
3月19日 8:30 12:00 0 210 自习  

缺陷日志:

日期 编号 缺陷内容 引入阶段 排除阶段 修复时间 修复缺陷
3月14日 1

如何计算运算

编写代码 思考、查资料 80+ 利用栈来实现
3月18日 2

如何识别真分

编写代码 思考、查资料 120+ 利用()来识别

c/c++:四则运算题目生成器3

标签:

原文地址:http://www.cnblogs.com/duwenxing/p/5294508.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!