#include <stdio.h>
#include "SqStack.h"
//判断是否是数字
int is_digital_str(char ch)
{
if(ch >= '0' && ch <= '9')
{
return 1;
}
return 0;
}
//判断是否为符号
int is_operand_str(char ch)
{
if(ch == '*' || ch == '+' || ch == '-' || ch == '%' || ch == '/')
{
return 1;
}
return 0;
}
//判断是否进栈 优先级 ch1是待进栈元素 ch2是栈顶元素
int is_compare_operand(char ch1,char ch2) //大可以从反面来看,以少胜多,只有一种情况栈顶元素不出栈
{
if( (ch1 == '*' || ch1 == '%' || ch1 == '/') && (ch2 == '+' || ch2 == '-'))
{
return 1;
}
return 0;
}
//计算吧肿瘤君
int calculate(struct SqStack*sq,struct SqStack*so)
{
//数字出栈
int a,b;
pop(sq,&b);
pop(sq,&a);
//符号出栈
int c;
pop(so,&c);
switch (c) //switch 语句来解决冗杂的问题
{
case '*': return a*b;
case '%': return a%b;
case '/': return a/b;
case '+': return a+b;
case '-': return a-b;
default:
return 0;
}
}
//计算器
int expression(char *str)
{
//如果表达式为空则返回零
if(str == NULL)
{
printf("你只是没输入数字");
return 0;
}
//初始化栈
struct SqStack * sq = InitStack(); //数字栈
struct SqStack * so = InitStack(); //符号栈
while(*str) //首地址的指针传进来
{
int sum = 0; //用来存高位数
while(is_digital_str(*str)) //因为要对他进行操作,所以传进来
{
sum = sum*10 + (*str-'0');
str++;
}
push(sq,sum);
if(*str == '\0') //字符串结束
{
break;
}
if(is_operand_str(*str)) //如果是操作符就进来
{
while(1)
{
int top;
GetTop(so,&top); //具现化栈顶元素
//栈里没有符号或者栈里优先级低就入栈
if(IsEmpty(so) || is_compare_operand(*str,top))
{
push(so,*str);
break;
}
else //不进栈我就出栈,逆水行舟,不进则退
{
int gap = calculate(sq,so); //出栈计算函数
//把结果入栈
push(sq,gap);
}
}
}
str++;
}
while( ! IsEmpty(so) ) //符号栈不为空
{
//如果最后符号栈还有元素就全部拿出来计算
push(sq,calculate(sq,so));
}
int ret; //拿出最后的结果
pop(sq,&ret);
Destroy_Stack(sq);
Destroy_Stack(so);
return ret;
}
int main()
{
char str[100] = {0};
scanf("%s",str);
int k = expression(str);
printf("%d",k);
return 0;
}
栈相关的代码
#include "SqStack.h"
#include <stdio.h>
#include <stdlib.h>
//对栈初始化
struct SqStack * InitStack()
{
struct SqStack * s = malloc(sizeof(struct SqStack));
s->data = malloc(sizeof(ElemType) * MAX_LEN);
s->top = -1;
return s;
}
//摧毁栈
void Destroy_Stack(struct SqStack*s)
{
if(s == NULL) //销毁成功
{
return ;
}
if(s->data) //栈里有数据
{
s->top = -1; /*清空之后只能入栈,从-1开始,会把原来的数据覆盖,相应的在出栈的时候
是从新的top开始,只有被更新的数据才会出来*/
free(s->data); //释放空间
}
}
//清空栈
void ClearStack(struct SqStack * s)
{
if(s) //栈存在
{
s->top = -1; //只需要把下表置为-1,他下一个元素入栈时会自动更新,不需要再主动删除
}
}
//判断栈是否为空
int IsEmpty(struct SqStack *s)
{
if(s == NULL || s->top == -1)
{
return 1;
}
return 0;
}
//求栈长度
int StackLength(struct SqStack *s)
{
if(s == NULL)
{
return 0;
}
return s->top+1;
}
//出栈
int pop(struct SqStack *s,ElemType *x)
{
//栈为空(s不存在或者s->data这个数组不存在,里面没有东西)
if(s == NULL || s->data == NULL || s->top == -1)
{
printf("出栈失败");
return 0;
}
else
{
*x = s->data[(s->top)--]; /*获取栈顶元素,为什么要传地址?如果传进来的是一个值
因为形参和实参的作用域,他不会把值传出去,所以要传地址进来
让他们指向同一个地址,值才会同时改变*/
return 1;
}
}
/*
出栈
返回值:
1 出栈成功
0 出栈失败
*/
int push(struct SqStack *s,ElemType x)/*进栈时不需要传地址,是因为它只需要对栈进行操作,形参的变化不关心*/
{
//当栈为空(s不存在,s->data这个数组不存在),栈满了时不可入栈
if(s == NULL || s->data == NULL || s->top == MAX_LEN-1) //栈从零开始计数
{
printf("入栈失败");
return 0;
}
s->data[++(s->top)] = x;
return 1;
}
//获取栈顶元素,但不销毁他
int GetTop(struct SqStack *s,ElemType *x)
{
//栈为空,没有数据
if(s == NULL || s->data == NULL || s->top == -1)
{
printf("里面没有数");
return 0;
}
*x = s->data[(s->top)];
return 1;
}
自定义头文件
#ifndef __SQSTACK_H__
#define __SQSTACK_H__
#define MAX_LEN 10
typedef int ElemType;
typedef struct SqStack
{
ElemType * data;//data指向一块地址连续的空间,来存储栈的每一个元素
// data = malloc( sizeof(ElemType) * MAX_LEN );
// ElemType data[MAX_LEN];
int top; //栈顶,指定栈顶元素的下标
// top == -1 表示栈中没有元素,空栈
}SQSTACK;
struct SqStack * InitStack();
int push(struct SqStack *s,ElemType x);
int pop(struct SqStack *s,ElemType *x);
int StackLength(struct SqStack *s);
void Destroy_Stack(struct SqStack*s);
void ClearStack(struct SqStack * s);
int GetTop(struct SqStack *s,ElemType *x);
int IsEmpty(struct SqStack *s);
#endif