數據結構與算法實驗:實驗四 棧應用二 表達式求值(+、-、* 、/、^)

表達式求值是進行數據處理的最基本操作。請編寫程序完成一個簡單算術表達式的求值。要求如下:
(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=‬*/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章