算法 表达式求值

表达式求值中用到了两个栈,一个栈存放的是操作数,另一个栈存放的是操作符(运算符号和#),#可以让循环结束(#优先级最小),下面是各个操作符优先级的比较,其中θ1为opter(操作符)栈的栈顶,θ2位字符ch,x意为不可比较


步骤:

1.先初始化两个栈opval(操作数)栈,opter(操作符)栈

2.将起始符#压入opter栈中,以便后续循环中输入#能够结束循环

3.定义一个count变量,并将初值设为0,这个变量的作用是能够将多位数字字符转化为double型压入栈中

4.循环(opter栈为空退出),内有两部分,一部分为数字的存放,另一部分为操作符的比较和存放,以及运算

①第一部分中分两类,一类实现的是多位数字的存入,另一类实现个位数字或第一次进入栈的单个数字字符的存入,同时这里就可以体现出count的作用了,具体实现看代码

②第二部分中使用到了两个函数,一个是返回二维数组下标的函数,另一个是返回优先级比较结果的函数

按照上表的顺序返回下标的函数中各个符号在数组中的位置是+~1,-~2,*~3,/~4,(~5,)~6,#~7

注意在优先级比较函数中,要减一(下标是从0开始的)

根据比较出来的结果:

如果是>,则将opval栈顶元素以及栈顶前面的一个元素弹出栈,最后将结果两数的计算结果存入栈中

如果是<,则直接将运算符压入opter栈中,接着读取字符

如果是=,则将opter栈顶元素弹出,接着读取字符

代码:

#include <iostream>
#include <stack>
#include <cctype>
#include <cstdio>
#include <cstdlib>
using namespace std;

stack <char> opter; //存储操作符
stack <double> opval;   //存储操作数
//根据上表返回操作符的位置下标
int Index(char ch)
{
    int index = 0;
    switch(ch)
    {
        case '+':
            index = 1;
            break;
        case '-':
            index = 2;
            break;
        case '*':
            index = 3;
            break;
        case '/':
            index = 4;
            break;
        case '(':
            index = 5;
            break;
        case ')':
            index = 6;
            break;
        case '#':
            index = 7;
            break;
        default:
            break;
    }
    return index;
}
//比较运算符之间的优先级
char Compare(char ch1, char ch2)
{
    char compare[][7] = {
                            {'>', '>', '<', '<', '<', '>', '>'},    //x表示不能比较
                            {'>', '>', '<', '<', '<', '>', '>'},
                            {'>', '>', '>', '>', '<', '>', '>'},
                            {'>', '>', '>', '>', '<', '>', '>'},
                            {'<', '<', '<', '<', '<', '=', 'x'},
                            {'>', '>', '>', '>', 'x', '>', '>'},
                            {'<', '<', '<', '<', '<', 'x', '='}
                        };
    int index1 = Index(ch1);
    int index2 = Index(ch2);
    return compare[index1 - 1][index2 - 1];
}
//计算
double Calculate(char ch, double v1, double v2)
{
    double v;
    switch(ch)
    {
        case '+':
            v = v1 + v2;
            break;
        case '-':
            v = v1 - v2;
            break;
        case '*':
            v = v1 * v2;
            break;
        case '/':
            v = v1 / v2;
            break;
        default:
            break;
    }
    return v;
}
//得到表达式的值
double GetValue()
{
    int count = 0;  //用来将多为数字存入栈中
    char ch;
    opter.push('#');
    ch = getchar();
    while(!opter.empty())   //操作符不为空是执行循环
    {
        if(isdigit(ch)) //isdigit若字符是数字,返回非0值
        {
            if(count == 1)  //count是1,说明数字是连续的
            {
                double t = opval.top();    //将多位数字字符变为int型存放入栈中
                opval.pop();
                opval.push(t * 10 + ch - '0');
            }
            else    //数字第一次入栈或者数字是个位
            {
                opval.push(ch - '0');
                count = 1;
            }
            ch = getchar();
        }
        else    //字符是操作数
        {
            char c1, c2;
            double v1, v2;
            c1 = Compare(opter.top(), ch);
            switch(c1)
            {
                case '<':
                    opter.push(ch);
                    ch = getchar();
                    break;
                case '>':
                    c2 = opter.top();
                    opter.pop();
                    v2 = opval.top();
                    opval.pop();
                    v1 = opval.top();
                    opval.pop();
                    opval.push(Calculate(c2, v1, v2));
                    break;
                case '=':
                    opter.pop();
                    ch = getchar();
                    break;
                default:
                    cout << "输入有误,退出" << endl;
                    exit(0);
                    break;
            }
            count = 0;  //将其再次置位0
        }
    }
    return opval.top();
}
int main()
{
    int n;
    cout << "你想要输入几次表达式:";
    cin >> n;
    getchar();
    while(n--)
    {
        cout << GetValue() << endl;
        opval.pop();    //将最后一个值弹出
    }
    return 0;
}

运行结果:


猜你喜欢

转载自blog.csdn.net/qq_37043100/article/details/79971013