1033. 表达式求值
Posted bernieloveslife
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1033. 表达式求值相关的知识,希望对你有一定的参考价值。
Description
二哥想自己做一个计算器,但是他需要一个程序来计算输入表达式的结果。你能帮助他吗?
Input Format
输入仅一行,给出一个算数表达式。表达式中包含:小括号,加减乘除,指数运算符,负号,整数,空格。其中负号的优先级最高(-),其次是指数运算(^),然后是乘除(*/),最后是加减(+-)。
这里规定除法为整除运算,如 5 / 2 = 2, 8 / -3 = -2 等等,与C++中的整除一致。另外注意指数运算为右结合,即 2^3^2 = 2^9 = 512 而非 2^3^2 = 8^2 = 64 。
输入的字符串长度不超过100。
Output Format
如果输入的表达式出现括号不匹配或者除零错误,输出一行“Error”(不含引号),否则输出运算结果。输入保证不包含任何其它类型的错误。
输入的数,输出的答案,以及中间结果均保证是不超过 long long 范围的整数。
Sample Input
5 + (1 + 3) * 6 ^ 1
Sample Output
29
Sample Input
(6 + 2)) * 3
Sample Output
Error
说明
30%的测试数据含有负号;
30%的测试数据含有指数运算。
#include <iostream>
#include <memory>
#include <stack>
#include <fstream>
#include <vector>
#include <cmath>
#include <iomanip>
#include <exception>
#include <climits>
#include <array>
#include <cstdint>
using namespace std;
class Token {
public:
virtual bool isOperator()=0;
virtual ~Token() {}
};
class ValueToken : public Token {
public:
long long value;
long long get_value(){ return value;}
virtual bool isOperator() { return false; }
explicit ValueToken(long long val) : value(val) {}
};
class OperatorToken : public Token {
public:
enum OpType {
BGN=0, END, ADD, MNS, NEG, MUL, DIV, POW, LBK, RBK
} optr;
virtual bool isOperator() { return true; }
char get_char(){
switch (optr){
case BGN:
return ‘@‘;
case END:
return ‘$‘;
case ADD:
return ‘+‘;
case MNS:
return ‘-‘;
case NEG:
return ‘#‘;
case MUL:
return ‘*‘;
case DIV:
return ‘/‘;
case POW:
return ‘^‘;
case LBK:
return ‘(‘;
case RBK:
return ‘)‘;
default:
return ‘?‘;
}
}
explicit OperatorToken(OperatorToken::OpType op) : optr(op) {}
bool is_prior(const OperatorToken& r){
return prior_table[this->optr][r.optr];
}
static bool prior_table[10][10];
};
bool OperatorToken::prior_table[10][10]={
//BGN, END, ADD, MNS, NEG, MUL, DIV, POW, LBK, RBK
{0,0,0,0,0,0,0,0,0,0},//BGN
{1,0,0,0,0,0,0,0,0,0},//END
{1,1,0,0,0,0,0,0,1,0},//ADD
{1,1,0,0,0,0,0,0,1,0},//MNS
{1,1,1,1,0,1,1,1,1,0},//NEG
{1,1,1,1,0,0,0,0,1,0},//MUL
{1,1,1,1,0,0,0,0,1,0},//DIV
{1,1,1,1,0,1,1,1,1,0},//POW
{1,1,1,1,1,1,1,1,1,0},//LBK
{1,1,0,0,0,0,0,0,1,0},//RBK
};
vector<shared_ptr<Token>> pre_process(const string &str) {
vector<shared_ptr<Token>> ret;
ret.emplace_back(new OperatorToken(OperatorToken::BGN));
long long val = 0;
bool f = false, is_neg = true;
for (char c:str) {
if (c >= ‘0‘ && c <= ‘9‘) {
if (f)val = val * 10 + c - ‘0‘;
else val = c - ‘0‘;
is_neg= false;
f = true;
} else {
if (f) {
ret.emplace_back(new ValueToken(val));
}
switch (c) {
case ‘+‘:
ret.emplace_back(new OperatorToken(OperatorToken::ADD));
is_neg=true;
break;
case ‘-‘:
ret.emplace_back(new OperatorToken(is_neg?OperatorToken::NEG:OperatorToken::MNS));
is_neg=true;
break;
case ‘*‘:
ret.emplace_back(new OperatorToken(OperatorToken::MUL));
is_neg=true;
break;
case ‘/‘:
ret.emplace_back(new OperatorToken(OperatorToken::DIV));
is_neg=true;
break;
case ‘^‘:
ret.emplace_back(new OperatorToken(OperatorToken::POW));
is_neg=true;
break;
case ‘(‘:
ret.emplace_back(new OperatorToken(OperatorToken::LBK));
is_neg=true;
break;
case ‘)‘:
ret.emplace_back(new OperatorToken(OperatorToken::RBK));
is_neg= false;
break;
case ‘ ‘:
break;
default:
break;
}
val = 0;
f = false;
}
}
if(f)ret.emplace_back(new ValueToken(val));
ret.emplace_back(new OperatorToken(OperatorToken::END));
return ret;
}
void print(const vector<shared_ptr<Token>> v){
for(auto p:v){
if(p->isOperator()){
cout<<static_pointer_cast<OperatorToken>(p)->get_char();
}
else{
cout<<static_pointer_cast<ValueToken>(p)->get_value();
}
}
}
void compute(stack<shared_ptr<OperatorToken>>& optrs, stack<long long>& vals){
long long l,r,s;
auto op=optrs.top()->optr;
optrs.pop();
switch (op){
case OperatorToken::ADD:
if(vals.size()<2)throw exception();
r=vals.top();
vals.pop();
l=vals.top();
vals.pop();
vals.push(l+r);
#ifdef DEBUG
cout<<l<<"+"<<r<<"="<<vals.top()<<endl;
#endif
break;
case OperatorToken::MNS:
if(vals.size()<2)throw exception();
r=vals.top();
vals.pop();
l=vals.top();
vals.pop();
vals.push(l-r);
#ifdef DEBUG
cout<<l<<"-"<<r<<"="<<vals.top()<<endl;
#endif
break;
case OperatorToken::NEG:
if(vals.size()<1)throw exception();
l=vals.top();
vals.pop();
vals.push(-l);
#ifdef DEBUG
cout<<" neg "<<l<<"="<<vals.top()<<endl;
#endif
break;
case OperatorToken::MUL:
if(vals.size()<2)throw exception();
r=vals.top();
vals.pop();
l=vals.top();
vals.pop();
vals.push(l*r);
#ifdef DEBUG
cout<<l<<"*"<<r<<"="<<vals.top()<<endl;
#endif
break;
case OperatorToken::DIV:
if(vals.size()<2)throw exception();
r=vals.top();
vals.pop();
if(!r)throw exception();
l=vals.top();
vals.pop();
vals.push(l/r);
#ifdef DEBUG
cout<<l<<"/"<<r<<"="<<vals.top()<<endl;
#endif
break;
case OperatorToken::POW:
if(vals.size()<2)throw exception();
r=vals.top();
vals.pop();
l=vals.top();
vals.pop();
s=pow(l,r);
vals.push(s);
#ifdef DEBUG
cout<<l<<"^"<<r<<"="<<vals.top()<<endl;
#endif
break;
case OperatorToken::RBK:
if(optrs.top()->optr!=OperatorToken::LBK)throw exception();
optrs.pop();
#ifdef DEBUG
cout<<"()"<<endl;
#endif
break;
case OperatorToken::END:
optrs.pop();
break;
default:
throw exception();
break;
}
}
int main() {
string string1;
getline(cin,string1);
auto s = pre_process(string1);
stack<shared_ptr<OperatorToken>> optrs;
stack<long long> vals;
optrs.push(dynamic_pointer_cast<OperatorToken>(s[0]));
try{
for(auto& ptoken:s){
if(ptoken==s[0])continue;
if(!ptoken->isOperator())vals.push(dynamic_pointer_cast<ValueToken>(ptoken)->value);
else{
shared_ptr<OperatorToken> ptr=dynamic_pointer_cast<OperatorToken>(ptoken);
while (!ptr->is_prior(*optrs.top())){
compute(optrs,vals);
}
optrs.push(ptr);
}
}
if(vals.size()!=1||optrs.size()!=2)throw exception();
}catch (exception e){
cout<<"Error";
return 0;
}
cout<<vals.top();
return 0;
}
以上是关于1033. 表达式求值的主要内容,如果未能解决你的问题,请参考以下文章