字符串处理之简单计算器

这道题分解出来,首先是分离运算符和数字,然后考虑运算顺序求结果。

1.分离运算符和数字

1)由题意,输入是浮点数,用到atof,如下。

头文件:#include <stdlib.h>

定义函数:double atof(const char *nptr);

函数说明:atof()会扫描参数nptr 字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时('\0')才结束转换,并将结果返回参数nptr 字符串可包含正负号、小数点或E(e)来表示指数部分,如123. 456 或123e-2。

注意加粗划线字体说明的,atof遇到开头空格跳过,结尾空格结束,并会读入正负。为了统一,我把字符串的运算符读取并改成空格。

2)在处理的时候有一种情况,比如  -1*-1*-1 就是乘除号两边有负数,这时候减号保留,只读出乘除。

2.运算顺序

1)方法:在前面,我把浮点数存数组,并且优先扫乘除,在乘除中是从左到右运算,所以遵循数组中相邻两数做乘除,结果保留在右,左边赋值0.

2)这时候会出现两种符号的存在情况,一种是跟在乘除前面,由于按右边存值,所以直接扫后把右边(i+1)变号就可以:

                                                        二是正常的减,把对应位(i)变号。

扫描二维码关注公众号,回复: 1072884 查看本文章

3)这时你可能会问,+号呢?经过前面的处理,只需求出处理后的数组和就可得到计算结果!

#include<bits/stdc++.h>
#define N 200
using namespace std;
double DoingCal(char Calcu[],double Num[],int cnt1,int cnt2)
{
    double result=0;
    for(int i=1;i<=cnt1;i++)
    {
        if(Calcu[i]=='*'||Calcu[i]=='/')      //依据运算顺序,先处理乘除
        {
            if(Calcu[i]=='*')
                Num[i+1]=Num[i]*Num[i+1];
            else
                Num[i+1]=Num[i]/Num[i+1];
            Num[i]=0;                        //靠右算,运算结果保留在i+1,i处赋0
            if(Calcu[i-1]=='-')
                Num[i+1]*=-1;            //处理乘除符号的前一个减号,是减号对应的计算结果变号
        }
        /*for(int i=1;i<=cnt2;i++)
            cout<<Num[i]<<" ";
        cout<<endl;*/
    }
    for(int i=1;i<=cnt1;i++)
    {
        if(Calcu[i]=='-'&&Calcu[i+1]!='/'&&Calcu[i+1]!='*') //处理后面没有乘除符号的减号,对应的数变号
            Num[i+1]*=-1;
        /*for(int i=1;i<=cnt2;i++)
            cout<<Num[i]<<" ";
        cout<<endl;*/
    }
    for(int i=1;i<=cnt1+1;i++)  //处理完的数组相加
        result+=Num[i];
    return result;     //返回计算结果
}
int main()
{
    char instructStr[N],Calcu[N];   //instructStr,存最初输入的计算指令(待加工);Calcu,存计算符号
    int t,i;
    double Num[N];                  //存分离出来的数
    cin>>t;                         //输入测试次数
    while(t--)
    {
        int cnt1=0;
        int cnt2=0;
        int flag=1;    //状态,1表示输入的第一个字符为数字,0为正or负号
        cin>>instructStr;
        if(instructStr[0]>'9'||instructStr[0]<'0')   //初加工,保证instructStr[0]是数字
        {
            flag=0;
            strcpy(instructStr,&instructStr[1]);
        }

        for(i=0;instructStr[i]!='\0';i++)    //运算符号录入
        {
            int flag1=1;
            if((instructStr[i]>'9'||instructStr[i]<'0')&&instructStr[i]!='.')   //该if防止“.”录入
            {
                if(instructStr[i]=='-'&&instructStr[i-1]==' ')    //为便于运算,乘或除号前面的减号忽略不录入,后面运算函数详细说明
                    flag1=0;
                if(flag1)
                {
                    Calcu[++cnt1]=instructStr[i];
                    instructStr[i]=' ';      //把运算符变为空格,因为atof遇符号停止转化。
                }
            }
        }
        /*cout<<instructStr<<endl;
        for(i=1;i<=cnt1;i++)
            cout<<Calcu[i]<<" ";
        cout<<endl;*/
        for(i=0;instructStr[i]!='\0';i++)      //字符转浮点,见对atof使用说明
        {
            if( (instructStr[i-1]==' '||!i) )   //如果读到空格或者开头,对后一位的数字(i=0是对开头)执行转浮点,遇到空格结束。
            {
                Num[++cnt2]=atof(&instructStr[i]);
                //cout<<Num[cnt2]<<endl;

            }
            /*for(j=i;;j++)
            {
                if(instructStr[j]==' '&&instructStr[j]=='\0')
                {
                    i=j-1;
                    break;
                }
            }*/
        }
        if(!flag)       //开头的符号被清,补上
            Num[1]*=-1;
        /*for(int i=1;i<=cnt2;i++)
            cout<<Num[i]<<" ";
        cout<<endl;*/
        cout<<fixed<<setprecision(2)<<DoingCal(Calcu,Num,cnt1,cnt2)<<endl;
    }
    return 0;
}
//
PS:这是本渣的第一篇博,在打完之后我发现其实代码里面很多处理比较鸡肋,但是好处是思路比较清晰,各位多指教!

猜你喜欢

转载自blog.csdn.net/szu_crayon/article/details/79084045