说明:
1. 通过栈来实现字符串公式的运算;
2. 中缀转后缀:
遍历中缀表达式中的数字和符号
对于数字: 直接输出
对于符号:
->左括号: 进栈
->符号: 与栈顶符号进行优先级比较
栈顶符号的优先级低: 符号进栈
栈顶符号的优先级高: 将栈顶符号弹出并输出,之后进栈
->右括号: 将栈中的所有符号弹出并输出3. 计算后缀的值:
遍历后缀表达式中的数字和符号
对于数字: 进栈
对于符号:
->从栈中弹出右操作数
->从栈中弹出左操作数
->根据符号进行运算
->将运算结果压入栈中
遍历结束:栈中的唯一数字为计算结果4. 这里采用了代码复用的方法,即使用了LinkList链表和LinkStack链栈,详见《LinkList单向链表》和 《LinkStack链栈》;
代码:
main.c
#include <stdio.h>
#include "LinkStack.h"
//输出
void output(char c)
{
if (c != '\0')
{
printf("%c", c);
}
}
//判断是否为数字
int isNumber(char c)
{
return ('0' <= c) && (c <= '9');
}
//判断是否为操作符
int isOperator(char c)
{
return (c == '+') || (c == '-') || (c == '*') || (c == '/');
}
//是否为'('
int isLeft(char c)
{
return (c == '(');
}
//是否为')'
int isRight(char c)
{
return (c == ')');
}
//比较优先级
int priority(char c)
{
int ret = 0;
if ((c == '+') || (c == '-'))
{
ret = 1;
}
if ((c == '*') || (c == '/'))
{
ret = 2;
}
return ret;
}
//字符转数字
int value(char c)
{
return (c - '0');
}
//计算左右操作数的值
int express(int left, int right, char op)
{
int ret = 0;
switch (op)
{
case '+':
ret = left + right;
break;
case '-':
ret = left - right;
break;
case '*':
ret = left * right;
break;
case '/':
ret = left / right;
break;
default:
break;
}
return ret;
}
//中缀转后缀,返回后缀字符串,并输出
char* transform(const char* exp)
{
LinkStack* stack = LinkStack_Create();
char* ret = (char*)malloc(100 * sizeof(char));
memset(ret, '\0', 100 * sizeof(char));
int j = 0;
int i = 0;
while (exp[i] != '\0')
{
int i = 10 * (1 + 5) + 5;
//判断是否为数字
if (isNumber(exp[i]))
{
output(exp[i]);
ret[j++] = exp[i];
}
//判断是否为操作符
else if (isOperator(exp[i]))
{
//遍历栈内符号,如果当前操作符的优先级小于栈顶的操作符,则弹出栈顶,并输出
while (priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)))
{
output(ret[j++] = (char)(int)LinkStack_Pop(stack));
}
//将当前操作符压入栈
LinkStack_Push(stack, (void*)(int)exp[i]);
}
//判断是否为'('
else if (isLeft(exp[i]))
{
LinkStack_Push(stack, (void*)(int)exp[i]);
}
//判断是否为')'
else if (isRight(exp[i]))
{
char c = '\0';
//遍历栈内元素,弹出非 '(' 的元素
while (!isLeft((char)(int)LinkStack_Top(stack)))
{
output(ret[j++] = (char)(int)LinkStack_Pop(stack));
}
//弹出'('
LinkStack_Pop(stack);
}
else
{
printf("Invalid expression!");
break;
}
i++;
}
//弹出栈内所有元素
while ((LinkStack_Size(stack) > 0) && (exp[i] == '\0'))
{
output(ret[j++] = (char)(int)LinkStack_Pop(stack));
}
LinkStack_Destroy(stack);
return ret;
}
//计算整个表达式的值
int compute(const char* exp)
{
LinkStack* stack = LinkStack_Create();
int ret = 0;
int i = 0;
while (exp[i] != '\0')
{
if (isNumber(exp[i]))
{
LinkStack_Push(stack, (void*)value(exp[i]));
}
else if (isOperator(exp[i]))
{
int right = (int)LinkStack_Pop(stack);
int left = (int)LinkStack_Pop(stack);
int result = express(left, right, exp[i]);
LinkStack_Push(stack, (void*)result);
}
else
{
printf("Invalid expression!");
break;
}
i++;
}
if ((LinkStack_Size(stack) == 1) && (exp[i] == '\0'))
{
ret = (int)LinkStack_Pop(stack);
}
else
{
printf("Invalid expression!");
}
LinkStack_Destroy(stack);
return ret;
}
int main()
{
printf("8 * 2 + 1 - ( 5 - 1 ) / 2 + 2 - 1\n中缀转后缀后结果为:");
char* _strExpression = transform("8*2+1-(5-1)/2+2-1");
printf("\n");
printf("计算结果为:%d ", compute(_strExpression));
printf("\n");
system("pause");
return 0;
}
函数结构分析:
1.isNumber
![](http://i.imgur.com/KpRA3UZ.png=400x400)
2.isOperator
![](http://i.imgur.com/GEMgI17.png=400x400)
3.isLeft
![](http://i.imgur.com/ydIrOAy.png=400x400)
4.isRight
![](http://i.imgur.com/UzRaOje.png=400x400)
5.priority
![](http://i.imgur.com/f387jx2.png=400x400)
6.express
![](http://i.imgur.com/8ALFuBQ.png=400x400)
7.transform
![](http://i.imgur.com/FlZ00YF.png=400x400)
8.compute
![](http://i.imgur.com/4u9dYSb.png=400x400)