表示式求值 NYOJ - 35
阿新 • • 發佈:2018-11-19
題解
題目連結
先將表示式字串去掉等號後使用逆波蘭規則轉換為字尾表示式然後計算
AC程式碼
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e3 + 10;
char s[MAXN];
struct node
{
double v;
char c; //操作符 為0則為值
node &operator + (const node & oth) //+-*/根據需求改變
{
v += oth.v;
return *this;
}
node &operator - (const node &oth)
{
v -= oth.v;
return *this;
}
node &operator * (const node &oth)
{
v *= oth.v;
return *this;
}
node &operator / (const node &oth)
{
v /= oth.v;
return *this;
}
};
int Lv(char c) //符號優先順序
{
if (c == '+')
return 1;
if (c == '-')
return 1;
if (c == '*')
return 2;
if (c == '/')
return 2;
return 0;
}
queue<node> q;
stack<node> stk;
void ToRPN(char *s) //輸入字串s逆波蘭處理後存入q中
{
double t = 0, p = 0; //數字 小數權值
for (int i = 0; s[i]; i++)
{
if (isdigit(s[i])) //數字 直接進隊
{
if (!i || !isdigit(s[i - 1]) && s[i - 1] != '.') //數字第一位
t = s[i] - '0';
else if (p == 0) //沒到小數點
t = t * 10 + s[i] - '0';
else //小數位
t = t + (s[i] - '0') / p, p *= 10;
if (!isdigit(s[i + 1]) && s[i + 1] != '.') //數字結束 入隊並清空小數標記
q.push({ t, 0 }), p = 0;
}
else if (s[i] == '.') //標記小數開始
p = 10;
else if (s[i] == '(') //左括號直接進棧
stk.push({ 0.0, s[i] });
else if (s[i] == ')') //右括號 將上一個左括號後的操作全部進隊
{
while (stk.top().c != '(')
q.push(stk.top()), stk.pop();
stk.pop();
}
else //其它操作符 將比自身優先順序高或者相等的全部進隊自身再進棧
{
while (!stk.empty() && Lv(s[i]) <= Lv(stk.top().c))
q.push(stk.top()), stk.pop();
stk.push({ 0, s[i] });
}
}
while (!stk.empty()) //剩餘全部進隊
q.push(stk.top()), stk.pop();
}
double CalRPN() //計算q中的逆波蘭並返回答案
{
while (!q.empty())
{
char c = q.front().c;
if (!c) //數字 直接進棧
stk.push(q.front()), q.pop();
else //操作符 計算
{
q.pop();
node lst = stk.top();
stk.pop();
node fst = stk.top();
stk.pop();
if (c == '+')
fst = fst + lst;
if (c == '-')
fst = fst - lst;
if (c == '*')
fst = fst * lst;
if (c == '/')
fst = fst / lst;
stk.push(fst);
}
}
double res = stk.top().v; //返回答案
stk.pop();
return res;
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int T;
cin >> T;
while (T--)
{
scanf("%s", s);
for (int i = 0;; i++) //消除等號
if (s[i] == '=')
{
s[i] = 0;
break;
}
ToRPN(s);
printf("%.2f\n", CalRPN());
}
return 0;
}