四则运算(带括号)、栈应用

程序小白,希望和大家多交流,共同学习

//使用两个栈,一个存储数字,一个存储运算符
//将给定的表达式(没有括号)变成后缀式,然后利用两个栈求出表达式的值
//为方便运算,先给定优先级'#'、'('、'+-'、'*/'、'^'
//所有的
#include<iostream>
#include<math.h>
using namespace std;

struct NodeDigit
{
    int data;
    NodeDigit *next;
};
typedef NodeDigit *DigitStack;

struct NodeOperator
{
    char data;
    NodeOperator *next;
};
typedef NodeOperator *OperatorStack;

//充分使用方法重用
//初始化
void init(DigitStack &ds);
void init(OperatorStack &os);
//进栈
void push(DigitStack &ds, int data);
void push(OperatorStack &os, char data);
//出栈
int pop(DigitStack &ds);
char pop(OperatorStack &os);
//判断为空
bool isEmpty(DigitStack ds);
bool isEmpty(OperatorStack os);
//判断满
bool isFull(DigitStack ds);
bool isFull(OperatorStack os);
//得到栈顶
int getTop(DigitStack ds);
char getTop(OperatorStack os);
//放回优先级
int priority(char ch);
//算后缀式,判断左多
int compute(DigitStack &ds, OperatorStack &os);
//锁定输入运算符
bool isOperator(char ch);

int main()
{
    DigitStack ds;
    OperatorStack os;
    init(ds);
    init(os);
    //错误状况:有空格,除数为零,非法字符输入,连续运算符输入,括号不匹配(左多右多)
    push(os, '#');
    char ch;
    char divide = '#';//记录除号,判断除数是否零
    bool op;//记录是否是运算符,判断两次输入是否都是运算符
    bool match = true;
    while (true)
    {
        if (!isOperator(ch = getchar()))
        {
            cout << "非法运算符 " << ch << endl;
            break;
        }

        if (ch == '=')//以'='作为截止符
        {
            while (getTop(os) != '#')
            {
                if (getTop(os) == '(')
                {
                    cout << "括号不匹配,左多\n";
                    break;
                }
                compute(ds, os);
            }
            if (getTop(os) != '(')
            {
                cout << pop(ds) << endl;
            }

            break;
        }

        if (ch == '/')//出栈可能会比较慢,直接将除号保存
        //由于初始化不是除号,所以下面的判断是对除号后紧接着数字的判断
        {
            divide = '/';
        }

        //输入的第一个字符是数字,就将字符推回输入流。
        //定义一个整型,用来读取一个完整的数字
        if (ch >= '0' && ch <= '9')
        {
            op = false;
            cin.putback(ch);
            int digit = 0;
            cin >> digit;
            if (divide == '/')
            {
                if (digit == 0)
                {
                    cout << "除数不能为零\n";
                    break;
                }
                else
                    divide = '#';
            }
            push(ds, digit);
        }

        else if (ch == '(')
        {
            push(os, ch);
        }

        else if (ch == ')')
        {
            while (getTop(os) != '(')
            {
                if (getTop(os) == '#')
                {
                    cout << "括号不匹配,右多\n";
                    match = false;
                    break;
                }
                compute(ds, os);
            }

            if (!match)
            {
                break;
            }
            pop(os);//将匹配的(抛出
        }

        else//不是字符那就是运算符,对于运算符,要么计算,要么入栈
            //排除括号的状况
        {
            if (op && ch != '(' && ch != ')')//先判断,那么判断的就是上一次的op状况
            {
                cout << "非法输入:连续两次输入运算符 " << ch << endl;
                break;
            }
            op = true;//再赋值,赋值的是这一次的状况
            //优先级较高者直接进栈
            //否则就计算
            //这是一个循环
            //最后将新的运算符入栈
            while (priority(ch) <= priority(getTop(os)))
            {
                compute(ds, os);
            }
            push(os, ch);
        }
    }
    return 0;
}

//初始化
void init(DigitStack &ds)
{
    //栈要封底
    ds = NULL;
}
void init(OperatorStack &os)
{
    os = NULL;
}
//进栈
void push(DigitStack &ds, int data)
{
    if (isFull(ds))
    {
        cout << "数字栈已满,无法进栈\n";
    }
    else
    {
        NodeDigit *newNode = new NodeDigit;
        newNode -> data = data;
        newNode -> next = ds;
        ds = newNode;
    }
}
void push(OperatorStack &os, char data)
{
    if (isFull(os))
    {
        cout << "运算符栈已满,无法进栈\n";
    }
    else
    {
        NodeOperator *newNode = new NodeOperator;
        newNode -> data = data;
        newNode -> next = os;
        os = newNode;
    }
}
//出栈
int pop(DigitStack &ds)
{
    if (isEmpty(ds))
    {
        cout << "数字栈已空,无法出栈\n";
        return 0;
    }
    NodeDigit *delosde = ds;
    int data = delosde -> data;
    ds = ds -> next;
    delete delosde;
    return data;
}
char pop(OperatorStack &os)
{
    if (isEmpty(os))
    {
        cout << "运算符栈已空,无法出栈\n";
        return ' ';
    }

    NodeOperator *delosde = os;
    char data = delosde -> data;
    os = os -> next;
    delete delosde;
    return data;
}
//判断为空
bool isEmpty(DigitStack ds)
{
    return ds == NULL;
}
bool isEmpty(OperatorStack os)
{
    return os == NULL;
}
//判断满
bool isFull(DigitStack ds)
{
    NodeDigit *newNode = new NodeDigit;
    if (newNode == NULL)
    {
        delete newNode;
        return true;
    }
    else
        return false;
}
bool isFull(OperatorStack os)
{
    NodeOperator *newNode = new NodeOperator;
    if (newNode == NULL)
    {
        delete newNode;
        return true;
    }
    else
        return false;
}
//得到栈顶
int getTop(DigitStack ds)
{
    if (isEmpty(ds))
    {
        cout << "数字栈已空,无栈顶数字\n";
        return 0;
    }
    return ds -> data;
}
char getTop(OperatorStack os)
{
    if (isEmpty(os))
    {
        cout << "运算符栈已空,无栈顶运算符\n";
        return ' ';
    }
    return os -> data;
}
//放回优先级
int priority(char ch)
{
    switch (ch)
    {
    case '#':
        return 0;
    case '(':
        return 1;
    case '+':
    case '-':
        return 2;
    case '*':
    case '/':
        return 3;
    case '^':
        return 4;
    }
}
//算后缀式,判断左多
int compute(DigitStack &ds, OperatorStack &os)
{
    int d2 = pop(ds);
    int d1 = pop(ds);
    char op = pop(os);
    double result;
    switch (op)
    {
    case '+':
        result = d1 + d2; break;
    case '-':
        result = d1 - d2; break;
    case '*':
        result = d1 * d2; break;
    case '/':
        result = d1 / d2; break;
    case '^':
        result = pow(d1, d2); break;
    }
    //cout << d1 << op << d2 << "=" << result <<endl;
    push(ds, result);
    return true;
}
//锁定输入运算符
bool isOperator(char ch)
{
    return (ch == '+' || ch == '-' || ch == '*' 
        || ch == '/' || ch == '^' || ch == '='
        || (ch >= '0' && ch <= '9') || ch == '('
        || ch == ')');
}

//2+5*6+7*9*10^2+6=
//2+5*6+7/0*10^2+6=
//2+5*6+7*10^2+6
//2+5*6+7**9*10^2+6=
//5*6+(7+8*6)+7^2-5=
//5*6+(7+8*6))+7^2-5=
//5*6+((7+8*6)+7^2-5=
//(5*6+(7+8*6))+7^2-5=

猜你喜欢

转载自blog.csdn.net/cheng_cuo_tuo/article/details/79954694