hdu 3000 A Simple Language (逆波兰式计算四则运算表达式数值)
2014-07-27 18:38
681 查看
A Simple Language
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 459 Accepted Submission(s): 86
[align=left]Problem Description[/align]
Professor X teaches the C Programming language in college, but he finds it's too hard for his students and only a few students can pass the exam. So, he decide to invent a new language to reduce the burden on students.
This new language only support four data type, but the syntax is an strict subset of C. It only support assignment operation, brackets operation , addition , subtration, multiplication and division between variables and numbers. The priority of operations is
the same as C.
In order to void the problem of forgetting the eliminator ";", this new language allow to omit it.
The variable naming rules is the same as C.
Comments is not allowed in this language.
Now Prof.X need to impelment this language, and the variable part is done by himself. Now Prof.X need you, a execllent ACM coder's help: Given a section of this language's code, please calculate it's return value.
[align=left]Input[/align]
The input contains many lines, each line is a section of codes written in the language described above, you can assume that all variables have been declared as int and have been set to 0 initially.
[align=left]Output[/align]
To each line of input, output an integer indicate the return value of the input line. the semicolon will only appear in the end of line, you can assume that every literal, variable's value and the intermediate results of calculation
would never bigger than a short integer.
Notice: the result may affect by assignment operation, if you don't know the exact return value of some statements such as a=3, you can try run codes such as ' printf("%d",a=3); ' in C, and check the result.
[align=left]Sample Input[/align]
a=3
a+b
a=a*(b+2)+c;
a+b
a/4
_hello=2*a;
[align=left]Sample Output[/align]
3
3
6
6
1
12
题目意思就是连续输入多行算术表达式,每行都会返回一个运算结果,变量的初始值都为0,每次赋值都会覆盖原先值并保存下来,输出每行运算结果。
刚学完编译原理,见过类似的形式,首先想到的便是用先逆波兰式表示出来然后再进行运算。就相当于先去掉括号和优先级的约束,当然没有这个约束计算就很简单了,然而事实却并不是那么简单,首先就是负数问题比如a=-b,-1+-2,这种类型,这就要求词法要写好,哪个地方作为分隔符要仔细判断,然后赋值运算的问题,可能出现连续而且带括号的形式,比如a=b= (a=b=1)+1,这种情况下其实只要确定好每个运算符的优先级,把赋值当一般的运算符进行运算就行了。。这两种过了基本就可以ac了。
而且这种题写过一次以后都可以重复用了,写好模板很重要!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
#include <map>
#include <cstdlib>
using namespace std;
map<string,int> mp;
////////////////
//RPN reverse Polish notation
class RPN{
private:
string ori;
vector<string> vec;
vector<string> res;
map<string,int> pri;
public:
void initial()
{
vec.clear();
res.clear();
ori = "";
pri["#"] = 0;
pri["="] = 1;
pri["+"] = pri["-"] = 2;
pri["/"] = pri["*"] = 3;
}
void input(string s){
ori = s;
}
void CiFa()
{
string tmp = "";
for(int i=0;i<ori.length();i++)
{
if(ori[i]==' ') continue;
if(i==ori.length()-1 || ori[i+1]=='+' || ori[i+1]=='-' || ori[i+1]=='/' || ori[i+1]=='*' || ori[i+1]=='(' || ori[i+1]==')' || ori[i+1]==' ' || ori[i+1]=='=')
{
tmp += ori[i];
vec.push_back(tmp);
tmp = "";
}
else if(ori[i]=='(' || ori[i]==')' ||ori[i]=='*' || ori[i]=='/' ||ori[i]=='+'||ori[i]=='=')
{
tmp = "";
tmp += ori[i];
vec.push_back(tmp);
tmp = "";
}
else if(ori[i]=='-')
{
if(vec.size()==0 || vec[vec.size()-1]=="(" || vec[vec.size()-1]=="+" || vec[vec.size()-1]=="-" || vec[vec.size()-1]=="*" || vec[vec.size()-1]=="/")
{
tmp+=ori[i];
}
else
{
tmp = "";
tmp += ori[i];
vec.push_back(tmp);
tmp = "";
}
}
else tmp += ori[i];
}
/*
for(int i=0;i<vec.size() ;i++)
{
cout << vec[i] << " ";
}
cout << endl;
*/
}
void process()
{
CiFa();
stack<string> s1;
stack<string> s2;
s1.push("#");
vec.push_back("#");
for(int i=0;i<vec.size();i++)
{
string tmp = vec[i];
if(tmp=="=")
{
string t1 = s1.top();
if(t1=="(" || pri[tmp]>=pri[t1])
{
s1.push(tmp);
}
else{
while(t1!="(" && pri[t1] > pri[tmp] )
{
s2.push(t1);
s1.pop();
t1 = s1.top();
}
s1.push(tmp);
}
}
else if(tmp=="+" || tmp=="-" ||tmp=="*"||tmp=="/")
{
string t1 = s1.top();
if(t1=="(" || pri[tmp]>pri[t1])
{
s1.push(tmp);
}
else{
while(t1!="(" && pri[t1] >= pri[tmp] )
{
s2.push(t1);
s1.pop();
t1 = s1.top();
}
s1.push(tmp);
}
}
else if(tmp=="(")
{
s1.push(tmp);
}
else if(tmp==")")
{
string t1 = s1.top();
while(t1!="(")
{
s2.push(t1);
s1.pop();
t1 = s1.top();
}
s1.pop();
}
else if(tmp=="#")
{
string t1 = s1.top();
while(t1!="#")
{
s2.push(t1);
s1.pop();
t1 = s1.top();
}
}
else s2.push(tmp); // num || var
}
// rpn save to stack s2
while(!s2.empty())
{
string tmp = s2.top();
res.insert(res.begin(),tmp);
s2.pop();
}
}
// rpn string
string getRes()
{
string s = "";
for(int i=0;i<res.size();i++)
{
s += res[i];
}
return s;
}
// int to string
string itoa(int x)
{
if(x==0) return "0";
string t = "";
if(x<0)
{
t = "-";
x=-x;
}
char p[50];
int cnt = 0;
while(x>0)
{
p[cnt++] = x%10 + '0';
x /= 10;
}
while(cnt--)
{
t+= p[cnt];
}
return t;
}
int getValue()
{
stack<string> sta;
string str;
int s1,s2;
for(int i=0;i<res.size();i++)
{
if(res[i]=="=")
{
string str1 = sta.top();
sta.pop();
string str2 = sta.top();
sta.pop();
if(str1[0]=='-')
{
if((str1[1]>='0' && str1[1]<='9'))
{
mp[str2] = atoi(str1.c_str());
}
else
{
str1.erase(0);
mp[str2] = -mp[str1];
}
}
else if((str1[0]>='0' && str1[0]<='9'))
{
mp[str2] = atoi(str1.c_str());
}else mp[str2] = mp[str1];
sta.push(str1);
}
else if(res[i]=="+" || res[i]=="-" || res[i]=="*" || res[i]=="/")
{
str = sta.top();
if(str[0]=='-')
{
if((str[1]>='0' && str[1]<='9'))
{
s1 = atoi(str.c_str());
}
else
{
str.erase(0,1);
s1 = -mp[str];
}
}
else if((str[0]>='0' && str[0]<='9') || str[0]=='-') s1 = atoi(str.c_str());
else s1 = mp[str];
sta.pop();
str = sta.top();
if(str[0]=='-')
{
if((str[1]>='0' && str[1]<='9'))
{
s2 = atoi(str.c_str());
}
else
{
str.erase(0,1);
s2 = -mp[str];
}
}
else if((str[0]>='0' && str[0]<='9') || str[0]=='-') s2 = atoi(str.c_str());
else s2 = mp[str];
sta.pop();
int tmp = 0;
if(res[i]=="+") tmp = s2 +s1;
if(res[i]=="-") tmp = s2 -s1;
if(res[i]=="*") tmp = s2 *s1;
if(res[i]=="/") {
if(s1!=0) tmp = s2 /s1;
else tmp = 0;
}
// char buffer[100];
// cout << "tmp:" << tmp << endl;
//itoa(tmp,buffer);
sta.push(itoa(tmp));
}
else{
sta.push(res[i]);
}
}
str = sta.top();
if((str[0]>='0' && str[0]<='9') || str[0]=='-') return atoi(str.c_str());
return mp[str];
}
};
//////////////////////
int solve(string s)
{
RPN rpn;
rpn.initial();
rpn.input(s);
rpn.process();
// cout << rpn.getRes() <<endl;
return rpn.getValue();
}
int main()
{
string s;
while(getline(cin,s))
{
int len = s.length();
if(s[len-1]==';') s.erase(len-1);
cout << solve(s) << endl;
}
return 0;
}
相关文章推荐
- 【表达式运算】hdu hdoj 3000 A Simple Language
- 【原创】Delphi实现数学表达式的计算(逆波兰式法)-四则运算解析
- java中正则表达式用Pattern计算字符串的结果(四则运算);分成有括号和没括号;当然也可以采用逆波兰式
- 表达式(四则运算)计算的算法
- 如何让计算机计算四则运算表达式[第一篇]
- 计算四则运算表达式
- 二叉树计算四则运算表达式
- 用PHP实现的四则运算表达式计算
- 一个计算四则运算表达式文本的方法
- 字符串四则运算表达式的计算(华为机试)
- bash shell数组模拟栈求四则运算混合表达式的逆波兰式和值
- 计算一个字符串表示的四则运算表达式
- 表达式(四则运算)计算的算法
- 字符串四则运算表达式的计算(华为机试)
- 表达式(四则运算)计算的算法代写 essay代写
- 用PHP实现的四则运算表达式计算实现代码
- 实数四则运算表达式的计算,C++ 实现
- 用PHP实现的四则运算表达式计算实现代码
- 计算表达式的值(仅含有四则运算和支持括号嵌套,浮点数运算)
- 中缀表达式的计算(只包含四则运算与括号)