C++實現支持浮點(x.x)的四則運算(帶括號)

思路:首先利用棧A把四則運算的字符串從中序表達式轉換成後序表達式;然後對後序表達式,如果是數字則保存到另一個棧B中,如果是運算符(+,-,*,/)就從棧B中依次獲取棧頂兩個操作數進行運算,運算結果再壓棧B,如此反覆,最終棧B中最後的值就是運算結果。

#define MAX_LENGTH  500

class Data
{
public:
    double num;
    char op;
};

class FourArithmeticOP
{
private:
    Stack<double> numStack;   //進行四則運算時,保存後序表達式中的操作數
    Stack<char> opStack;         //保存中序表達式轉換成後序表達式過程中的操作符
    int InStackPriority(char op);   //進入棧內後的優先級
    int NormalPriority(char op);    //普通表達式中的優先級
public:
    Data post[MAX_LENGTH];    //保存後序表達式
    int postLength;                     //後序表達式數組的實際長度
    void InorderToPostorder(char *cExp);  //把中序表達式轉換成後序表達式
    double Calculate();                //進行四則運算
};

//對四則運算符,棧內優先級提升,'('的棧內優先級應該比所有的操作符都小,')'的棧內優先級應該最大
//+-的優先級一致,*/的優先級一致
int FourArithmeticOP::InStackPriority(char op)
{
    int priority;
    switch (op)
    {
    case '+' : priority = 3;
        break;
    case '-' : priority = 3;
        break;
    case '*' : priority = 5;
        break;
    case '/' : priority = 5;
        break;
    case '(' : priority = 1;
        break;
    case ')' : priority = 10;
        break;
    default:  priority = 0;
        break;
    }
    return priority;
}

int FourArithmeticOP::NormalPriority(char op)
{
    int priority;
    switch (op)
    {
    case '+' : priority = 2;
        break;
    case '-' : priority = 2;
        break;
    case '*' : priority = 4;
        break;
    case '/' : priority = 4;
        break;
    case '(' : priority = 10;
        break;
    case ')' : priority = 1;
        break;
    default: priority = 0;
        break;
    }
    return priority;
}

void FourArithmeticOP::InorderToPostorder(char *cExp)
{
    char num[10];

    //把字符串中的數字和操作符(+-*/)放入後序表達式
    opStack.makeEmpty();

    //加入一個優先級最低的特殊字符,使opStack不爲空
    opStack.push('&');
    
    int index = 0;
    postLength = 0;
    while (cExp[index] != '\0')
    {
        if (cExp[index] == '+' || cExp[index] == '-' || cExp[index] == '*' || cExp[index] == '/' || cExp[index] == '(')
        {
            //優先級高於當前操作符的棧內操作符出棧
            while (NormalPriority(cExp[index]) < InStackPriority(opStack.getTop()))
            {
                post[postLength++].op = opStack.pop();
            }
            opStack.push(cExp[index]);
        }
        else if (cExp[index] == ')')
        {
            //一直退棧到'('
            while (opStack.getTop() != '(') 
            {
                post[postLength++].op = opStack.pop();
            }

            // '(' 出棧
            opStack.pop();
        }
        else if (cExp[index] >= '0' && cExp[index] <= '9')
        {
            //數字
            int j = 0;
            memset(num, 0, 10);
            while (cExp[index] >= '0' && cExp[index] <= '9')
            {
                num[j++] = cExp[index++];
            }
            index--;

            post[postLength].num = atof(num);
            post[postLength].op = '&';
            postLength++;
        }
        else
        {
            //非法字符,不處理
        }
        index++;
    }

    while (opStack.getTop() != '&')
     {
         post[postLength++].op = opStack.pop();
     }

     // '&' 出棧
     opStack.pop();
}

//根據後序表達式進行四則運算
double FourArithmeticOP::Calculate()
{
    double left, right;

    numStack.makeEmpty();

    for (int i = 0; i < postLength; i++)
    {
        if (post[i].op == '&')
        {
            // 數字
            numStack.push(post[i].num);
        }
        else
        {
            //操作符,取出兩個數字進行運算
            right = numStack.pop();
            left = numStack.pop();
            switch (post[i].op)
            {
            case '+' : numStack.push(left + right);
                break;
            case '-' : numStack.push(left - right);
                break;
            case '*' : numStack.push(left * right);
                break;
            case '/' : numStack.push(left / right);
                break;
            }
        }
    }

    return numStack.pop();
}
以上內容轉載自 http://blog.163.com/wmk_2000_ren/blog/static/138846192201031211285589/

以下爲本人的代碼,其中計算優先級的部分借用了上述的代碼。

所有操作都封裝到了一個類中

#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <vector>
#include <list>
#include <stack>
#include <queue>

using namespace std;

typedef struct{
    double operand;
    char opt;
}PostNode;

class FourArithmeticOP
{
private:
    const char NO_OPERATOR = 0x00;

    stack< char , list<char> > OpStack;
    queue< PostNode , list<PostNode> > PostStr;
    stack< double , list<double> > OperandStack;


public:
    FourArithmeticOP() {
        OpStack.push('#');
    }

    ~FourArithmeticOP() {

    }

    int IsNumOrDot(char chra);
    int IsOperator(char chra);
    int NormalPriority(char opt);
    int StackPriority(char opt);

    int InorderToPost(char *cExp);
    void ShowPostStr();
    double Calculate();
};


<span style="font-size:18px;">int FourArithmeticOP::IsNumOrDot(char chra)
{
    if( (chra >= '0' && chra <= '9') || chra == '.' )
        return 1;
    return 0;
}

int FourArithmeticOP::IsOperator(char chra)
{
    if(chra == '+' || chra == '-' ||
            chra == '*' || chra =='/' ||
            chra =='(' || chra == ')')
        return 1;
    return 0;
}

int FourArithmeticOP::NormalPriority(char opt)
{
    int priority;
    switch (opt)
    {
    case '+' : priority = 2;
        break;
    case '-' : priority = 2;
        break;
    case '*' : priority = 4;
        break;
    case '/' : priority = 4;
        break;
    case '(' : priority = 10;
        break;
    case ')' : priority = 1;
        break;
    default: priority = 0;
        break;
    }
    return priority;
}
//相同運算符,在棧中優先級更高
int FourArithmeticOP::StackPriority(char opt)
{
    int priority;
    switch (opt)
    {
    case '+' : priority = 3;
        break;
    case '-' : priority = 3;
        break;
    case '*' : priority = 5;
        break;
    case '/' : priority = 5;
        break;
    case '(' : priority = 1;
        break;
    case ')' : priority = 10;
        break;
    default:  priority = 0;
        break;
    }
    return priority;
}

int FourArithmeticOP::InorderToPost(char *cExp)
{
    string NumStr;
    //    double num;
    PostNode node;

    int i = 0;
    while(i < strlen(cExp)) {
        NumStr.clear();
        while(IsNumOrDot(cExp[i])) {
            NumStr += cExp[i];
            i++;
        }//get int or float
        if(!NumStr.empty()) {
            if('.' == NumStr.at(NumStr.length() - 1) ||
                    '.' == NumStr.at(0))
            {
                cout << "valid float : " << NumStr << endl;
                return 0;
            }
            node.operand = atof(NumStr.c_str());
            node.opt = NO_OPERATOR;
            PostStr.push(node);
        }
        else if(IsOperator(cExp[i])) {
            if(')' == cExp[i]) {</span>
<span style="font-size:18px;"><span style="white-space:pre">		</span>//遇到 ) 則 一直彈出直到 (
                while('(' != OpStack.top()) {
                    if('#' == OpStack.top()) {
                        cout << "parenthesis error" << endl;
                        return 0;
                    }
                    //pop out pair parenthesis
                    node.opt = OpStack.top();
                    PostStr.push(node);
                    OpStack.pop();
                }
                OpStack.pop(); //pop out '('
                i++;
                continue;
            }
            while(NormalPriority(cExp[i]) <= StackPriority(OpStack.top()))
            {
                node.opt = OpStack.top();
                PostStr.push(node);
                OpStack.pop();
            }
            OpStack.push(cExp[i]);
            i++;
        }
        else {
            cout << "valid operator : " << cExp[i] << endl;
            return 0;
        }
    }
    while('#' != OpStack.top()) {
        node.opt = OpStack.top();
        PostStr.push(node);
        OpStack.pop();
    }
    return 1;
}

double FourArithmeticOP::Calculate()
{
    PostNode node;
    double operand_1;
    double operand_2;
    char Operator;
    while(!PostStr.empty()) {
        Operator = PostStr.front().opt;
        //operand
        if(NO_OPERATOR == Operator) {
            operand_1 = PostStr.front().operand;
            OperandStack.push(operand_1);
            //            Operator = PostStr.front().opt;
        }
        else {
            //handle operator
            operand_2 = OperandStack.top();
            OperandStack.pop();
            operand_1 = OperandStack.top();
            OperandStack.pop();
            switch(Operator){
            case '+' : OperandStack.push(operand_1 + operand_2);
                break;
            case '-' : OperandStack.push(operand_1 - operand_2);
                break;
            case '*' : OperandStack.push(operand_1 * operand_2);
                break;
            case '/' :
                if(0 == operand_2) {
                    cout << "operand_2 = 0 while /" << endl;
                    return 0;
                }
                else {
                    OperandStack.push(operand_1 / operand_2);
                }
            }
        }
        PostStr.pop();
    }
    double res = OperandStack.top();
    OperandStack.pop();
    return res;
}</span>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章