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

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

一、开发环境:

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;
}


  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值