二元Operads示例程序

时间:2011-11-17 07:57:50

标签: c++ stack postfix-notation rpn

问题陈述: 编写一个C ++程序来评估后缀表达式。你的程序应该将postfix表达式作为输入,在堆栈的帮助下处理它,并在执行所需的计算后显示结果。

此程序仅允许使用以下二元运算符: +, - ,*,/,^ [加法,减法,乘法,除法,取幂]

如果在处理后缀表达式时发生某些错误,您的程序应显示有意义的消息,如: 错误:不允许除零 错误:__运算符需要两个操作数 错误:后缀表达式无效

帮助我,我的程序产生错误这是我的尝试:

#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>

#define MAX_SIZE 20

using namespace std;
template<class T>
class Stack
{
private:
    T item[MAX_SIZE];
    int top;
public:
    Stack()
    {
        top = -1;
    }

    void push(T data)
    {
        if(!this->is_full())
            item[++top] = data;
        else
        {
            cout<<"Stack Error"<<endl;
            exit(10);
        }
    }
    T pop()
    {
        if(!this->is_empty())
            return item[top--];
        else
        {
            cout<<"Stack is Empty"<<endl;
            exit(11);
        }
    }

    int size()
    {
        return top+1;
    }

    bool is_empty()
    {
        if(top==-1)
            return true;
        else
            return false;
    }

    bool is_full()
    {
        if(top==MAX_SIZE-1)
            return true;
        else
            return false;
    }

    void display()
    {
        for(int i=0; i<this->size(); i++)
        {
            cout<<item[i]<<" ";
        }
        cout<<endl;
    }
    T return_top()
    {
        return item[top];
    }
};

class Convert
{
private:
    bool num_flag;
    bool tow_digit_flag;
public:
    Convert();
    string return_with_bracket(string infix);
    void to_Postfix(string infix,char postfix[]);
    bool prcd(char op1, char op2);
    int isOperand(char op);
    int isOperator(char op);
    bool return_flag()
    {
        return num_flag;
    }
};

Convert::Convert()
{
    this->num_flag = false;
    this->tow_digit_flag = false;
}
string Convert::return_with_bracket(string infix)
{
    return("(" + infix + ")");
}

bool Convert::prcd(char op1, char op2)
{
    if((op1=='+' || op1=='-' || op1=='*' || op1=='/') && op2=='(' )
        return true;
    if(op1=='+' && op2=='+')
        return true;
    if(op1=='-' && op2=='-')
        return false;
    if(op1=='-' && op2=='+')
        return false;
    if(op1=='+' && op2=='-')
        return false;
    if(op1=='/' && op2=='/')
        return false;
    if(op1=='/' && (op2=='-' || op2=='+'))
        return true;
    if(op1=='*' && (op2=='+' || op2=='-'))
        return true;
    if((op1 == '-' || op1 == '+') && (op2 =='*' || op2 == '/'))
        return false;
    if((op1=='$' || op1 == '+') && (op2 =='*' || op2 == '/' || op2=='-'))
        return true;
    if((op1 == '-' || op1 == '+' || op1 =='*' || op1 == '/')&& op2=='^')
        return false;
    if(op1 == '^' && ( op2 == '+' || op2 =='*' || op2 == '/' || op2=='-'))
        return false;
}

int Convert::isOperand(char op)
{
    return(op>= '0' && op <= '9');
}

int Convert::isOperator(char op)
{
    return(op=='+' || op=='-' || op == '/' || op=='*' || op=='^');
}

void Convert::to_Postfix(string infix, char postfix[])
{
    int position, outpos=0;
    char c;
    int count = 0;
    char temp;
    char stacktop ;
    Stack<char> stack;
    for(position = 0; (c = infix[position])!='\0'; position++)
    {
        if(this->isOperand)
        {
            postfix[outpos++] = c;
            this->num_flag = true;
            count++;
            if(count>=2)
            {
                this->tow_digit_flag = true;
            }
        }
        else if(this->isOperator©)
        {
            count = 0;
            if(isOperator(infix[position]) && isOperator(infix[position+1]))
            {
                cout<<"\aMissing argument in between "<<infix[position]<<" and "<<infix[position+1]
                    <<" in column "<< position+1<<endl;
                exit(9);
            }
            if(this->prcd(c, stacktop))
            {
                stacktop=stack.return_top();
                stack.push©;
                stacktop = c;
            }
            else
            {
                while(true)
                {
                    temp = stack.pop();
                    postfix[outpos++] =temp;
                    stacktop = stack.return_top();
                    if(prcd(c, stacktop) || stacktop=='(')
                        break;
                }
                stack.push©;
                stacktop = stack.return_top();
            }
        }
        else if(c=='(')
        {
            count = 0;
            stack.push©;
            stacktop = stack.return_top();
        }
        else if(c==')')
        {
            count = 0;
            while(1)
            {
                if(stack.size()==0)
                {
                    cout<<"Warning!! Number of ')' is greater than '('" <<endl;
                    exit(2);
                }
                temp = stack.pop();
                if(temp!='(')
                {
                    postfix[outpos++] = temp;
                }
                else
                {
                    break;
                }
            }
            stacktop =stack.return_top();
        }
        else
        {
            cout<<"Invalid input";
            exit(3);
        }
        if(infix[position]==')' && infix[position+1]=='(')
        {
            stack.push('*');
            stacktop = stack.return_top();
        }
    }
    if(stack.size()!=0)
    {
        cout<<"Warning!!Number of '(' is greater than ')'"<<endl;
        // exit(6);
    }
    if(!this->return_flag())
    {
        cout<<"You must Enter Numeric value for calculation"<<endl;
        cout<<"This program cannot perform operations on variables";
        exit(5);
    }
    if(this->tow_digit_flag)
    {
        cout<<"Sory! Althoug u may have entered right string"<<endl;
        cout<<"this program is only for single digit operation"<<endl;
        exit(8);
    }
    postfix[outpos] = '\0';
}

class Evaluate
{
public:
    double eval(char expr[], Convert &Wink;
                double oper(int symb, double op1, double op2);
};
double Evaluate::oper(int symb, double op1, double op2)
{
    switch(symb)
    {
    case '+':
        return (op1 + op2);
    case '-':
        return (op1 - op2);
    case '*':
        return (op1 * op2);
    case '/':
        return (op1 / op2);
    case '^':
        return (pow(op1, op2));
    }
}
double Evaluate::eval(char expr[],Convert &convert)
{
    int c, position;
    char temp1;
    int count = 0;
    double opnd1, opnd2, value;
    Stack<double> stack;
    for(position = 0; (c = expr[position])!='\0'; position++)
    {
        if(convert.isOperand©)
        {
            temp1 = double(c-'0');
            stack.push(temp1);
        }
        else
        {
            opnd2 = stack.pop();
            if(stack.size()==0)
            {
                cout<<"This program cannot process unary operation";
                exit(1);
            }
            opnd1 = stack.pop();
            value = oper(c, opnd1, opnd2);
            stack.push(value);
        }
    }
    if(stack.size()>=2)
    {
        cout<<"Sory! this program cannot calculate this"<<endl;
        cout<<"Enter +, *, /, - or ^ between bracket"<<endl;
        exit(4);
    }

    return (stack.pop());
}
int main()
{
    Convert convert;
    Evaluate evaluate;
    string bracketted_infix;
    char infix[50], postfix[50];
    char choice;
    while(1)
    {
        cout<<"Enter operation: ";
        cin>>infix;
        cout<<endl;
        cout<<"Entered operation: "<<infix<<endl;
        bracketted_infix = convert.return_with_bracket(infix);
        convert.to_Postfix(bracketted_infix, postfix);
        cout<<"Equivalent Postfix operation: "<<postfix<<endl;
        cout<<"RESULT: ";
        cout<<evaluate.eval(postfix, convert);
        cout<<"\nCalculate another operation?(y/n) ";
        cin>>choice;
        cout<<endl;
        if(choice=='n')
            break;
    }
    return 0;
}

2 个答案:

答案 0 :(得分:2)

要实际编译,您需要修复两个语法错误;

在第154行,你正在调用一个没有参数的方法, 但是这个方法的唯一声明需要1个参数。

if (this->isOperand) {

我相信你可能意味着:

if (this->isOperand(c)) {

同样在第255行,分号前面有一个缺少的括号:

double eval(char expr[], Convert &Wink;

当我实际运行你的代码时,它在运行时失败,VS2010给出错误“字符串下标超出范围”。

如果您还没有,我建议在开发时使用一个好的IDE(如Visual C ++);语法着色和对动态调试的支持(即断点和监视)对调试这样的程序非常有帮助。

答案 1 :(得分:1)

这是最终的解决方案

#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>

#define MAX_SIZE 20

using namespace std;
template<class T>
class Stack
{
private:
    T item[MAX_SIZE];
    int top;
public:
    Stack()
    {
        top = -1;
    }

    void push(T data)
    {
        if(!this->is_full())
            item[++top] = data;
        else
        {
            cout<<"Stack Error"<<endl;
            exit(10);
        }
    }
    T pop()
    {
        if(!this->is_empty())
            return item[top--];
        else
        {
            cout<<"Stack is Empty"<<endl;
            exit(11);
        }
    }

    int size()
    {
        return top+1;
    }

    bool is_empty()
    {
        if(top==-1)
            return true;
        else
            return false;
    }

    bool is_full()
    {
        if(top==MAX_SIZE-1)
            return true;
        else
            return false;
    }

    void display()
    {
        for(int i=0; i<this->size(); i++)
        {
            cout<<item[i]<<" ";
        }
        cout<<endl;
    }
    T return_top()
    {
        return item[top];
    }
};

class Convert
{
private:
    bool num_flag;
    bool tow_digit_flag;
public:
    Convert();
    string return_with_bracket(string infix);
    void to_Postfix(string infix,char postfix[]);
    bool prcd(char op1, char op2);
    int isOperand(char op);
    int isOperator(char op);
    bool return_flag()
    {
        return num_flag;
    }
};

Convert::Convert()
{
    this->num_flag = false;
    this->tow_digit_flag = false;
}
string Convert::return_with_bracket(string infix)
{
    return("(" + infix + ")");
}

bool Convert::prcd(char op1, char op2)
{
    if((op1=='+' || op1=='-' || op1=='*' || op1=='/') && op2=='(' )
        return true;
    if(op1=='+' && op2=='+')
        return true;
    if(op1=='-' && op2=='-')
        return false;
    if(op1=='-' && op2=='+')
        return false;
    if(op1=='+' && op2=='-')
        return false;
    if(op1=='/' && op2=='/')
        return false;
    if(op1=='/' && (op2=='-' || op2=='+'))
        return true;
    if(op1=='*' && (op2=='+' || op2=='-'))
        return true;
    if((op1 == '-' || op1 == '+') && (op2 =='*' || op2 == '/'))
        return false;
    if((op1=='$' || op1 == '+') && (op2 =='*' || op2 == '/' || op2=='-'))
        return true;
    if((op1 == '-' || op1 == '+' || op1 =='*' || op1 == '/')&& op2=='^')
        return false;
    if(op1 == '^' && ( op2 == '+' || op2 =='*' || op2 == '/' || op2=='-'))
        return false;
}

int Convert::isOperand(char op)
{
    return(op>= '0' && op <= '9');
}

int Convert::isOperator(char op)
{
    return(op=='+' || op=='-' || op == '/' || op=='*' || op=='^');
}

void Convert::to_Postfix(string infix, char postfix[])
{
    int position, outpos=0;
    char c;
    int count = 0;
    char temp;
    char stacktop ;
    Stack<char> stack;
    for(position = 0; (c = infix[position])!='\0'; position++)
    {
     if (this->isOperand(c)) 

        {
            postfix[outpos++] = c;
            this->num_flag = true;
            count++;
            if(count>=2)
            {
                this->tow_digit_flag = true;
            }
        }
        else if(this->isOperator(c))
        {
            count = 0;
            if(isOperator(infix[position]) && isOperator(infix[position+1]))
            {
                cout<<"\aMissing argument in between "<<infix[position]<<" and "<<infix[position+1]
                    <<" in column "<< position+1<<endl;
                exit(9);
            }
            if(this->prcd(c, stacktop))
            {
                stacktop=stack.return_top();
                stack.push(c);
                stacktop = c;
            }
            else
            {
                while(true)
                {
                    temp = stack.pop();
                    postfix[outpos++] =temp;
                    stacktop = stack.return_top();
                    if(prcd(c, stacktop) || stacktop=='(')
                        break;
                }
                stack.push(c);
                stacktop = stack.return_top();
            }
        }
        else if(c=='(')
        {
            count = 0;
            stack.push(c);
            stacktop = stack.return_top();
        }
        else if(c==')')
        {
            count = 0;
            while(1)
            {
                if(stack.size()==0)
                {
                    cout<<"Warning!! Number of ')' is greater than '('" <<endl;
                    exit(2);
                }
                temp = stack.pop();
                if(temp!='(')
                {
                    postfix[outpos++] = temp;
                }
                else
                {
                    break;
                }
            }
            stacktop =stack.return_top();
        }
        else
        {
            cout<<"Invalid input";
            exit(3);
        }
        if(infix[position]==')' && infix[position+1]=='(')
        {
            stack.push('*');
            stacktop = stack.return_top();
        }
    }
    if(stack.size()!=0)
    {
        cout<<"Warning!!Number of '(' is greater than ')'"<<endl;
        // exit(6);
    }
    if(!this->return_flag())
    {
        cout<<"You must Enter Numeric value for calculation"<<endl;
        cout<<"This program cannot perform operations on variables";
        exit(5);
    }
    if(this->tow_digit_flag)
    {
        cout<<"Sory! Althoug u may have entered right string"<<endl;
        cout<<"this program is only for single digit operation"<<endl;
        exit(8);
    }
    postfix[outpos] = '\0';
}

class Evaluate
{
public:
    double eval(char expr[], Convert &Wink);
                double oper(int symb, double op1, double op2);
};
double Evaluate::oper(int symb, double op1, double op2)
{
    switch(symb)
    {
    case '+':
        return (op1 + op2);
    case '-':
        return (op1 - op2);
    case '*':
        return (op1 * op2);
    case '/':
        return (op1 / op2);
    case '^':
        return (pow(op1, op2));
    }
}
double Evaluate::eval(char expr[],Convert &convert)
{
    int c, position;
    char temp1;
    int count = 0;
    double opnd1, opnd2, value;
    Stack<double> stack;
    for(position = 0; (c = expr[position])!='\0'; position++)
    {
        if(convert.isOperand(c))
        {
            temp1 = char(c-'0');
            stack.push(temp1);
        }
        else
        {
            opnd2 = stack.pop();
            if(stack.size()==0)
            {
                cout<<"This program cannot process unary operation";
                exit(1);
            }
            opnd1 = stack.pop();
            value = oper(c, opnd1, opnd2);
            stack.push(value);
        }
    }
    if(stack.size()>=2)
    {
        cout<<"Sory! this program cannot calculate this"<<endl;
        cout<<"Enter +, *, /, - or ^ between bracket"<<endl;
        exit(4);
    }

    return (stack.pop());
}
int main()
{
    Convert convert;
    Evaluate evaluate;
    string bracketted_infix;
    char infix[50], postfix[50];
    char choice;
    while(1)
    {
        cout<<"Enter operation: ";
        cin>>infix;
        cout<<endl;
        cout<<"Entered operation: "<<infix<<endl;
        bracketted_infix = convert.return_with_bracket(infix);
        convert.to_Postfix(bracketted_infix, postfix);
        cout<<"Equivalent Postfix operation: "<<postfix<<endl;
        cout<<"RESULT: ";
        cout<<evaluate.eval(postfix, convert);
        cout<<"\nCalculate another operation?(y/n) ";
        cin>>choice;
        cout<<endl;
        if(choice=='n')
            break;
    }
    return 0;
}