目录
后缀表达式(逆波兰式):运算符在运算数后面,不需要括号标明运算符的优先级
后缀表达式特点:
1、运算数排列顺序与中缀表达式一样
2、运算符是按照运算顺序排列的
3、运算符紧跟在被运算数后面
中缀表达式转后缀表达式示例:
示例1:
char* str1= "2 + 3";//中缀表达式
char* str2= "2 3 +";//后缀表达式
innt result=5;
示例2:
char* str1="2 + 3 * 4";//中缀表达式
char* str2="2 3 4 * +";//后缀表达式
int result=14;
示例3:
char* str1="( 3 + 4 ) * 2 + 5";//中缀表达式
char* str2="3 4 + 2 * 5 +";//后缀表达式
int result=29;
示例4:
char* str1="2 + 3 - 4 / 2";//中缀表达式
char* str2="2 3 + 4 2 / -";//后缀表达式
int result=4;
运算法则:
1、从左向右计算
2、先计算乘除,后计算加减
3、含括号的,先算括号里面的
运算符优先级:
+ | - | * | / | % | ( | ) | /0‘ | |
栈内优先级 | 3 | 3 | 5 | 5 | 5 | 1 | 6 | 0 |
栈外优先级 | 2 | 2 | 4 | 4 | 4 | 6 | 1 | 0 |
代码实现:
函数声明:
const int EXPLEN = 128;
extern char* BuyStr(size_t sz); //动态获取空间
extern void DelStr(char* p); // 释放空间
extern bool IsOperator(char ch); // 判断是否是操作符
extern int InStackOp(char op); //栈内优先级
extern int OutStackOp(char op); //栈外优秀级
extern double Operator(double left, double right, char op); // 根据op运算符计算
extern double LastExprValue(char* laststr); // 后缀表达式求值
extern void InputMidexp(char* midstr); //输入中缀表达式
extern void PostFix(char* midstr, char* laststr); // 中缀转后缀
extern void PrintValue(int dx);
函数实现:
char* BuyStr(size_t sz) //动态获取空间
{
char* newstr = (char*)malloc(sizeof(char) * sz);
if (NULL == newstr) exit(1);
memset(newstr, 0, sizeof(char) * sz);
return newstr;
}
void DelStr(char* p) // 释放空间
{
free(p);
}
bool IsOperator(char ch) // 判断是否是操作符
{
bool res = false;
switch (ch)
{
case '+': case '-': case '*':case '/': case '(': case ')':
res = true;
break;
}
return res;
}
int InStackOp(char op) //栈内优先级
{
switch (op)
{
case '+': return 3;
case '-': return 3;
case '*': return 5;
case '/': return 5;
case '(': return 1;
case ')': return 6;
case '\0': return 0;
}
}
int OutStackOp(char op) //栈外优秀级
{
switch (op)
{
case '+': return 2;
case '-': return 2;
case '*': return 4;
case '/': return 4;
case '(': return 6;
case ')': return 1;
case '\0': return 0;
}
}
double Operator(double left, double right, char op) // 根据op运算符计算
{
double ret = 0.0;
switch (op)
{
case '+': ret = left + right; break;
case '-': ret = left - right; break;
case '*': ret = left * right; break;
case '/':
assert(right != 0.0); //
ret = left / right;
break;
default:
break;
}
return ret;
}
// laststr ="12 23 2 * +"
double LastExprValue(char* laststr) // 后缀表达式求值
{
assert(laststr != NULL);
GenLinkStack opst;
InitLinkStack(&opst, sizeof(int));
int i = 0;
int left='\0', right ='\0',ret='\0';
while (laststr[i] != '\0')
{
if (isdigit(laststr[i]))
{
int val = 0;
while (isdigit(laststr[i]))//如果不是一位数,循环遍历
{
val = val * 10 + laststr[i] - '0';
++i;
}
Push(&opst, &val);
}
else if(IsOperator(laststr[i]))
{
Pop(&opst, &right);//先出栈的作为右运算符
Pop(&opst, &left);
ret =Operator(left, right, laststr[i]);
Push(&opst, &ret);
}
i++;
}
Pop(&opst, &ret);
return ret;
}
void InputMidexp(char* midstr) //输入中缀表达式
{
assert(midstr != NULL);
printf("输入中缀表达式:\n");
//scanf("%s", midstr);
fgets(midstr, 128, stdin);//scanf 以空格结束,无法用在这里
}
void PostFix(char* midstr, char* laststr) // 中缀转后缀
{
assert(midstr != NULL && laststr != NULL);
GenLinkStack opst;
InitLinkStack(&opst, sizeof(char));
char op = '\0';
Push(&opst, &op);//先将'\0'放入,优先级最低
char* sp = laststr;
for (int i = 0; midstr[i] != '\0'; ++i)
{
if (isdigit(midstr[i]))
{
while (isdigit(midstr[i]))//不是一位数时,循环遍历直到该整数结束
{
*sp++ = midstr[i];
++i;
}
*sp++ = ' ';
if (midstr[i] == '\0') break;
}
if (IsOperator(midstr[i]))
{
if (OutStackOp(midstr[i]) > InStackOp((GetTop(&opst, &op), op)))
{
Push(&opst, &midstr[i]);//栈外运算符优先级大时,运算符入栈
}
else if (OutStackOp(midstr[i]) < InStackOp((GetTop(&opst, &op), op)))
{
Pop(&opst, &op);//站内运算符优先级小大时,运算符出栈
*sp++ = op;//后缀表达式指针指向出栈的运算符
--i;//回退一位,以便于for循环+1后保持i不变继续判断判断该栈外运算符与栈顶运算符优先级
}
else if (midstr[i] == ')' && ((GetTop(&opst, &op), op) == '('))
{
Pop(&opst, &op);//如果左括号遇见右括号,左括号出栈
}
}
}
while (!IsEmpty(&opst)&& (GetTop(&opst, &op), op)!='\0')//将栈内剩余运算符遍历完
{
char op = '\0';
Pop(&opst, &op);
*sp++ = op;
*sp++ = ' ';
}
DestroyLinkStack(&opst);
}
void PrintValue(int dx)
{
printf("the result=%d\n", dx);
}
测试函数:
int main()
{
char midstr[EXPLEN] = { 0 };
char laststr[EXPLEN] = { 0 };
InputMidexp(midstr);
PostFix(midstr,laststr);
int result=LastExprValue(laststr);
PrintValue(result);
}
测试结果: