题目描述
小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算术表达式,其中只有如下符号:
“(”,“)”,“0~9”,“+”,“-”,“*”,“/”,“^”
其中“^”表示乘方,“/”用整除。
输入的表达式都是合法的,这个表达式的值就是密码。小明数学学得不好,还需你帮他的忙。
输入格式
输入一行字符串,为一个算术表达式。
输出格式
输出一个整数,就是密码。
样例数据 1
输入
1+(3+2)*(7^2+6*9)/(2)
输出
258
备注
【数据范围】
100% 的数据满足:整个算式长度<=30,其中所有数据运算结果(包含中间运算结果)都在 231-1 的范围内。
分析
我们先来了解一下字符串 string 的使用,以及一些常用函数
substr 取出字符串的一个子串 使用:str2 = str1.substr(5,7)
这个使用的意思就是,取出str1中从第5个位置开始往后数7个位置,这一段字符串,并存在str2中
sscanf 从一个字符串中读入
其实和scanf是一样的,只是scanf是从屏幕中读,但是sscanf是从你给定的字符串中读取
使用:
if s=" 100 50y "
sscanf(s_c.str(),“%d%d",&a,&b);
这个时候a=100,b=50
sprintf 将一些东西输出到一个字符串里去
其实也和printf差不多,只是printf是输出到屏幕上,sprintf是输出到你给定的字符串中
知道这些常用操作后,做起字符串的题来简直顺溜极了
对于这道题而言,由于我们知道计算机比较笨笨的,不会像我们人一样直接判断运算的优先级然后进行计算,它只会按部就班从左往右算。所以我们要体谅它一下,转化一下表达式的样子,然后再交给计算机算
我们维护两个栈,一个是运算符栈,一个是操作数栈
从左往右扫描字符串,遇到数字就截取这一段数字将其压入操作数栈,遇到运算符就压入运算符栈。在压入运算符的时候,我们需要保证栈顶运算符的优先级低于当前的运算符,然后再压入,如果大于当前的运算符,我们就将其弹出栈,并从操作数栈中取头两个数进行相应运算,再将得到的值压回操作数栈
这样一直进行下去,直到字符串扫描完
为了方便,我们在字符串的一头一尾加上括号
为什么这样搞就是对的呢??
手动模拟一下吧……这很显然
代码
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int number[301]; //数字栈
char symbol[301]; //运算符栈
string s,t; //s为表达式串,t是一个多位数字串
int i,j,p; //i为s中读数据指针,p为栈指针
int POW(int a,int b) //求a^b
{
int j,t=1;
for(j=1;j<=b;j++) t*=a;
return t;
}
void push() //运算符入栈
{
p++;
symbol[p]=s[i];
}
void pop() //运算符栈顶元素出栈,并取出操作数栈栈顶的2个元素完成相应的运算
{
p--; //运算符栈,栈顶运算符出栈
switch(symbol[p+1]) //数字栈,栈顶2个元素出栈利用刚才出栈的符号运算
{
case '+' : number[p]+=number[p+1]; break;
case '-' : number[p]-=number[p+1]; break;
case '*' : number[p]*=number[p+1]; break;
case '/' : number[p]/=number[p+1]; break;
case'^' :number[p]=POW(number[p],number[p+1]);break;
}
}
bool can() //判断运算符的优先级别,建立是否出栈运算的标志函数
{
if((s[i]=='+' || s[i]=='-') && (symbol[p]!='(' )) return true; //能出栈运算
if((s[i]=='*' || s[i]=='/') && (symbol[p]=='^' ||symbol[p]=='*' || symbol[p]=='/')) return true;
if(s[i]=='^' && symbol[p]=='^') return true;
return false; //不能出栈运算
}
int main()
{
cin>>s;
s="("+s+")"; //读入表达式并在两端加一对括号
i=0; p=0;
while(i<s.size()) //扫描字符串
//一定要注意处理顺序
{
while(s[i]=='(' ) //左括号处理
{
push(); //左括号入栈
i++;
}
if(s[i]>='0' && s[i]<='9')
{
j=i;
do //取连续数字入操作数栈
{
i++;
}while(s[i]>='0' && s[i]<='9');
t=s.substr(j,i-j); //从s中截取多位串并转成数值型
sscanf(t.c_str(),"%d",&number[p]); //转成整数
}
//处理数字后面的情况,只能是')'或运算符号两种情况
if(s[i]==')') //右括号处理
{
while(symbol[p]!='(') pop(); //反复计算括号中的表达式直到左括号为止
p--; //左括号出栈(已经完成运算)
number[p]=number[p+1]; //把结果下移到下面一个空格中
}
else //如果是运算符,根据can值作运算符出栈计算 或 入栈
{
while(can()) pop(); //如果新运算符号级别低于栈内符号,则反复出栈运算
push(); //新符号s[i]入栈
}
i++; //取下一个字符
}
cout<<number[0]<<endl; //输出结果
return 0;
}