您的位置:首页 > 其它

栈的应用:计算字符串表达式

2017-08-29 13:42 381 查看

说明:

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



2.isOperator



3.isLeft



4.isRight



5.priority



6.express



7.transform



8.compute

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: