上一篇文章是后缀表达式求值,由于后缀表达式不是我们人类能接受的求值表达式,so本文为中缀表达式转换为后缀表达式的方法。然后再结合上一篇逆波兰表达式,我们就可以利用中缀表达式求值啦!!!!本文的代码依然可以计算带小数点,大于10的数字的表达式!
思路:
一、遇到数字,直接存入字符串中。
二、遇到的是表达式符号(+,-,*,/,(,)):
1、如果栈为空,或者表达式为左括号‘(’,直接压入栈中;
2、做出栈操作,出栈元素存入c1,与待输入的符号c2进行比较,如果c1的优先级高于c2,则将c1存到结果字符串结尾,跳转到第1条,重新判断!
三、比较完毕后,将栈中剩余的元素弹出存到结果字符串的尾部!
关于栈的声明与定义就不再赘述,直接进入代码:
void toPolish()
{
SqStack s;
StackInit(&s);
char c;
char str[100]; //用于存储后缀表达式的结果字符串
int i=0; //字符数组下标,初始化为0
printf("请输入正确的中缀表达式,以#结束输入。\n");
scanf("%c",&c);
while (c!='#')
{
if (isdigit(c) || c=='.')
{/*大于10的数位数之间不能有空格,所以先做判断再循环,循环结束后加空格,结尾在赋'\0'*/
while(isdigit(c) || c=='.')
{
str[i++]=c;
scanf("%c",&c);
}
str[i++]=' ';
str[i]='\0';
}
if(c=='#')break; /*如果数字之后是#的话,此处判断才是大循环的结束之处,否则在循环结束后再输入会造成死循环,不理解可以下断点试试*/
if (c=='(') //右括号直接压栈
{
Push(&s,c);
}
if (c==')') //左括号则做出栈并赋给结果字符串中,再将有括号也弹出栈。
{
while(*(s.top)!='(')
{
Pop(&s,&str[i]);
i++;
str[i++]=' ';
str[i]='\0';
}
char temp;
Pop(&s,&temp);
}
if (c=='+' || c== '-' || c=='*' || c=='/') //判断是否为符号,封装起来也许更我,我没做而已
{
if (s.top-s.base==0 || *(s.top)=='(') //如果空栈或栈顶为(,入栈
{
Push(&s,c);
}
else
{
char temp;
Pop(&s,&temp);
if (judge(temp,c)) //重点,判断栈顶和当前的符号优先级,并左相应操作,相关代码在后面
{
str[i++]=temp;
str[i++]=' ';
str[i]='\0';
continue;
}
else
{
Push(&s,temp);
Push(&s,c);
}
}
}
scanf("%c",&c);
}
while (s.top-s.base>0) //把栈中剩余元素赋给结果数组
{
Pop(&s,&str[i]);
i++;
str[i++]=' ';
str[i]='\0';
}
str[i++]='#';
str[i]='\0';
puts(str);
system("pause");
return 0;
}
这个函数是用来判断c1 与c2谁的优先级更高,true代表c1>c2,false代表c1<c2;
方法挺傻的,copy一下倒是蛮方便,呵呵!
//判断表达式符号(+ - * /)c1,c2的优先级,有人用数组的方式左,反正就是个方法而已无所谓!
bool judge(char c1,char c2)
{
switch(c1)
{
case '+':
{
switch(c2)
{
case '+':
return true;
case '-':
return true;
case '*':
return false;
case '/':
return false;
}
}
case '-':
{
switch(c2)
{
case '+':
return true;
case '-':
return true;
case '*':
return false;
case '/':
return false;
}
}
case '*':
{
switch(c2)
{
case '+':
return true;
case '-':
return true;
case '*':
return true;
case '/':
return true;
}
}
case '/':
{
switch(c2)
{
case '+':
return true;
case '-':
return true;
case '*':
return true;
case '/':
return true;
}
}
}
}
输出结果:
小结:表达式求值就到此结束了,不论哪个版本的数据结构,算法的参考资料里,学习栈时,表达式求值都是很经典的例子!它充分的利用了栈的原理进行操作!
当初刚接触栈时,表达式求值对我来说简直是个噩梦!过来再看,对栈的理解更深刻了!