简单计算器实现(C++)

来源:互联网 发布:阳光姐姐嘉年华淘宝网 编辑:程序博客网 时间:2024/06/02 14:30

       本人写了一个简单的计算器实现代码,能实现+-*/及()功能.特此备案.

一、开发环境:

Linux操作系统(Fedora虚拟机), vim、g++等开发环境。

二、核心算法

1、 int Test(string str): 对输入的const string类型字符串(计算式)进行检测,发现其是否为一正确的计算表达式,如果是则return 1,如果否则return 0。如“12+23”为正确则返回1,“12*&45”为错误计算式,则返回0。

2、 string stringtoarr(const stringstr):对输入的无括号的conststring类型字符串str进行单元转换,将最终返回其值,如果某个单元“12+23*2”,则将之返回为“58”。

3、 string trims(const string&sub):将输入的带括号的字符串进行去括号操作,最后返回无括号的表达式(对带括号的子字符串部分进行stringtoarr处理,去除括号)。这是一个递归函数,如果子字符串中含有多个括号,则反复地自递归调用。

三、编译与链接

在虚拟机环境下,使用vim环境指令创建Calculation.cpp文件,并用g++进行编译与链接g++ Calculation.cpp –oCal.out。并使程序能正常进行实现计算器功能。

四、自测试报告。

1、对生成的Cal.out文件进行运行,并进行测试用例自测试过程(正异常用例共7组):

正常用例测试

第一组(加减):12.2+23.0      24+34.6+34+7854.3      56-23.3+23.5-0.12

第二组(乘除):17/56  23*45.75 12.04/34  23.77/34.901*23.0  23.04*0/34.2

第三组(+-*/混合):23.4*23.5/34     23+234*34.3/45.9-23/23.04 

第四组(+-*/混合,带一个或多个括号):

(12-45.4)/23.78   (12*23.5-23/(25.7-34.6))*12   2*(12-(45.5*(12.3*(11.92-6))-12.4)*2.3)

错误用例测试:

第一组(字符错误):12<23.2-34.6   89.6/56,2+2 23%7   21^2   2a.0-12 12”3-12

第二组(被除数为零): 12/0.0+12

第三组(式中括号有误): 12-(12.7*(35-45.8)+2    12-(12.7*)35-45.8)+2   12*)34-98(-23

2、部分测试报告截图如下:

 

*说明:此计算器代码相对较简单,是以一个.cpp文件将三个子函数全部写下。如果在建立的工程需要将子函数写成不成同的.cpp文件,则需要用到Makefile,规定每个程序源文件的编译顺序,否则改动程序时会经历循环反复的编辑à编译à测试过程,比较费时。

五、审评意见:

使用递归算法实现计算器功能,代码相对简洁,但编码不太规范,希望在以后的编码工作中加强规范编码的训练。


附录代码:

//Calculation.cpp : 定义控制台应用程序的入口点。////#include"stdafx.h"#include<stdio.h>#include<iostream>#include<string>#include<stdlib.h>#include<fstream>usingnamespace std; intTest(string as){         string::size_type len=as.size();         string::size_type i=0;         int k=0;         while(i<len)         {         if(!((as[i]>='0' &&as[i]<='9') || as[i]=='+' || as[i]=='-' || as[i]=='*' || as[i]=='/'||as[i]=='.' || as[i]=='(' ||  as[i]==')'))         {             cout<<"输入的表达式错误,请重新输入!"<<endl;             return 0;         }         if(as[i]=='/'&&as[i+1]=='0')         {             cout<<"分母不能为零!"<<endl;             return 0;                    }         if(as[i]=='(')              k++;         else if(as[i]==')')                    {                              k--;                              if(k<0)                                       return 0;                    }         i++;         }    if(k!=0)    {       cout<<"括号输入错误!"<<endl;       return 0;         }         return 1;} stringstringtoarr(const string str)   //将一个字符串转化成两个数组,一个为数字数组保存数字,另一个为字符数组,保存符号{                               //此函数将用于无括号的计算。    int i=0,z=0,s,temp;         float rate=10.0,itemp=0.0;         float valueStr=0.0;         float a[40];            char b[20];         for(i=0;i<40;i++)         a[i]=0.0;                         //对数组a[20]初始化         for(i=0;i<20;i++)         b[i]=' ';                                //对数组b[10]初始化         i=0;                                           //把0赋给i         for(i=0;i<str[i];i++)                           {                   if(str[i]>='0'&& str[i]<='9')                //如果字符串str.GetAt(i)的内容是整数                   {                                                                     if(rate==10.0)                         //整数部分                                     itemp=itemp*rate+(str[i]-'0');     //获得整数                            else                                   //小数部分                            {                                            itemp=itemp+rate*(str[i]-'0');     //获得小数                                     rate=rate/10;                      //每次让rate小10倍                            }                   }                   elseif(str[i]=='.')                       //如果str.GetAt(i)是小数点                            rate=0.1;                              //让rate=0.1,开始计算小数部分                   elseif(str[i]=='+')                       //如果str.GetAt(i)是加号        {                              a[z]=itemp;itemp=0;                    //把itemp的值放入双精度数组a中,并把itemp的值改为0                            z++;                                   //让z自加一次                            b[z]='+';                              //把加号放入字符数组b中                             z++;                                   //让z自加一次                            rate=10.0;                             //把10赋给rate,确保读取下个数字时,先计算整数部分                   }                   else if(str[i]=='-')                            //如果str.GetAt(i)是减号        {                                  a[z]=itemp;itemp=0;                //把itemp的值放入双精度数组a中,并把itemp的值改为0                          z++;                                  //让z自加一次                          b[z]='-';                               //把减号放入字符数组b中                                z++;                              //让z自加一次                           rate=10.0;                                  //把10赋给rate,确保读取下个数字时,先计算整数部分                   }                   else if(str[i]=='*')                             //如果str.GetAt(i)是乘号        {                            a[z]=itemp;itemp=0;                    //把itemp的值放入双精度数组a中,并把itemp的值改为0                            z++;                                  //让z自加一次                            b[z]='*';                               //把减号放入字符数组b中                            z++;                                  //让z自加一次                       rate=10.0;                               //把10赋给rate,确保读取下个数字时,先计算整数部分                   }                   else if(str[i]=='/')                             //如果str.GetAt(i)是除号        {                            a[z]=itemp;itemp=0;                    //把itemp的值放入双精度数组a中,并把itemp的值改为0                            z++;                                  //让z自加一次                            b[z]='/';                               //把除号放入字符数组b中                            z++;                                //让z自加一次                            rate=10.0;                           //把10赋给rate,确保读取下个数字时,先计算整数部分                   }         }         a[z]=itemp;                                     //把最后一个整数itemp的值放入双精度数组a中    s=z;                               //把z的值赋给变量s,用来控制计算结果的循环中的条件,s即为数与值的大小。         for(i=0;i<=s;i++)                                       {                   if(b[i]=='/')                               //当循环遇到除号时                   {                            a[i+1]=1/a[i+1];                        //把a[i+1]的值改为1/a[i+1]                            b[i]='*';                                        //把b[i]的值改为乘号                           }                                                   }     for(i=0;i<=s;i++)                                       {                   while(b[i]=='*')                               //当循环遇到乘号时                   {                            a[i-1]=a[i-1]*a[i+1];                            for(temp=i+1;temp+2<40;temp++)                                     a[temp]=a[temp+2];                            for(temp=i;temp+2<20;temp++)                                     b[temp]=b[temp+2];                   }         }         valueStr=a[0];         for(i=0;i<s;i++)         {                   if(b[i]=='+')                            valueStr+=a[i+1];                   else if(b[i]=='-')                            valueStr-=a[i+1];         }         char svalue[16];    sprintf(svalue,"%f" , valueStr);    string ssavalue(svalue);    return ssavalue;} stringtrims(const string &sub){         string s1,s2,s3,sp,ss;         int i;         int counter=0;         int left,right;         if(string::size_typepos1=sub.find(")")==string::npos)                   return sub;         for(i=0;sub[i];i++)                   if(sub[i]=='(')                   {                            left=i;                            counter++;                            break;                   }         for(i=left+1;sub[i];i++)         {                   if(sub[i]=='(')                            counter++;                   else if(sub[i]==')')                            counter--;                   if(counter==0)                   {                            right=i;                            break;                   }         }         s1=sub.substr(0,left);         sp=sub.substr(left+1,right-left-1);         s2=stringtoarr(trims(sub.substr(left+1,right-left-1)));         s3=trims(sub.substr(right+1));    ss=s1+s2+s3;         return ss;}  voidcalcation(string &str1){    int stTe;         if((stTe=Test(str1))<=0)         {                   cout<<"输入字符串有误,请重新输入!!!"<<endl;            return;         }         string sk=trims(str1);         string ssk=stringtoarr(sk);         cout<<ssk<<endl;         cout<<"--------------------"<<endl;   } intmain(){   string input_str;   int p=1;   int tsTest;   //string tss;   while(1)   {            cout<<"请输入表达式(退出请输入小写exit):"<<endl;        cin>>input_str;                   cout<<endl;       if(input_str.compare("exit")==0)            break;        if((tsTest=Test(input_str))==1)                   {                            calcation(input_str);            //tss=trims(input_str);            //cout<<stringtoarr(tss)<<endl;                   }         }cout<<"Close this calculation!"<<endl;return 0;}