栈的一些功能函数,这边用到的是链式栈。
typedef char ElemType;
//结点的信息
struct node
{
ElemType data; //数据域
struct node *next; //指针域
};
typedef struct node Node;
//栈的信息
struct stack
{
Node *top; //头指针
int count; //结点个数
};
typedef struct stack Stack;
//初始化
int StackInit(Stack **s)
{
(*s) = (Stack *)malloc(sizeof(Stack) * 1);
(*s)->top = NULL;
(*s)->count = 0;
}
//初始化只要分配栈信息结构体的空间,结点的空间等到进栈的时候再分配。
//进栈:
int push(Stack **s, ElemType e)
{
Node *p = (Node *)malloc(sizeof(Node)); //给结点分配空间
p->data = e; //数据域
p->next = (*s)->top;
(*s)->top = p;
(*s)->count++;
}
//出栈:
int pop(Stack **s)
{
Node *p = (*s)->top;
ElemType e = (*s)->top->data;
(*s)->top = (*s)->top->next;
(*s)->count--;
free(p);
}
首先定义两个栈,一个叫s_num用来存放操作数,另一个叫s_opt用来存放操作符。
再定义一个字符数组用来存放输入的表达式,初始化为0;
当表达式的字符不为‘/0’时,或者操作符栈中不为空的时候,就要一直执行程序!
在执行的时候做两个判断,输入的不是数字就是操作符,当输入数字的时候进栈就可以了,并且i++,遍历下一个。
当遇到操作符时:有三种情况
一、入栈的情况:(入栈结束后,i++,遍历下一个输入字符)
1.操作符栈为空的时候。
2.操作符的优先级大于栈顶元素的时候。
3.当栈顶元素为’(‘时,并且输入不为')'时。
二、出栈不计算(结束后,i++,遍历下一个字符)
1.操作符出栈不计算的情况只有一种情况就是“( ”操作符出栈的时候。
当输入为“ )”时,并且栈顶为“( ”时,就是两个符号相遇时,出栈“( ”并不计算。
三、出栈计算(计算完将数字存入s_num中就可以了,不需要遍历下一个字符)
将输入的字符与栈顶元素比较,满足情况的话将栈顶元素出栈,并取num栈中的数字进行运算,这是不需要i++,遍历下一个输入字符,break后再将输入的字符与栈顶元素比较,判断是入栈还是出栈!!!
1.输入的操作符为"/0"的时候,并且操作符栈不为空的时候,要将操作符中的所有元素出栈运算。
2.输入的操作符优先级小于或等于栈顶元素时。
3.当输入的字符为“ )”时,并且栈顶元素不为“( ”时。
#include <stdio.h>
#include "LinkStack.h"
int Priority(char ch)
{
switch(ch)
{
case '(':
return 3;
case '*':
case '/':
return 2;
case '+':
case '-':
return 1;
default:
return 0;
}
}
int main()
{
Stack *s_opt, *s_num;
char opt[1024] = {0}; //存放表达式
int i = 0, tmp = 0, num1 = 0, num2 = 0;
if (StackInit(&s_opt) != SUCCESS || StackInit(&s_num) != SUCCESS)
{
printf("Init Failure!\n");
}
printf("Please input : \n");
scanf("%s", opt);
while (opt[i] != '\0' || StackEmpty(s_opt) != TRUE) //表达式没结束 或者 操作符栈不为空 一直执行这个循环
{
//输入的时候不是数字就是操作符分两次判断
if (opt[i] >= '0' && opt[i] <= '9') //当输入为数字的时候
{
tmp = tmp * 10 + opt[i] - '0';
i++;
if (opt[i] > '9' || opt[i] < '0') //如果数组后面为操作符时直接入栈,但是如果数字后面还是数字的话就是两位数
{
push(&s_num, tmp); //入栈 写入到接受数字的那个栈
tmp = 0;
}
}
else //如果输入是操作符 分三种情况
{
if (opt[i] == ')' && GetTop(s_opt) == '(')
//1.操作符直接出栈不计算 当输入遇到‘)’时,并且栈顶为‘(’时
{
pop(&s_opt);
i++;
continue;
}
if (StackEmpty(s_opt) == TRUE || (Priority(opt[i]) > Priority(GetTop(s_opt)))
|| (GetTop(s_opt) == '(' && opt[i] != ')'))
//2.操作符进栈,三种可能
1)操作符栈为空的时候,
2)操作符优先级大于栈顶的时候,
3)栈顶为‘(’时任何操作符都能进栈,除了‘)’!
{
push(&s_opt, opt[i]);
i++;
continue;
}
if ((opt[i] == '\0' && StackEmpty(s_opt) != TRUE) ||
(opt[i] == ')' && GetTop(s_opt) != '(') ||
(Priority(opt[i]) <= Priority(GetTop(s_opt))))
//3.操作符出栈平取操作数栈的前两个进行计算,三种可能
1)当表达式输入结束接收到字符'\0'时并且操作符栈不为空的时候,这时候要将操作符栈出光,
2)输入遇到字符‘)’时,栈顶不为‘(’时,
3)当输入操作符的优先级小于等于栈顶操作符优先级的时候
{
switch(pop(&s_opt))
{
case '+':
num1 = pop(&s_num);
num2 = pop(&s_num);
push(&s_num, (num1 + num2));
break;
case '-':
num1 = pop(&s_num);
num2 = pop(&s_num);
push(&s_num, (num2 - num1));
break;
case '*':
num1 = pop(&s_num);
num2 = pop(&s_num);
push(&s_num, (num1 * num2));
break;
case '/':
num1 = pop(&s_num);
num2 = pop(&s_num);
push(&s_num, (num2 / num1));
break;
}
}
}
}
printf("%d\n", GetTop(s_num));
return 0;
}