数据结构与算法实验:实验四 栈应用二 表达式求值(+、-、* 、/、^)

表达式求值是进行数据处理的最基本操作。请编写程序完成一个简单算术表达式的求值。要求如下:
(1) 运算符包括:+、-、* 、/、^(乘方)、括号
(2)运算量为数值常量,根据自己的能力可以对运算量做不同的约束,例如1位整数、多位整数、实数等(会有不同的测试用例);
输入:一行,即表达式,以“=”结束。例如:
5*(8-3)+6/5=
输出:一行,即表达式的值。结果值为整数时输出为整数,如果有小数时保留5位小数。
26.20000

#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include<iostream>
using namespace std;

const double eps=1e-20;
stack<char> op;
stack<double> num;
double cal(double x1,double x2,char c)
{
    double x;
    switch (c)
    {
        case '+': x = x1 + x2; break;
        case '-': x = x2 - x1; break;
        case '*': x = x1 * x2; break;
        case '/': x = x2 / x1; break;
        case '^': x = pow(x2,x1); break;
    }
    return x;
}

void push()///将前两个数进行计算,并并将其放入栈中
{
    double x1 = num.top(); num.pop();
    double x2 = num.top(); num.pop();
    num.push(cal(x1,x2,op.top()));
    op.pop();///符号弹栈
}

int main()
{

    char s[1010];
    scanf("%s",s+1);
    int len = strlen(s+1);
    s[0] = '(';
    s[len] = ')';
    for (int i = 0; i <= len; i++)
    {
        if (s[i] == '(') op.push(s[i]);
        else if (isdigit(s[i]))///提取数字
        {
            int pos,sign = 0;
            double sum = 0;
            while (isdigit(s[i])||s[i]=='.')
            {
                if (s[i] == '.')
                {
                    pos = i;
                    sign = 1;
                }
                else sum=sum*10+s[i]-'0';
                i++;
            }
            i--;
            if(sign==1)  num.push(sum/pow(10,i-pos));
            else num.push(sum);
        }
        else if (s[i] == '+' || s[i] == '-')///优先级最低,可以进行前面的运算
        {
            while (op.top() != '(')
                push();
            op.push(s[i]);
        }
        else if (s[i] == '*' || s[i] == '/')
        {
            char OP=op.top();
            if (OP == '*'||OP == '/'||OP == '^')///只能进行*,/,^
            {
                push();
                if(OP == '^'&&op.top()=='/')///除法需要先计算
                    push();
            }
            op.push(s[i]);
        }
        else if (s[i] == '^')
        {
            if (op.top() == '^')///只能进行^
                push();
            op.push(s[i]);
        }
        else if (s[i] == ')')
        {
            while (op.top()!= '(') push();///进行括号内的运算
            op.pop();
        }
    }
    double ans=num.top();
    if(ans-(long long)ans<eps)
        printf("%.0lf\n", num.top());
    else
        printf("%.5lf\n", num.top());
    return 0;
}

4/8更新
发现bug:
1)-2*5=无法运算,负数的运算没处理
2)3+(5)=无法计算,括号内只有一个数没处理
给出几个样例:

3+5^2/2-3*4+7/5^(3-1)*2=
4.06
(3+7.5)/7/5^(3-2)*7^(2*3)-1=
35293.7
(3+7.5)/7-2^4/(5-2)^(3-2)*7^(2*3)-1=
-627460.83333
8*5/3+50/(1^10-55)^2*7=
13.45336
-2*5=
-10
2+7+(10)=
19
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include<iostream>
using namespace std;

const double eps=1e-30;
stack<char> op;
stack<double> num;
double cal(double x1,double x2,char c)
{
    double x;
    switch (c)
    {
        case '+': x = x1 + x2; break;
        case '-': x = x2 - x1; break;
        case '*': x = x1 * x2; break;
        case '/': x = x2 / x1; break;
        case '^': x = pow(x2,x1); break;
    }
    return x;
}

void push()///将前两个数进行计算,并并将其放入栈中
{
    double x1 = num.top(); num.pop();
    double x2 =0;
    char c='+';
    if(!num.empty())/// 2)防止括号内只有一个数
    {
        x2= num.top();
        num.pop();
        c=op.top();
        op.pop();///符号弹栈
    }
    num.push(cal(x1,x2,c));
}

int main()
{
    char s[1010];
    scanf("%s",s+1);
    int len = strlen(s+1);
    s[0] = '(';
    s[len] = ')';
    for (int i = 0; i <= len; i++)
    {
        if (s[i] == '(') op.push(s[i]);
        else if (isdigit(s[i]))///提取数字
        {
            int pos,sign = 0;
            double sum = 0;
            while (isdigit(s[i])||s[i]=='.')
            {
                if (s[i] == '.')
                {
                    pos = i;
                    sign = 1;
                }
                else sum=sum*10+s[i]-'0';
                i++;
            }
            i--;
            if(s[i-1]=='-'&&s[i-2]=='(')///1)处理负数,防止-2+5=的情况
            {
                sum*=-1;
                op.pop();
            }
            if(sign==1)  num.push(sum/pow(10,i-pos));
            else num.push(sum);
        }
        else if (s[i] == '+' || s[i] == '-')///优先级最低,可以进行前面的运算
        {
            while (op.top() != '(')
                push();
            op.push(s[i]);
        }
        else if (s[i] == '*' || s[i] == '/')
        {
            char OP=op.top();
            if (OP == '*'||OP == '/'||OP == '^')///只能进行*,/,^
            {
                push();
                if(OP == '^'&&op.top()=='/')///除法需要先计算,再乘法:1/5^2*25
                    push();
            }
            op.push(s[i]);
        }
        else if (s[i] == '^')
        {
            if (op.top() == '^')///只能进行^
                push();
            op.push(s[i]);
        }
        else if (s[i] == ')')
        {
            while (op.top()!= '(') push();///进行括号内的运算
            op.pop();///'('弹栈
        }
    }
    double ans=num.top();
    if(abs(ans-(long long)ans)<=eps)
        printf("%.0lf\n", ans);
    else
        printf("%.5lf\n", ans);
    return 0;
}

/*‭(3+7.5)/7-2^4/(5-2)^(3-2)*7^(2*3)-1=‬*/

猜你喜欢

转载自blog.csdn.net/Spidy_harker/article/details/105245001