持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情
1、思路
中缀表达式就是我们常用的表达式的形式如 1+2*(8-5)-4/2,我们自己是可以一眼看出先算括号里的,然后是乘除优先于加减计算。但是计算机不行,我们需要把中缀表达式转化成后缀表达式让计算机去计算。
(1)初始化算符栈S,将结束符‘#’压入栈S中
(2)从中缀表达式中读入字符给w
(3)当栈顶为‘#’并且w也是‘#’时结束;否则循环以下步骤:
(3-1)如果w是操作符,直接把它给后缀表达式,读取下一个字符,转到步骤(3)
(3-2-1)如果栈顶为右括号'('并且w为左括号')',就出栈且不把出栈元素给后缀表达式,然后读取下一个字符,之后转到步骤(3)
(3-2-2)如果栈顶为右括号'('或者栈顶优先级小于w的优先级,则w入栈,读取下一个字符,转到步骤(3),否则从栈出栈给到后缀表达式。
2、代码解析
//中缀表达式转后缀表达式
//设置优先级,数字大的优先级高
int priority(char op)
{
switch (op)
{
case '#':return 1; break;//1级
case ')':return 2; break;//2级
case '+':
case '-':return 3; break;//3级
case '*':
case '/':return 4; break;//4级
case '(':return 5; break;//5级
default:
return 0;
break;
}
}
int infix_exp_value(char * infixexp, char * postfixexp)//infixexp中缀 postfixexp后缀
{
PSeqStack S;//这个栈是用装符号的栈,用于解决优先级的问题
char c, w, topelement;//c永远是栈顶元素
S = Init_SeqStack();
if (!S)
{
//pritnf("栈初始化失败!");
return 0;
}
Push_SeqStack(S, '#');//这才入一个
w = *infixexp;//w是字符,不是指针??
while ((GetTop_SeqStack(S, &c), c) != '#' || w != '#')//栈顶元素返回给c 逗号表达式
{
if (IsNum(w))//如果是数字,就直接给到字符串
{
*postfixexp = w;
postfixexp++;
w = *(++infixexp);//读取下一个字符
}
else//如果w符号
{
if ((GetTop_SeqStack(S, &c), c) == '('&&w == ')')//去括号,得到的w是算符,且发生‘(’ 和‘)’的匹配,就把括号中的字符给到后缀表达式的字符串
{
Pop_SeqStack(S, &topelement);//用toplement吸收掉‘(’
w = *(++infixexp);//读取下一个字符
}
else//如果读的w是算符,且不发生‘(’ 和‘)’的匹配
{
//
if ((GetTop_SeqStack(S, &c), c) == '(' || priority((GetTop_SeqStack(S, &c), c)) < priority(w))
{//翻译:如果栈顶元素是'('或者栈顶元素的优先级小于当前字符,就把w压入栈内,然后读取下一个字符
Push_SeqStack(S, w);
w = *(++infixexp);
}
else
{
Pop_SeqStack(S, &topelement);//出栈
*postfixexp = topelement;
postfixexp++;
}
}
}
}
*postfixexp = '#';
*(++postfixexp) = '\0';//结果就直接是值传递给了postfixexp 他是一个char *postfixexp
Destroy_SeqStack(&S);
return 1;
}
//中缀转后缀测试
void test03()
{
char *infixexp = "(4*5)-8/2#";
char *postfixexp;
postfixexp = (char*)malloc(sizeof(char));
infix_exp_value(infixexp, postfixexp);
puts(postfixexp);
printf("%.2f", postfix_exp(postfixexp));
}
3、用例测试结果
char *infixexp = "(4*5)-8/2#";