在一个表达式中,只有“(”,“)”,“0-9”,“+”,“-”,“*”,“/”,“^”,请求出表达式的值。(“/”用整数除法)。
共1 行,为一个算式。 (算式长度<=30 其中所有数据在 0~2^31-1的范围内)。
共一行,为表达式的值。
在这里给出一组输入。例如:
1+(3+2)(7^2+69)/(2)
在这里给出相应的输出。例如:
258
读取完字符串之后,扫描一遍,扫描一遍后,运算也同时结束,过程中将中缀表达式转化成后缀表达式,一边转化,一边计算。
1.如果碰到了数字,开始往数字栈放数字(考虑多位数情况)
2.如果碰到了 “(” 直接入符号栈
3.如果碰到了运算符,如果其优先级大于符号栈顶元素优先级,入栈;
否则,先计算符号栈顶元素和数字栈顶两元素的运算结果
(特别的,如果数字栈内元素不足2,那么不论哪一种运算符都要直接入栈)
4.如果碰到了 “)” 开始从两个栈往外提取元素,进行计算,直到符号栈顶元素是 “(” ,计算结束后要把 “(” 也取出,表示这一对括号内的表达式已经计算成一个结果了
5.特别的,“^”的优先级要大于 “” 和 “/” (比较723和7 ^23的区别)
6.更多的细节在代码和注释中
以下是我的代码,使用的是非常非常基础的方法,代码本身非常易懂,并适当进行了注释,对想了解一下这种问题解决思路的朋友比较合适:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
int in(char ch)//判断是否是数字 函数
{
if(ch<='9'&&ch>='0')
{
return 1;
}
return 0;
}
int cal(int a,char c,int b)//计算函数
{
if(c=='*'){
return a*b;
}else if(c=='/'){
return a/b;
}else if(c=='-'){
return a-b;
}else if(c=='+'){
return a+b;
}else{
return pow(a,b);
}
}
int com(char a,char b)//比较运算符优先级
{
int x=0;//a的优先级
int y=0;//b的优先级
if(a=='+'||a=='-')
{
x=1;
}else if(a=='*'||a=='/')
{
x=2;
}else if(a=='^')
{
x=3;
}
else if(a=='(')
{
x=4;
}
if(b=='+'||b=='-')
{
y=1;
}else if(b=='*'||b=='/')
{
y=2;
}else if(b=='^')
{
y=3;
}
else if(b=='(')
{
y=4;
}
if(x>y)return 1;
return 0;
}
int main()
{
char s[310];//主串
int num[310];//数字栈
char ch[310];//运算符栈
gets(s);
int a,b;
a=0;//数字栈的栈顶
b=0;//符号栈的栈顶
for(int i=0;i<310;i++)
{
num[i]=0;
ch[i]='0';
}
int i=0;
while(i<strlen(s))
{
if(in(s[i]))
{
while(in(s[i]))//如果是数字 进入数字栈 字符转化成数字
{
num[a]=num[a]*10+s[i++]-'0';
}
a++;
//printf("%d %d ",num[a-2],num[a-1]);
//for(int k=0;k<b;k++)
//{
// printf("%c ",ch[k]);
//}
//printf("\n");
continue;
}
else
{
if(s[i]=='(')//如果是左括号 直接入栈
{
ch[b++]=s[i];
}
else if(s[i]==')')//如果是右括号 开始计算括号内的表达式
{
while(ch[b-1]!='(')//在找到相匹配的左括号之前 一直计算
{
//printf("%d %d ",num[a-2],num[a-1]);
//for(int k=0;k<b;k++)
//{
// printf("%c ",ch[k]);
//}
//printf("\n");
num[a-2]=cal(num[a-2],ch[b-1],num[a-1]);//数字栈前面的数字更新为计算后的结果
num[a-1]=0;//数字栈顶元素用完之后要清零,否则影响之后的运算, 之前的转化数字循环开始时 num[a]=num[a]*10+s[i++]-'0'; 默认num[a]的初始值是0
b--;//符号栈退一格
a--;//数字栈退一格
}
b--;//计算完括号内的式子后将左括号移除
}//如果是运算符
else{
if(b==0)//如果符号栈为空,则直接入栈
{
ch[b++]=s[i];
}
else if(com(s[i],ch[b-1])){//如果是当前运算符优先级比栈顶运算符优先级大 直接入栈
ch[b++]=s[i];
}else //果是当前运算符优先级比栈顶运算符优先级小 说明可以进行计算了
{
while(!com(s[i],ch[b-1])){
if(ch[b-1]=='(')
{
break;
}
//printf("%d %d ",num[a-2],num[a-1]);
//for(int k=0;k<b;k++)
//{
// printf("%c ",ch[k]);
//}
//printf("\n");
num[a-2]=cal(num[a-2],ch[b-1],num[a-1]);//数字栈前面的数字更新为计算后的结果
num[a-1]=0;
b--;//符号栈退一格
a--;//数字栈退一格
if(b==0)break;//如果运算符栈为空,那没办法进行计算 直接跳出循环
}
ch[b++]=s[i];//计算完成之后就可以让这个运算符进来了
}
}
}
i++;
}
while(a!=1&&b>0)//在遍历了整个字符串之后如果两个栈还没有空 那么继续 (一旦数字栈里只剩一个数字 或者运算符栈没有符号了 那就停止计算)
{
num[a-2]=cal(num[a-2],ch[b-1],num[a-1]);
a--;
b--;
//因为不会再有新数字入栈了,所以不需要再num[a-1]=0;
}
printf("%d",num[0]);//输出结果
}
诶,对于一个对算法一窍不通的菜鸡而言这种题简直就是折磨,这里特别感谢两位大佬ATFWUS和sky~key的帮助