1、问题
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+、-、*、\以及左右括号(),表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
2、解决思路
中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
转换过程需要用到栈,具体过程如下:
1)如果遇到操作数,我们就直接将其输出。
2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( "。
5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
注意点
1、测试点3 运算数前有正负号
分两种情况:1、+ - 是第一个字符;2、+ - 出现在 ‘(’ 之后,则表示正负
陷阱:当+表示正负时,不予输出
测试用例:
输入:-2*(+2-2)
输出:-2 2 2 - *
3、我的代码
#include <stdio.h>
#include <stdlib.h>
char str[25];
char st[20];
int top=-1;
int main()
{
gets(str);
int len=0,count=0;//len是需要打印的字符的个数 ,count表示已打印的字符个数
for(int i=0;str[i]!='\0';i++)
{
if(str[i]!='('&&str[i]!=')')
len++;
}
for(int i=0;str[i]!='\0';i++)
{
if(str[i]=='(')
{
st[++top]=str[i];
}
else if(str[i]=='*'||str[i]=='/')
{
while(top>-1&&(st[top]=='*'||st[top]=='/'))
{
printf("%c",st[top--]);
count++;
if(count!=len)
printf(" ");
}
st[++top]=str[i];
}
else if(str[i]=='+'||str[i]=='-')
{
//以下情况表示正负
if(i==0||(i>0&&str[i-1]=='(') )
{
+表示正负时无需打印
if(str[i]=='+')
{
count++;//表示跳过 实际没打印
}
else
{
printf("%c",str[i]);
count++;
}
continue;
}
while(top>-1&&st[top]!='(')
{
printf("%c",st[top--]);
count++;
if(count!=len)
printf(" ");
}
st[++top]=str[i];
}
else if(str[i]==')')
{
while(st[top]!='(')
{
printf("%c",st[top--]);
count++;
if(count!=len)
printf(" ");
}
top--;
}
else
{
printf("%c",str[i]);
count++;
if(count!=len&&(str[i+1]<'0'||str[i+1]>'9')&&str[i+1]!='.')
printf(" ");
}
}
while(top!=-1)
{
printf("%c",st[top--]);
count++;
if(count!=len)
printf(" ");
}
return 0;
}