C++實現簡易計算器

qq_38515771發表於2019-04-22

 

#include <iostream>
#include <string>
#include <stack>
//#define fin cin
//#define fo
using namespace std;
bool isOperator(char x)
{
    if(x=='('||x==')'||x=='+'||x=='-'||x=='*'||x=='/')
        return true;
    else
        return false;
}
int getPriority(char x)
{
    if(x=='+'||x=='-')
        return 1;
    if(x=='*'||x=='/')
        return 2;
    if(x=='(')
        return 0;
}
bool isBracket(char x)
{
    if(x=='('||x==')')
        return true;
    else
        return false;
}
int doOperate(int d1,int d2,char t)
{
    //cout<<d1<<" "<<t<<" "<<d2<<endl;
    if(t=='+')
        return (d1+d2);
    if(t=='-')
        return (d1-d2);
    if(t=='*')
        return (d1*d2);
    if(t=='/')
        return (d1/d2);


}
int main()
{
    stack<int> Q;
    stack<char> S;
    string str;
    cin>>str;
    char x;
    int opnum;
    string temp="";//臨時存放運算元
    int d2,d1;
    char t;
    //cout<<str.size()<<endl;
    //cout<<str[str.size()-1]<<endl;
    for(int i=0;i<str.size();i++)
    {
        x=str[i];
        //cout<<x<<endl;
    }
    for(int i=0;i<str.size();i++)
    {
        x=str[i];
        //cout<<x<<endl;
        //如果是運算元

        if(x>=48&&x<=57)
        {
            temp.append(1,x);
        }
        if(isOperator(x))
        {
            if(temp!="")
            {
                opnum=stoi(temp);
                //cout<<opnum<<endl;
                Q.push(opnum);
                temp="";
            }
            if(S.empty())
                S.push(x);
            else{//棧中有一個(,然後壓入一個+,由於(的優先順序未知而出錯
                if(x=='('||
                        ((!isBracket(x))&&
                         (getPriority(x)>getPriority(S.top()))))
                    S.push(x);
                else
                    if(x==')')
                    {
                        while(S.top()!='(')
                        {
                            d2=Q.top();
                            Q.pop();
                            d1=Q.top();
                            Q.pop();
                            t=S.top();
                            S.pop();
                            Q.push(doOperate(d1,d2,t));
                        }
                        S.pop();//彈出)
                    }
                    else
                    {
                        while(!S.empty()&&
                              ((getPriority(S.top())>getPriority(x))||(getPriority(x)==getPriority(S.top()))))
                        {
                            d2=Q.top();
                            Q.pop();
                            d1=Q.top();
                            Q.pop();
                            t=S.top();
                            S.pop();
                            Q.push(doOperate(d1,d2,t));
                        }
                        S.push(x);
                    }
            }
        }
        if(!isOperator(x)&&i==str.size()-1)
            Q.push(stoi(temp));

    }
    while(!S.empty())
    {
        d2=Q.top();
        Q.pop();
        d1=Q.top();
        Q.pop();
        t=S.top();
        S.pop();
        Q.push(doOperate(d1,d2,t));
    }
    cout<<Q.top();
    /*
    if(Q.size()==2)
    {
        d2=Q.top();
        Q.pop();
        d1=Q.top();
        Q.pop();
        t=S.top();
        S.pop();
        Q.push(doOperate(d1,d2,t));

    }
    */
    return 0;
}

實現思想:一邊中綴轉字尾一邊計算,這樣只需要一次掃描就可以計算完畢,計算複雜度為O(n),計算步驟如下

處理某個x

  1. 判斷是運算元還是運算子
  2. 處理字元
  • 如果是運算元,壓入運算元棧Q 
  • 如果是運算子,分為如下情況討論
  1. 如果運算子棧S為空,直接將x壓入S棧

  2. 如果運算子棧S不空,且x是'('或者x的優先順序大於棧頂元素優先順序,x壓棧

  3. 如果S不空,且x優先順序小於等於棧頂元素,彈棧處理至S為空或者x優先順序大於棧頂 

  4. 如果x為')',處理至'(' 

當處理完所有字元之後,彈棧處理直到S為空,Q的棧頂即為所求

彈棧處理:取Q的兩個元素,目前棧頂為d2,將d2彈出之後的棧頂為d1,設操作符棧頂為t,則處理過程為計算 d1 t d2,然後後將d1 t d2壓棧,此過程中d1,d2, t都已經彈棧了

實現細節:

  1. 如何擷取運算元?兩個操作符(或者頭與操作符,操作符與尾)之間的為運算元
  2.  優先順序的判定?此處應該注意'(',因為與棧頂優先順序比較,如果不給'('設定一個優先順序在判斷時會產生錯誤,可以將(優先順序設定為最低。
  3. 短路與和短路或?會不會產生因為壓入一個'('就將之前的都計算的錯誤呢?因為上面的設定?不會的,因為在下面這句程式碼裡,我們會首先判斷是不是括號,如果滿足條件,不會計算||之後的條件,因為a||b這樣的判斷,如果a為真,不管b是否為真該語句都是真,所以不會判斷b條件,從而不會產生錯誤
if(x=='('||
                        ((!isBracket(x))&&
                         (getPriority(x)>getPriority(S.top()))))
                    S.push(x);



while(!S.empty()&&
                              ((getPriority(S.top())>getPriority(x))||(getPriority(x)==getPriority(S.top()))))

 

 

 

 

相關文章