四则运算三

这一周,老师提出了新的要求:

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

  • 例如程序输出:20-5=?用户输入15,那么程序就会反馈正确,然后继续出题。直到三十道题目结束,程序最后告诉用户做对了几道题。

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

  • 20-5*2=?         正确答案是10.
  • 20-5*2+9/3=?  正确答案是13.

注意:

      连续的减法和除法,应该遵循左结合的规定。

      连续除法要打括号,否则会引起歧义。

针对这一次的练习,只需只需在上一次的基础上加上表达的式的求值即可,只是就需要用到数据结构中的栈来解决。说是简单,但是实现起来却不容易,数据结构一直是我头疼的东西。和我的同学比起来真的是自愧不如,这次他和我一直,询问了他许久。

最后在上一次的基础上,增加了一个表达式求解的模块,具体代码如下:

  1 // 按要求随机生成四则运算  王世强 2015/3/15  
  2 #include<iostream>
  3 #include<stdlib.h>
  4 #include<iomanip>
  5 #include<time.h>  
  6 #include<stdio.h> 
  7 #include"math.h"  
  8 #define true 1   
  9 #define false 0   
 10 #define OPSETSIZE 7  
 11 #define random() (rand()%100000)  
 12 #include"string.h"   
 13 typedef int Status;
 14 using namespace std;   
 15   
 16 unsigned char Prior[7][7] =  
 17 { // 运算符优先级表   
 18     // '+' '-' '*' '/' '(' ')' '#'    
 19     /*'+'*/'>','>','<','<','<','>','>',  
 20     /*'-'*/'>','>','<','<','<','>','>',  
 21     /*'*'*/'>','>','>','>','<','>','>', 
 22     /*'/'*/'>','>','>','>','<','>','>',
 23     /*'('*/'<','<','<','<','<','=',' ', 
 24     /*')'*/'>','>','>','>',' ','>','>',
 25     /*'#'*/'<','<','<','<','<',' ','=', 
 26 };   
 27   
 28 typedef struct StackChar  
 29 {  
 30     char c;   
 31     struct StackChar *next;   
 32 }SC;       //StackChar类型的结点SC  
 33   
 34 typedef struct StackFloat  
 35 {  
 36     float f;   
 37     struct StackFloat *next;   
 38 }SF;       //StackFloat类型的结点SF  
 39   
 40 SC *Push(SC *s,char c)          //SC类型的指针Push,返回p  
 41 {  
 42     SC *p=(SC*)malloc(sizeof(SC));   
 43     p->c=c;   
 44     p->next=s;   
 45     return p;   
 46 }   
 47   
 48 SF *Push(SF *s,float f)        //SF类型的指针Push,返回p  
 49 {  
 50     SF *p=(SF*)malloc(sizeof(SF));   
 51     p->f=f;   
 52     p->next=s;   
 53     return p;   
 54 }   
 55  
 56 SC *Pop(SC *s)    //SC类型的指针Pop  
 57 {  
 58     SC *q=s;   
 59     s=s->next;   
 60     free(q);   
 61     return s;   
 62 }   
 63   
 64 SF *Pop(SF *s)      //SF类型的指针Pop  
 65 {  
 66     SF *q=s;   
 67     s=s->next;   
 68     free(q);   
 69     return s;   
 70 }   
 71   
 72 float Operate(float a,unsigned char theta, float b)      //计算函数Operate  
 73 {  
 74     switch(theta)  
 75     {  
 76     case '+': return a+b;   
 77     case '-': return a-b;   
 78     case '*': return a*b;   
 79     case '/': return a/b;   
 80     default : return 0;   
 81     }   
 82 }   
 83   
 84 char OPSET[OPSETSIZE]={'+','-','*','/','(',')','#'};   
 85   
 86 Status In(char Test,char *TestOp)  
 87 {  
 88     int Find=false;   
 89     for (int i=0; i< OPSETSIZE; i++)  
 90     {  
 91         if(Test == TestOp[i])  
 92             Find= true;   
 93     }   
 94     return Find;   
 95 }   
 96   
 97 Status ReturnOpOrd(char op,char *TestOp)  
 98 {   
 99     for(int i=0; i< OPSETSIZE; i++)  
100     {  
101         if (op == TestOp[i])  
102             return i;  
103     }  
104 }  
105   
106 char precede(char Aop, char Bop)  
107 {   
108     return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];   
109 }   
110   
111 float EvaluateExpression(char* MyExpression)  
112 {   
113     // 算术表达式求值的算符优先算法  
114     // 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合   
115     SC *OPTR=NULL;       // 运算符栈,字符元素   
116     SF *OPND=NULL;       // 运算数栈,实数元素   
117     char TempData[20];   
118     float Data,a,b;   
119     char theta,*c,Dr[]={'#','\0'};   
120     OPTR=Push(OPTR,'#');   
121     c=strcat(MyExpression,Dr);   
122     strcpy(TempData,"\0");//字符串拷贝函数   
123     while (*c!= '#' || OPTR->c!='#')  
124     {   
125         if (!In(*c, OPSET))  
126         {   
127             Dr[0]=*c;   
128             strcat(TempData,Dr);           //字符串连接函数   
129             c++;   
130             if (In(*c, OPSET))  
131             {   
132                 Data=atof(TempData);       //字符串转换函数(double)   
133                 OPND=Push(OPND, Data);   
134                 strcpy(TempData,"\0");   
135             }   
136         }   
137         else    // 不是运算符则进栈   
138         {  
139             switch (precede(OPTR->c, *c))  
140             {  
141             case '<': // 栈顶元素优先级低   
142                 OPTR=Push(OPTR, *c);   
143                 c++;   
144                 break;   
145             case '=': // 脱括号并接收下一字符   
146                 OPTR=Pop(OPTR);   
147                 c++;   
148                 break;   
149             case '>': // 退栈并将运算结果入栈   
150                 theta=OPTR->c;OPTR=Pop(OPTR);   
151                 b=OPND->f;OPND=Pop(OPND);   
152                 a=OPND->f;OPND=Pop(OPND);   
153                 OPND=Push(OPND, Operate(a, theta, b));   
154                 break;   
155             } //switch  
156         }   
157     } //while   
158     return OPND->f;   
159 } //EvaluateExpression  
160 
161 //符号生成
162 char create_symbol(int n)
163 {
164     int n1,j;    
165     char symbol[1];
166     if(n==0)
167     {
168         n1=2;
169     }
170     else if(n=1)
171     {
172         n1=4;
173     }
174     j=random()%n1;
175     if(j==0) symbol[0]='+';
176     else if(j==1) symbol[0]='-';
177     else if(j==2) symbol[0]='*';
178     else symbol[0]='/';
179     return symbol[0];      
180  } 
181  //把数字转换成字符串型
182  string int_string(int number)
183  {
184     char str[200];
185     itoa(number,str,10);
186     string str_=str;
187     return str_; 
188   } 
189   //真分数合成一个字符串
190  string combination1(string str1,string str2,char k) 
191  {
192      string equation;
193      equation='('+str1+k+str2+')';
194      return equation;
195  } 
196  //新生成一个数
197 string create_num(int proper_fs,int range)
198 { 
199     int num,num1,num2,fs;
200     string str_num,str_num1,str_num2;
201       num=random()%range+1;
202     str_num=int_string(num);
203     if(proper_fs==1)
204     {
205         fs=random()%3;
206         if(fs==1)//判断是否生成真分数  
207         {    
208             for(;;)
209             {
210                 num1=random()%range+1;
211                  num2=random()%range+1;
212                 if(num1<num2) break;
213             }
214             str_num1=int_string(num1);
215             str_num2=int_string(num2);
216             str_num=combination1(str_num1,str_num2,'/');
217         }
218     }
219     return str_num; 
220   } 
221  //运算式转换成一个字符串
222  string combination(string str1,string str2,char k) 
223  {
224      string equation;
225      equation=str1+k+str2;
226      return equation;
227  }
228 
229 //得出正确答案 
230 float get_ans(string str)
231 {
232     int len;
233     float ans;
234     len=str.length();
235     char num[len];
236     for(int j=0;j<len;j++)
237     {
238         num[j]=str[j];
239     }
240     //用堆栈解决。。。 
241     ans=EvaluateExpression(num);
242     return ans;
243 } 
244  //主函数 
245 int main()
246 {
247     srand((int)time(NULL));  //设置时间种子 ,使得程序每次运行的结果都不同 
248     int num1,num2,num3,num4,count,n,change,amount,shuchu,range,j,repeat=0,bracket,proper_fs,right=0,wrong=0;
249     string str_num1,str_num2,temp;
250     float Answer,InputAns;
251     cout<<"有无乘除法?1有,0没有:"<<endl;
252     cin>>n;
253     cout<<"是否有括号?1有,0没有:"<<endl;
254     cin>>bracket; 
255     cout<<"是否有真分数?1有,0没有:"<<endl;
256     cin>>proper_fs; 
257     cout<<"请输入数字范围:"<<endl;
258     cin>>range; 
259     cout<<"请输入出题数量:"<<endl;
260     cin>>amount; 
261     string Equation[amount];
262     char symbol;
263     cout<<amount<<"道四则运算题如下:"<<endl; 
264     for(int i=0;i<amount;i++)
265     {    
266         count=random()%3+2;
267         str_num1=create_num(proper_fs,range);
268         str_num2=create_num(proper_fs,range);
269         symbol=create_symbol(n);
270         Equation[i]=combination(str_num1,str_num2,symbol);
271         if(count>2)
272         {
273             for(count;count>2;count--)
274             {
275                 symbol=create_symbol(n);
276                 str_num1=Equation[i];
277                 if(bracket==1)
278                 {
279                     change=random()%3;
280                     if(change==0)
281                     {
282                        str_num1='('+str_num1+')';
283                      }
284                 } 
285                 symbol=create_symbol(n);
286                 str_num2=create_num(proper_fs,range);    
287                 change=random()%2;
288                 if(change==0)
289                 {
290                     temp=str_num1;
291                     str_num1=str_num2;
292                     str_num2=temp;
293                 }                
294                 Equation[i]=combination(str_num1,str_num2,symbol);
295             }
296         }
297         //判断是否重复
298          for(j=0;j<i;j++)
299          {
300              if(Equation[j]==Equation[i])
301              {
302                 i=i-1;
303                 repeat=1;
304                 break;
305              }
306          }
307          if(repeat!=1)//若不重复,则输出 
308          {     
309             cout<<Equation[i]<<"=";
310             //判断结果是否正确
311             cin>>InputAns;
312             Answer=get_ans(Equation[i]);
313             Answer*=100;
314             int temp=(int)Answer;
315             Answer=((double)temp)/100.00;
316             if(InputAns==Answer)
317             {
318                 cout<<"回答正确!"; 
319                 right++;
320             }
321             else
322             {
323                 cout<<"回答错误!正确答案为";
324                 cout<<setprecision(2)<<fixed<<Answer;
325                 wrong++;
326             } 
327             cout<<endl;
328          }
329     }
330     cout<<"一共答对"<<right<<"道题,答错"<<wrong<<"道题。"<<endl; 
331 }

 

 

 下面是运行结果截图:

总结:这次的练习,熟悉了数据结构的知识,但是对我来说还是一个空缺部分,希望能够补上。

这次和我结队的同学是高逸凡,附一张我俩合作时的照片

项目计划总结:

日期&&任务 听课 编写程序 阅读相关书籍 网上查找资料   日总计
周一 2 3 2   7
周二   2    2 4
周三          
周四 2 2     4
周五   2  1   3
周六      2   2
周日          
周总计 4 9 5 2 20

  时间记录日志:

日期 开始时间 结束时间 中断时间 净时间 活动 备注
3/4 14:00 15:50 10 100 听课 软件工程上课
  16:00 18:20   140 编写程序 任务3
  19:00 20:00  10 50 编写程序 任务3
  20:00 21:00   60 网上查找资料,阅读 《构建之法》
3/15 16:00 18:00  10 110 查资料,编写程序 作业3
  19:00 21:10  10 120 编写程序 任务3
3/16            
3/17 14:00 15:50  10 100 听课 软件工程上课
  19:00 21:20  20 100 查资料,编写程序 休息,聊天,作业3
3/18 8:00 10:05  5 120 修改,编程 任务3
  16:10 17:20  10 60 阅读  《构建之法》
3/19 19:20 21:50  30 120 修改程序,写博客 休息,谈论问题,修改,发表博客
3/13 19:00 19:30   30 阅读书籍 计划阅读《梦断代码》

缺陷记录日志:

日期 编号 类型 引入阶段 排除阶段 修复时间 修复缺陷
3/18 1 20 编码 编译 120min  
  描述:栈的定义及使用,总是报错!

队友博客地址:http://www.cnblogs.com/yifan2016/p/5296389.html

posted @ 2016-03-19 12:40  John_Wang7  阅读(483)  评论(3编辑  收藏  举报