C++ 表达式求值(栈)

表达式求值


第一次使用Markdown编辑器不太习惯,写了很多版本的表达式求值有并且有Java的。但是就觉得这一个还不错。
表达式求值主要就是主要考虑运算符的优先级,“+-”属于同一级别,”%/属于同一级别我自定义了一个函数判断


static int precedence(char ch)
{
    switch (ch) {
    case '+': return 1;
    case '-': return 1;
    case '*': return 2;
    case '/': return 2;
    case '%': return 2;
    default:
        break;
           }
    return 0;
}

运算操当栈顶的运算符优先级大于等于当前运算符,就取出数据栈的两个数据和运算符栈的运算符进行运算


//运算操作
static int stack_count(stack<double> *num, stack<char> *op)
{
        char oper= op->top();op->pop();//取出运算符
        //取出两个数据进行运算
        if (num->size()<2) { return -1; }//如果数据栈的数据少于两个说明出错
        double num1 = num->top();num->pop();
        double num2 = num->top();num->pop();
        int s = 0;
        switch(oper)
        {
        case '+': num->push(num2+num1);break;
        case '-': num->push(num2-num1);break;
        case '*': num->push(num2*num1);break;
        case '/': num->push(num2/num1);break;
        case '%': num->push((int)num2 % (int)num1);break;
        default:s = -1;break;
        }
        return s;
}

主函数就是将输入的表达式进行传入到运算函数里面进行运算,我的是将输入的表达式存储到一个string类里面然后,遍历str的每个字符进行操作


static int oper_expre(string str)
{
    char *op = { "+-*/%" };
    char *left = { "({[" };
    char *right = { ")]}" };
    stack<double> OPND;//存放数据
    stack<char>   OPTR;   //存放运算符
    for (string::iterator it = str.begin();it != str.end();it++)
    {
        if (*it == ' ') { continue; }   //跳过空字符
        else if (strchr(op, *it) != NULL)
        {
            while (!OPTR.empty() && precedence(OPTR.top()) >= precedence(*it))
            {
                if (stack_count(&OPND, &OPTR) == -1)
                {
                    return -1;
                }
            }
            OPTR.push(*it);
        }
        else if (strchr(left, *it) != NULL)//处理左括号
        {
            OPTR.push(*it);
        }
        else if (strchr(right, *it) != NULL)//处理右括号
        {
            while (strchr(left, OPTR.top()) == NULL)
            {
                if (stack_count(&OPND, &OPTR) == -1)
                {
                    return -1;
                }
            }
            OPTR.pop();
        }
        else if (*it >= '0'&&*it <= '9')//处理数据 
        {

            string num;
            while (*it >= '0'&&*it <= '9' || *it == '.')
            {
                num += *it;
                it++;
                if (it == str.end()) { break; }
            }
            it--;
            stringstream  sir(num);
            double d;
            sir >> d;
            OPND.push(d);
        }
        else
        {
            return -1;
        }
    }
    while (!OPTR.empty())
    {
        if (stack_count(&OPND, &OPTR) == -1)
        {
            return -1;
        }
    }
    if (OPND.empty()) { return -1; }//如果为空说明输入有问题
    cout << OPND.top() << endl;
    return 1;
}

这里是所有代码 程序缺点是不能进行负数的运算 大家可以自行优化下


#include<iterator>
#include<iostream>
#include<stack>
#include<string>
#include<string.h>
#include<sstream>
using namespace std;
//运算符优先级判断
static int precedence(char ch)
{
    switch (ch) {
    case '+': return 1;
    case '-': return 1;
    case '*': return 2;
    case '/': return 2;
    case '%': return 2;
    default:
        break;
           }
    return 0;
}
//运算操作
static int stack_count(stack<double> *num, stack<char> *op)
{
        char oper= op->top();op->pop();//取出运算符
        //取出两个数据进行运算
        if (num->size()<2) { return -1; }//如果数据栈的数据少于两个说明出错
        double num1 = num->top();num->pop();
        double num2 = num->top();num->pop();
        int s = 0;
        switch(oper)
        {
        case '+': num->push(num2+num1);break;
        case '-': num->push(num2-num1);break;
        case '*': num->push(num2*num1);break;
        case '/': num->push(num2/num1);break;
        case '%': num->push((int)num2 % (int)num1);break;
        default:s = -1;break;
        }
        return s;
}
static int oper_expre(string str)
{
    char *op = { "+-*/%" };
    char *left = { "({[" };
    char *right = { ")]}" };
    stack<double> OPND;//存放数据
    stack<char>   OPTR;   //存放运算符
    for (string::iterator it = str.begin();it != str.end();it++)
    {
        if (*it == ' ') { continue; }   //跳过空字符
        else if (strchr(op, *it) != NULL)
        {
            while (!OPTR.empty() && precedence(OPTR.top()) >= precedence(*it))
            {
                if (stack_count(&OPND, &OPTR) == -1)
                {
                    return -1;
                }
            }
            OPTR.push(*it);
        }
        else if (strchr(left, *it) != NULL)//处理左括号
        {
            OPTR.push(*it);
        }
        else if (strchr(right, *it) != NULL)//处理右括号
        {
            while (strchr(left, OPTR.top()) == NULL)
            {
                if (stack_count(&OPND, &OPTR) == -1)
                {
                    return -1;
                }
            }
            OPTR.pop();
        }
        else if (*it >= '0'&&*it <= '9')//处理数据 
        {

            string num;
            while (*it >= '0'&&*it <= '9' || *it == '.')
            {
                num += *it;
                it++;
                if (it == str.end()) { break; }
            }
            it--;
            stringstream  sir(num);
            double d;
            sir >> d;
            OPND.push(d);
        }
        else
        {
            return -1;
        }
    }
    while (!OPTR.empty())
    {
        if (stack_count(&OPND, &OPTR) == -1)
        {
            return -1;
        }
    }
    if (OPND.empty()) { return -1; }//如果为空说明输入有问题
    cout << OPND.top() << endl;
    return 1;
}
int main()
{
    string str;
    while(cin>>str)
    {
            if (oper_expre(str) == -1)//处理格式是否正确
            {
                cout << "输入格式不正确请重新输入" << endl;
            }
    }
    return 0;
}

这里写图片描述

猜你喜欢

转载自blog.csdn.net/dog_dream/article/details/80198653