一个小小的计算器

(一) 需求和规格说明

输入是一个带有括号的四则运算表达式,输出是计算得出的正确计算结果。例如:输入:123+213-67*34+345/23*45*(34+34-345+245+567)回车,然后程序计算得出结果为:359183。

(二)设计:

1.首先我想到不能打空格的话还能分开存储于是我先用到了字符串。

2.接着我将问题分开解决,因为输入的是一个char型,我首先做的是先将其转换为int型的数据,然后又开一个数组(num)进行储存。在用在字符串中的排列顺序,将每个数值都乘上一个10的阶乘进行运算,然后储存进入数组(NUM).

3.然后就是计算加减的问题了,一开始这个是花了一点时间的,因为顺序的问题总是会录入错位的数据,后来在草稿纸上写了一下就弄好了,这也让我觉得在草稿纸上写一下,把自己当做编译器是一件有趣的事。

4.接着就是乘除,我一开始觉得和加法没什么不同啦,就是指将乘除放在前面而已,但是后来才发现,机器不是人,他们能想到是只有我们给他们的,比如3+4*5和4*5+3是不一样的,我们需要改变的对所有的情况判断,要能让计算机有这个判断的能力运算所有的运算列。

5.这个做了之后我就开始考虑括号的问题了,一开始我做了前面的时候我以为也很简单但是我觉得我真的太嫩,我就想到了首先规定了运算等级,然后这就和生活一样就可以了,括号最大,接着乘除,然后是加减。于是我将括号内的运算单独形成了一个小世界,设置了多个单独的数组进行储存。最后只要将整个括号内的运算结果带出来就可以了。

6.最后就是检验完善的时候了,老师的例子的确好,发现了不少的问题,也是花了不少的时间改正了过来。

7.从最初的107行到现在的174行,不停地找bug和可以完善的地方。

8.最后用老师的代码直接自己改了一下,弄了一个小小的美化。

9.有觉着这是一个计算器,于是我又加了一些小小的简化运算,比如开方什么的。

10.本来写的是一个整体的,后来也是在老师的建议下,我还是成了子函数,因为子函数整体的结构比较清晰明了。

大概的思路就是上面那个了,之后的调试之类的也是很久,但是主要的框架就只这样做出来的。

 

程序结构图:

文字演示:

输入:3-4*(8-5)

第一步:找到括号,运算出括号内为3。

第二步:扫描括号外数字扫描到括号就直接当做3,并跳过,式子变为:3-4*3。

第三布:就直接运算3-4*3=-9。输出,结束。

 

 

表1.子函数:

 

数值类型

名字

作用描述

void

NUMchucun

括号内录入

void

KUOjisuan

括号内运算结果

void

shu

括号外的数字的存储

void

cheng

整个的乘法运算

void

jiafa

最后的加减的运算

void

jiancha

检查式子有无错误

 

 

表2.数组:

数据类型

名字

描述

char

mula

用户输入的运算式

double

KUOSUM

每个括号的所有数的运算结果

double

KUONUM

括号内的所有的数

double

KUOSEA

          括号内的乘法和除法的运算结果

double

KUO

           括号在字符串内的位置

double

NUM

非括号的其他数字

double

SEA

非括号的其他数字的乘法和除法的运算结果

double

num

将char类型装换的存放的一个数组,不参加主要运算

 

 

 

 

 

(三) 用户手册

1.当程序运行时,会提示你输入。

2.只能输入数字,加减乘除,括号,和规定的特殊运算代号。

警告:输入其他的字符将会终止程序。

 

(六)进一步改进

 

(1).目前这个程序不支持空格的处理,但是可以考虑用getchar来进行一个一个的输入扫描排出。

(七)心得体会:

问题:

1.定义的int型,导致4/5的时候输出结果为0,发现之后先就是将程序的所有

数组改为了double型,然后将关键的变量也修改为double,ok了。

2. 无法计算4+5*1-6,原因是在前面没有+或者-的时候,存储的算式中的数值没办法进位,所以进行运算的就是零了,加入了判断,让。

3.  4*5-4,这个算式之前会遇到一个bug,因为在*之前的运算符号里面并没有+-这两种中的一个,所以的算式在看到这个式子的时候就会直接将后面的4给变为0,这样的话我们的算式就直接变成了4*5-0.这样肯定是错的,所以我增加了一个代码行,写入一个如果前面没有加号和减号,也会计算一个变量。

心得:

首先肯定是自己的编程能力得到了很大的提高,在对待问题的严谨程度上也有了很大的提升,在编程中找到快乐是走得更远的一大前提,而这次最美的就是在最无助的时候坚持。一开始写的时候想的是2天写出来,因为一开始就得很简单嘛,但是写着写着就不对了,慢慢觉得好多东西都对,一个一个的bug出来,白天也想晚上也想,就这样过了整整4天的样子,终于把一个大概的成品写出来了,当时写出的时候真的是觉得值了,之前的努力都没白费,简直爽。慢慢的自己也是喜欢上了编程,他不像其他东西,有可能出错,他特别严谨,只有你错了,没有它错了。

建议:

感觉的话就是题目太少了,这样很大的限制了同学的发挥,就是可不可以试一试让同学自己随便写然后根据难易创意来打分。

 

 

源代码:

#include<iostream>

#include<math.h>

#include<vector>

#include"ConsoleOut.h"

#pragmacomment (lib, "ConsoleOut.lib")

usingnamespace std;

#defineSize 10000

#definePI 3.1415926

voidNUMchucun(double[],int,char[],double[],double[]);//括号内录入函数的声明

voidKUOjisuan(double[],int,double[],char[],double[],double[]);//括号内运算结果函数声明

voidshu(int,char[],double[],double[],double[],double[]);//括号外的数字的存储函数声明

voidcheng(int,double[],char[],double[],double[],int[]);//整个的乘法运算函数声明

voidjiafa(int,double[],char[],double[],double[]);//最后的加减的运算函数声明

voidjiancha(char[],int,int,int[]);

voidgraph_welcome(void)

{

      CreateSmWindow(0,0, 75,23, 12, 0, 2, 1,"Super Counter", false);

      MoveCursorTo(2, 1);

      SetTextColor(12, 1);

}

//主程序代码

intmain()

{

op:

      int weizi=4;

      graph_welcome();

      char mula[Size];//用户输入的运算式

      cout<<"使用说明:1.式子前面加“s,c,t”可以执行正弦余弦正切。";

      MoveCursorTo(2, 2);

      cout<<"    2.式子前面加“:”可以执行开方。";

      MoveCursorTo(2, 3);

      while(cin>>mula)

{

     

      double teshu[1]={0};//专门用来当特殊数

      int teshu1[1]={0};//专门当特殊数

      int error[1]={0};

      double KUOSUM[Size]={0};//每个括号的所有数的运算结果

      double KUONUM[Size]={0};//括号内的所有的数

      double KUOSEA[Size]={0};//括号内的乘法和除法的运算结果

      double KUO[Size]={0};//括号在字符串内的位置

      double NUM[Size]={0};//非括号的其他数字

      double SEA[Size]={0};//非括号的其他数字的乘法和除法的运算结果

      double num[Size]={0};//将char类型装换的存放的一个数组,不参加主要运算

      double sum=0,DX=0;

      int n=0,i=0,kuo=0;

      n=strlen(mula);//计算输入的长度

      mula[n]=',';//在最后一位后加一个P

      jiancha(mula,n,weizi,error);

      if(error[0]){weizi+=1;goto over1;}

      for(i=0;i<=n;i++)//找到括号的位置

      {

             if(mula[i]=='('||mula[i]==')'){KUO[kuo]=i;kuo++;}

      }

      NUMchucun(KUO,kuo,mula,KUONUM,num);//将每个括号内的数单独给存储出来

      KUOjisuan(KUONUM,kuo,KUO,mula,KUOSEA,KUOSUM);//将括号内的运算结果储存到KUOSUM这个数组里面

      shu(n,mula,num,NUM,KUO,KUOSUM);//扫描非括号内的数字储存

      cheng(n,KUO,mula,SEA,NUM, teshu1);//算式的乘法

      jiafa(n,NUM,mula,SEA,teshu);//算式的加减

      for(i=0;i<=teshu1[0];i++){teshu[0]+=SEA[i];}//为了保险进行一个加减

      MoveCursorTo(2, weizi);

      weizi+=1;

      if(mula[0]==':'){teshu[0]=sqrt(teshu[0]);}//求开方

      if(mula[0]=='s'){teshu[0]=teshu[0]/180*PI;teshu[0]=sin(teshu[0]);}//求sin

      if(mula[0]=='c'){teshu[0]=teshu[0]/180*PI;teshu[0]=cos(teshu[0]);}//求cos

      if(mula[0]=='t'){teshu[0]=teshu[0]/180*PI;teshu[0]=tan(teshu[0]);}//求tan

      cout<<teshu[0]<<endl;//输出

over1:

      MoveCursorTo(2, weizi);//移动光标

      weizi+=1;

      cout<<"------------------------------";

      MoveCursorTo(2, weizi);

      if(weizi==24){goto op;}//限制不出方格

      weizi+=1;

 

}

      return 0;

}

voidjiancha(char*mula,int n,int weizi,int*error)

{

for(inti=1;i<n;i++)//判断输入的算式有没有错误

      {

             if(mula[i]<39||mula[i]==44||mula[i]>58)

             {

                    MoveCursorTo(2,weizi);cout<<"!!算式错误"<<endl;//输出错误

                    weizi+=1;error[0]+=1;gotoover;//终止程序

             }

             if(mula[i]=='+'||mula[i]=='-'||mula[i]=='*'||mula[i]=='/')

             {

                    if(mula[i+1]=='+'||mula[i+1]=='-'||mula[i+1]=='*'||mula[i+1]=='/'||mula[i+1]=='=')

                    {

                           MoveCursorTo(2,weizi);cout<<"!!算式错误"<<endl;//输出错误

                    weizi+=1;error[0]+=1;gotoover;//终止程序

                    }

             }

      }

over:;

}

 

//录入数字的子函数

voidNUMchucun(double*KUO,int kuo,char*mula,double*KUONUM,double*num)

{

      intx=0,in=0,i=0,peak=0,l=0,y=0,g=0,wwe=0,ww=0;

      for(x;x<=kuo/2;x++)

      {

             i=KUO[in]+1;

             for(i;i<=KUO[in+1];i++)

             {

                    if(mula[i]=='.')//判断是否为带小数点的

                    {

                           ww=i;

                           for(ww;ww<=KUO[in+1];ww++)//循环存储小数点后几位的函数

                           {

                                  if(mula[ww]>47&&mula[ww]<58){num[peak]=mula[ww]-48;peak++;i++;}

                                  if(mula[ww]=='+'||mula[ww]=='-'||mula[ww]=='*'||mula[ww]=='/'||mula[ww]==','||mula[ww]==')'){gotonike;}

                           }

                    }

                    if(mula[i]>47&&mula[i]<58){num[peak]=mula[i]-48;peak++;l++;}//录入小数点前几位

                    if(mula[i]=='+'||mula[i]=='-'||mula[i]=='*'||mula[i]=='/'||mula[i]==','||mula[i]==')')//开始总结存入数字

                    {

                           wwe=l;

                           for(y=0;y<peak;y++)

                                  {

                                         KUONUM[g]=num[y]*pow(10,l-1)+KUONUM[g];

                                         l--;

                                  }

                    //     l=0;

                           g++;

                           peak=0;

                    }

nike:;

             }

             in+=2;

      }

}

 

 

 

//括号内运算结果函数

voidKUOjisuan(double*KUONUM,intkuo,double*KUO,char*mula,double*KUOSEA,double*KUOSUM)

{

      int x=0, in=0,q=0,i=0,sea=0,nike=0;

      double DX=0,sum=0;

      DX=KUONUM[0];//先将DX赋第一个括号的第一个数

      for(x;x<kuo/2;x++)//计算括号内的运算结果

      {

             i=KUO[in]+1;

             for(i;i<KUO[in+1];i++)//乘除的运算结果

             {    

                    if(mula[i]=='+'||mula[i]=='-'){q++;DX=KUONUM[q];sea++;}

                    if(mula[i]=='*'){DX=DX*KUONUM[q+1];KUONUM[q+1]=0;KUONUM[q]=0;q++;KUOSEA[sea]=DX;}

                    if(mula[i]=='/'){DX=DX/KUONUM[q+1];KUONUM[q+1]=0;KUONUM[q]=0;q++;KUOSEA[sea]=DX;}

             }

             q=0;sum=KUONUM[0];

             i=KUO[in]+1;

             for(i;i<KUO[in+1];i++)//加减

             {

                    if(mula[i]=='+'||mula[i]=='*'||mula[i]=='/'){sum+=KUONUM[q+1];q++;}

                    if(mula[i]=='-'){sum-=KUONUM[q+1];q++;}

             }

             for(i=0;i<=sea;i++){sum+=KUOSEA[i];}//算出结果

             KUOSUM[x]=sum;//给KUOSUM这个数组

             in+=2;

             nike+=(KUO[x+1]-KUO[x])/2;

             DX=KUONUM[nike];//又将DX赋于第二个括号内的第一个数

      }

}

 

 

 

//括号外的数字的存储函数

voidshu(int n,char*mula,double*num,double*NUM,double*KUO,double*KUOSUM)

{

      int i=0,x=0,l=0,y=0,in=0,yun=0,g=0,ww=0;

      for(i;i<=n;i++)//开始扫描出非括号内的数

      {

             if(mula[i]=='.')//

                    {

                           ww=i;

                           for(ww;ww<=n;ww++)

                           {

                                  if(mula[ww]>47&&mula[ww]<58){num[x]=mula[ww]-48;x++;i++;}

                                  if(mula[ww]=='+'||mula[ww]=='-'||mula[ww]=='*'||mula[ww]=='/'||mula[ww]==','||mula[ww]==')'){gotonike;}

                           }

                    }

             if(mula[i]>47&&mula[i]<58){num[x]=mula[i]-48;x++;l++;}

             if(mula[i]=='+'||mula[i]=='-'||mula[i]=='*'||mula[i]=='/'||mula[i]==',')

             {

                    for(y=0;y<x;y++)

                           {

                           NUM[g]=num[y]*pow(10,l-1)+NUM[g];

                           l--;

                           }

                    l=0;

                    g++;

                    x=0;

             }

             if(mula[i]=='('){NUM[g]=KUOSUM[yun];i=KUO[in+1];in++;yun++;g++;}//扫描到括号的时候就插入之前的运算数,并跳过

nike:;

      }

}

 

 

//整个的乘法运算函数

voidcheng(int n,double*KUO,char*mula,double*SEA,double*NUM,int*teshu1)

{

      int in=0,i=0,q=0;

      teshu1[0]=0;

      double DX=NUM[0];

      for(i=0;i<n;i++)//运算括号外的的乘除运算结果

      {

             if(mula[i]=='('){i=KUO[in+1];in++;}

             if(mula[i]=='+'||mula[i]=='-'){q++;DX=NUM[q];if(SEA[teshu1[0]]!=0){teshu1[0]+=1;}}//如果第一个是没有赋值的话就不sea++

             if(mula[i]=='*'){DX=DX*NUM[q+1];NUM[q+1]=0;NUM[q]=0;q++;SEA[teshu1[0]]=DX;}

             if(mula[i]=='/'){DX=DX/NUM[q+1];NUM[q+1]=0;NUM[q]=0;q++;SEA[teshu1[0]]=DX;}

      }

}

 

 

//最后的加减的运算函数

voidjiafa(int n,double*NUM,char*mula,double*SEA,double*teshu)//算式的加减

{

      int q=0,i=0,adidas=0,over=0;

      teshu[0]=NUM[0];

      for(i=0;i<n;i++)//扫描过去

      {

             if(mula[i]=='+')

             {

                    for(adidas=i+1;adidas<=n;adidas++)//为了防止一个bug(PS:2-3*4)比如括号这个,减法的话会执行减去的是我

                    {                                                        //已经归零的3,而不是这个整式子,然后就会子

                           if(mula[adidas]=='*'||mula[adidas]=='/'){teshu[0]+=SEA[over];SEA[over]=0;over++;q++;gotoloop;}

                           if(mula[adidas]=='+'||mula[adidas]=='-'||mula[adidas]==','||mula[adidas]=='('){teshu[0]+=NUM[q+1];q++;gotoloop;}

                    }

             }

 

             if(mula[i]=='-')

             {

                    for(adidas=i+1;adidas<=n;adidas++)

                    {

                           if(mula[adidas]=='*'||mula[adidas]=='/'){teshu[0]-=SEA[over];SEA[over]=0;over++;q++;gotolop;}

                           if(mula[adidas]=='+'||mula[adidas]=='-'||mula[adidas]==','||mula[adidas]=='('){teshu[0]-=NUM[q+1];q++;gotolop;}

                    }

             }

 

             if(mula[i]=='*'||mula[i]=='/'){q++;}//如果为了防止一个bug(PS:3*4-5),因为前面没有+或者-。

loop:lop:;                                                             //所以不会执行q++然后就么办法执行到-5的命令,而是执行-4,

      }                                                                    //但是4在我前一个步就归零了,所以错误

 

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值