一、题目描述
问题描述
带有变量的中缀表达式是常见的数学表达式。如果规定变量由长度不超过 8 个小写字母组成;end为保留字,表示程序段结束;用?表示输出指定变量的值,则可以设计出比较复杂的表达式(即一个可顺序执行语句序列)。例如,如果有如下语句段:
abc=10
def=8
c=abc+def
abc=abc+5-c*2
? c
? abc
end则输出为:
c=18
abc=-21注意:为了简化编程实现,运算符只有+,-,*,/ ,%和^(指数运算),可以处理圆括号(),并假定输入的算术表达式正确。
要求:使用栈结构实现。
输入:表达式序列
输出:全部指定变量的值
表达式中的全部计算结果均为整数。如果在计算过程中出现除数为0的情况,则输出:Divide 0.
特殊情况说明:
在表达式中,如果操作数出现负数(例如-8),则要特别注意。例如:
10加-8表示为:10+-8。
10减-8表示为:10--8。
测试输入 期待的输出 时间限制 内存限制 额外进程 测试用例 1 以文本方式显示
- abc=10↵
- def=8↵
- c=abc+def↵
- abc=abc+5-c*2↵
- ? c↵
- ? abc↵
- end↵
以文本方式显示
- c=18↵
- abc=-21↵
1秒 64M 0 测试用例 2 以文本方式显示
- a=12↵
- b=5↵
- c=a/b↵
- d=(a+1)%(b+1)↵
- e=a^2↵
- f=-12+a↵
- g=(a+5)*d-c↵
- ? c↵
- ? d↵
- ? e↵
- ? f↵
- ? g↵
- a=a+10↵
- ? a↵
- end↵
以文本方式显示
- c=2↵
- d=1↵
- e=144↵
- f=0↵
- g=15↵
- a=22↵
1秒 64M 0 测试用例 3 以文本方式显示
- abc=3↵
- ab=2^(abc-1)^(5-abc)↵
- ? ab↵
- end↵
以文本方式显示
- ab=16↵
1秒 64M 0 测试用例 4 以文本方式显示
- a=2↵
- b=a^(a+1)^(10-8)↵
- ? b↵
- end↵
以文本方式显示
- b=512↵
1秒 64M 0 测试用例 5 以文本方式显示
- a=10↵
- ? a↵
- b=-10+10↵
- ? b↵
- a=-10-10↵
- ? a↵
- c=a+-10+-10↵
- ? c↵
- d=-20+-8-8↵
- ? d↵
- e=a-12*-2↵
- ? e↵
- f=80--10+2↵
- ? f↵
- g=-10--10↵
- ? g↵
- h=-10+-10↵
- ? h↵
- i=(90)↵
- ? i↵
- k=(-100)↵
- ? k↵
- end↵
以文本方式显示
- a=10↵
- b=0↵
- a=-20↵
- c=-40↵
- d=-36↵
- e=4↵
- f=92↵
- g=0↵
- h=-20↵
- i=90↵
- k=-100↵
1秒 64M 0 测试用例 6 以文本方式显示
- abcdefgh=4↵
- ten=10↵
- a=18-32↵
- ? a↵
- b=18/abcdefgh↵
- ? b↵
- c=18%(b-1)↵
- ? c↵
- d=ten+(ten+ten)*abcdefgh↵
- ? d↵
- e=ten-2*ten/abcdefgh↵
- ? e↵
- f=(18-3)*3↵
- ? f↵
- ten=ten*(ten)↵
- ? ten↵
- ten=ten/10↵
- ten=(ten+2)/(8-ten)↵
- ? ten↵
- h=(2*3)/(5*2)↵
- ? h↵
- ten=10↵
- x=ten-(80-30)/3*3+abcdefgh↵
- y=(((2+8)*2-(2+abcdefgh)/2)*2-8)*2↵
- z=(((8+2)*(abcdefgh/2)))↵
- ? x↵
- ? y↵
- ? z↵
- end↵
以文本方式显示
- a=-14↵
- b=4↵
- c=0↵
- d=90↵
- e=5↵
- f=45↵
- ten=100↵
- ten=-6↵
- h=0↵
- x=-34↵
- y=52↵
- z=20↵
1秒 64M 0
二、思路提示
1、从输入入手
输入为若干行,可以分为以下三种:
①带等号的常规赋值式或四则运算
②以问号开头代表需要输出变量的值
③end
2、关于变量
考虑使用结构体来存储。
#define N 110
typedef struct {
string name;
int value;
} VRBL;
VRBL v[N];
声明VRBL是一个结构体。每个v表示一个变量,v.name是这个变量的名称,v.value是这个变量当前的值。
还是使用string,非常的方便,真的是干净又卫生啊。
3、关于四则运算
还是栈,做过很多题目了,此处不再赘述。
三、完整代码
这道题目虽然是选做,不过论难度那还真是不难。
#include<bits/stdc++.h>
using namespace std;
#define N 110
typedef struct {
string name; //name是变量的名字,例如abc,e等。
int value; //value是变量的值。
} VRBL;
VRBL v[N];
//若返回值大于1,表示运算符;若返回1,表示是数字;若返回0,表示既不是运算符也不是数字,也就是字母。注意,这里面是不考虑等于号的。
int valu(char c) {
if ( c==')' ) return 6;
if ( c=='^' ) return 5;
if ( c=='*' || c=='/' || c=='%' ) return 4;
if ( c=='+' || c=='-' ) return 3;
if ( c=='(' ) return 2;
if ( c>='0' && c<='9' ) return 1;
return 0;
}
//两个数之间的计算
void cal(int *a1, int a2, char op) {
switch (op){
case '+': (*a1) = (*a1) + a2; break;
case '-': (*a1) = (*a1) - a2; break;
case '*': (*a1) = (*a1) * a2; break;
case '/': (*a1) = (*a1) / a2; break;
case '%': (*a1) = (*a1) % a2; break;
case '^': (*a1) = pow((*a1),a2); break;
}
}
int main(){
int valu(char);
void cal(int*, int ,char);
string Formula;
int n=0; //n用来统计变量的个数
while (cin>>Formula,Formula!="end") {
//如果是问号
if (Formula.find('?')!=-1) {
cin >> Formula;
//遍历一次v,找到相应的变量
int i;
for (i=0;i<=n;i++) {
if (Formula==v[i].name) {
break;
}
}
cout << v[i].name << '=' << v[i].value << endl;
}
else {
//执行通常的赋值或计算
int target, digit=0; //digit用来遍历Formula,target是待赋值的变量
string tpry; //tpry用来暂时存放读入的字符串内容
//找到待赋值的变量
while (Formula[digit]!='=') {
tpry+=Formula[digit];
digit++;
} digit++;
//将待赋值的变量在v中进行匹配,如果已经有了就直接套用,否则就加入新的
if (n==0) {
target = 0;
v[0].name = tpry;
n++;
}
else {
int flag=0;
for (int i=0;i<n;i++) {
if (tpry==v[i].name) {
flag=1;
target = i;
break;
}
}
if (flag==0) {
target = n;
v[n].name = tpry;
n++;
}
}
//计算等号后面的内容
stack<int> Svalue; //Svalue用来存储值
stack<char> Sop; //Sop用来存储运算符
int len = Formula.length(), start=digit, flag=1; //flag用来标记正负数
while ( digit<len ) {
if ( valu( Formula[digit] )==1 )
//数字
{
int cnt=0;
while ( digit<len && valu(Formula[digit])==1 ) {
cnt = cnt * 10 + Formula[digit] - '0';
digit++;
}
Svalue.push(cnt*flag);
flag=1;
}
else if ( valu( Formula[digit] )>1 )
//运算符
{
if ( Sop.size()==0 ) {
if (digit==start && Formula[digit]=='-') flag = -1;
else Sop.push( Formula[digit] );
}
else {
//Sop不为空
//负数
if ( digit>start && Formula[digit]=='-' && valu(Formula[digit-1])>1 ) {
flag=-1;
}
//左括号
else if (Formula[digit]=='(' ) {
Sop.push( Formula[digit] );
}
//右括号
else if (Formula[digit]==')' ) {
while ( Sop.size() && Sop.top()!='(' ) {
char c = Sop.top(); Sop.pop();
int a = Svalue.top(); Svalue.pop();
cal(&Svalue.top(), a, c);
}
Sop.pop();
}
else {
//连续乘方
if ( Sop.size() && Formula[digit]=='^' && Sop.top()=='^' ) {
Sop.push('^');
}
else {
if ( Sop.size() && valu(Formula[digit])<=valu(Sop.top()) ) {
while ( Sop.size() && valu(Formula[digit])<=valu(Sop.top()) ) {
char c = Sop.top(); Sop.pop();
int a = Svalue.top(); Svalue.pop();
cal(&Svalue.top(), a, c);
}
Sop.push(Formula[digit]);
}
else {
Sop.push(Formula[digit]);
}
}
}
}
digit++;
}
else if ( valu( Formula[digit] )==0 )
//字母
{
//找到完整的变量名称
string word;
while ( digit<len && valu(Formula[digit])==0 ) {
word += Formula[digit];
digit++;
}
//匹配并且取值,将其值存入栈
for (int i=0;i<n;i++) {
if (v[i].name==word) {
Svalue.push(v[i].value*flag);
flag=1;
break;
}
}
}
}
//补刀
while ( Sop.size() ) {
int a = Svalue.top(); Svalue.pop();
cal(&Svalue.top(), a, Sop.top());
Sop.pop();
}
//为目标变量赋新值
v[target].value = Svalue.top();
}
}
return 0;
}