计算2*3+(2*(5+6)*3)/2+4*6的值

代码弊端:

1.初始公式串的数值只能是0-9. 大于10的数字会有问题,可以改造myCopy函数

2. 计算顺序是从左到右。 比如2*3*4是先算的2*3 再算的rusult*4. 貌似c语言是从又到左的计算顺序

#include<iostream>
#include<iomanip>
#include<vector>
#include<algorithm>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;


bool isOper(char val)
{
    return ((val == '+') || (val == '-') ||(val == '*') || (val == '/') ||(val == '(') || (val == ')'));
}

//把char*字符串拷贝到vector中
void myCopy(vector<char>& container, char* v)
{
    while(*v != 0)
    {
        if (isOper(*v))
        {
            container.push_back(*v);
        }
        else
        {
            container.push_back(*v  - '0');
        }
        v++;
    }
}

void prtVecs(const vector<char>& values, const vector<int>& pris)
{
    //打印权重串
    for(auto pri : pris)
    {
        cout << " " << pri;
    }
    cout << endl;
    //打印公式串
    for(auto val : values)
    {
        if (isOper(val))
        {
            cout << " " << val;
        }
        else
        {
            cout << " " << (int)val;
        }
    }
    cout << endl;
}

void prtVecs(const vector<char>& values)
{
    //打印公式串
    for(auto val : values)
    {
        if (isOper(val))
        {
            cout << " " << val;
        }
        else
        {
            cout << " " << (int)val;
        }
    }
    cout << endl;
}

//加减乘除计算
int realCal(int first, char oper, int second)
{
    if (oper == '+') return first + second;
    if (oper == '-') return first - second;
    if (oper == '*') return first * second;
    if (oper == '/') return first / second;
    return -1;
}

/*权重计算:
数字权重固定是0,()权重固定是-1;
加减的基础权重是1 乘除的基础权重是2 ;
()括号控制附加权重0, (:附加权重+2 ):附加权重-2
[之所以选择附加权重为2举例: 2*(2+3)中要先算加法. 加的基础权重1+附加权重2得到3;乘的基础权重2+附加权重0得到2.所以会先算加法]
加减乘除的最终权重为 他的基础权重+当前附加权重*/

//values公式串, pris公式串对应的权重串[in out]
int calPri(const vector<char>& values, vector<int>& pris)
{
    int basePri = 0; //附加权重
    for(int i = 0; i < values.size(); ++i)
    {
        if (!isOper(values[i]))
        {
            pris[i]  = 0;
        }

        if (values[i] == '(')
        {
            basePri+=2;
            pris[i] = -1;
        }

        if (values[i] == ')')
        {
            basePri-=2;
            pris[i] = -1;
        }

        if ((values[i] == '+') || (values[i] == '-'))
        {
            pris[i] = 1 + basePri;
        }

        if ((values[i] == '*') || (values[i] == '/'))
        {
            pris[i] = 2 + basePri;
        }
    }
}

//移除公式串和权重串中的括号字符
void removeParentheses(vector<char>& values, vector<int>& pris)
{
    for(int i = values.size(); i >= 0; --i)
    {
        if ((values[i] == '(') || (values[i] == ')'))
        {
            values.erase(values.begin()+i);
            pris.erase(pris.begin()+i);
        }
    }
}
/*获取可以计算的权重符的位置:
 如果左边操作符的权重>= 右边操作符的权重,那么左边操作符的左右数据可以进行计算
 如果左边操作符的权重< 右边操作符的权重,那么需要右边操作符和它的右边操作符进行比较。
*/
int getCalPos(const vector<int>& pris)
{
    //pris[0]是左数字, pris[1]是操作符  pris[2]是右数字
    for(int i = 1; i < pris.size(); i+=2)
    {
        if(i+2 < pris.size())
        {
             if (pris[i] >= pris[i+2]) //如果左操作符的权重 >= 右操作符的权重,那么此左操作符可以计算
             {
                 return i;
             }
        }
    }

    return pris.size() - 2;
}


void calResult(vector<char>& values, vector<int>& pris)
{
    while(values.size() != 1)
    {
        //获取可以计算的操作符的位置,并进行左右数字和操作符的计算
        int pos = getCalPos(pris);
        int result = realCal(values[pos-1], values[pos], values[pos+1]);

        //当左数字,操作符,右数字计算完后,删掉操作符和右数组的位置,左数字的位置改成计算结果。然后继续计算。
        //举例2*3+4 计算2*3得出6,删除*这个位置,3这个位置,2这个位置改成6.这样公式变成6+4.下次循环继续计算6+4
        values.erase(values.begin()+pos+1);
        pris.erase(pris.begin()+pos+1);

        values.erase(values.begin()+pos);
        pris.erase(pris.begin()+pos);

        values[pos-1] = result;;
        prtVecs(values);
    }
}

int main()
{
    //原始字符串
    char data[]="2*3+(2*(5+6)*3)/2+4*6";
    vector<char> values;
    myCopy(values, data);
    cout << "origin:"; prtVecs(values);
   // prtVecs(values, pris);
    //计算原始字符串的权重
    vector<int> pris(values.size(),0);
    calPri(values, pris);
    //原始字符串去掉括号
    removeParentheses(values,pris);//把括号去掉
   // prtVecs(values, pris);

    calResult(values, pris);

    cout << "result:"; prtVecs(values);
}

 

posted @ 2020-11-24 21:57  哈哈不是嘎嘎  阅读(179)  评论(0编辑  收藏  举报