数据结构——栈实现简易计算器

遍历表达式过程中,

        元素入符号栈的条件:

  1. 符号栈为空(即此元素是第一个符号);
  2. 此符号优先级  > 栈顶符号;
  3. 前一个符号为  '('  且此符号不是  ')' ;

        先进行阶段性计算的条件:

  1. 表达式已经全部遍历结束(无论有没有计算结束);
  2. 遍历到符号时,此符号的优先级 <= 栈顶元素;
  3. 遍历到符号时,此符号为  ')'  且前一个符号不是  ')'  ;

    表达式中有  '()'  存在时,要设置其优先级为最高。而且其中的运算结束后要手动将  '('  出栈。

linkstack.h

#ifndef __LINKSTACK_H__
#define __LINKSTACK_H__

typedef struct stack_s
{
    int data;
	struct stack_s *next;
}stack_t;

#define SUCCESS 0
#define FAILED -1

#define TRUE 1
#define FALSE -2


void stack_display(stack_t *top);
int stack_init(stack_t **top);
int push(stack_t **top,int data);
int pop(stack_t **top);
int stack_isempty(stack_t *top);
int get_top(stack_t *top);


#endif

linkstack.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkstack.h"

void stack_display(stack_t *top)
{
    stack_t *tmp = top->next;
    if(top == NULL||top->next == NULL)
	{
	    return ;
	}

    printf("========top========\n");
	while(tmp)
	{
	    printf("%d\n",tmp->data);
		tmp = tmp->next;
	}	
    printf("=======bottom=======\n");
}



int stack_init(stack_t **top)
{
    *top = (stack_t *)malloc(sizeof(stack_t));
	if(*top == NULL)
	{
	    printf("stack_init failed\n");
		return FAILED;
	}
	memset(*top,0,sizeof(stack_t));
	(*top)->next = NULL;
	(*top)->data = -1;

	return SUCCESS;
}

int push(stack_t **top,int data)
{
    stack_t *new_node = NULL;
    if(*top == NULL)
	{
	    printf("top is NULL\n");
		return FAILED;
	}

    new_node = (stack_t *)malloc(sizeof(stack_t));
	if(new_node == NULL)
	{
	    printf("push malloc failed\n");
		return FAILED;
	}
	memset(new_node,0,sizeof(stack_t));

	new_node->data = data;
	new_node->next = (*top)->next;
	(*top)->next = new_node;

	return SUCCESS;
}

int pop(stack_t **top)
{
    int data;
	stack_t *tmp = (*top)->next;
	if(*top == NULL || (*top)->next == NULL)
	{
	    printf("stack is NULL\n");
		return FAILED;
	}

	data = tmp->data;

	(*top)->next = tmp->next;
	tmp->next = NULL;
	free(tmp);

	return data;
}

int stack_isempty(stack_t *top)
{
    if(top == NULL || top->next == NULL)
		return TRUE;
	else
		return FALSE;
}

int get_top(stack_t *top)
{
    if(top == NULL || top->next == NULL)
	{
	    printf("stack is NULL\n");
		return FAILED;
	}

	return top->next->data;
}

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkstack.h"

int priority(char opt)
{
    switch(opt)
	{
	    case '(':
			return 3;
	    case '*':
		case '/':
			return 2;
	    case '+':
		case '-':
			return 1;
		default :
		    return 0;
	}
}

int main()
{
    stack_t *s_num = NULL;	
    stack_t *s_opt = NULL;
    char expr[1024] = {0};
	int tmp = 0;
	int num1 = 0;
	int num2 = 0;
	int i = 0;
	int ret;

	//判空
	if(stack_init(&s_num) == FAILED || stack_init(&s_opt) == FAILED)
	{
	    printf("stack_init failed\n");
		return FAILED;
	}

	printf("please input expr:");
	scanf("%s",expr);
													/* ?????? */
	while(expr[i] != '\0' || stack_isempty(s_opt) != TRUE)
	{	//如果数字和符号已经全部入栈	或者数字和符号已经全部入栈但是运算还没有完全结束,就继续循环
	    while(expr[i] >= '0' && expr[i] <= '9')
    	{	//只要是数字,就进来转化	并且 i 后移
    	    tmp = tmp * 10 + expr[i] - '0';
			i++;
			if(expr[i] < '0' || expr[i] > '9')
			{	//只要下一个字符是符号,就将先前转化好的数字入栈  出了这个while之后,符号另作处理
				ret = push(&s_num, tmp);
				if(ret == FAILED)
				{
					printf("push failed\n");
					return FAILED;
				}
				tmp = 0;				//tmp用完之后要置 0 ,以备下次重新赋值使用
			}
    	}
		
		//清除符号栈残余的'('  //有 '()' 的情况下, '()' 里的运算结束之后‘(’仍在符号栈内,需要手动清除
	    if(expr[i] == ')' && get_top(s_opt) == '(')
	    {	//如果此符号是 ')' 并且经过计算后栈顶符号是 '(' ,就将 '(' pop出去
	        pop(&s_opt);
			i++;
			continue;				//符号入栈后立即结束当前次循环,进行新一轮的while判断
	    }
			
		if((stack_isempty(s_opt) == TRUE) ||
	    //如果符号栈为空   或者
			(priority(expr[i]) > priority(get_top(s_opt)))||
			//此符号的优先级 > 栈顶符号		或者
			((get_top(s_opt) == '(') && (expr[i] != ')')))
			//栈顶符号为 '(' 并且此符号不是 ')'
	    {	/*就将符号入栈   并且 i 后移*/
	        push(&s_opt, expr[i]);
			i++;
			continue;		//表达式中符号后面必定为数字,所以必须要重启大循环
	    }
		
													/* 不需要 */
		if(((expr[i] == '\0' )&&(stack_isempty(s_opt) != TRUE))||
		//如果表达式入栈完毕并且符号栈有符号,  或者
			(priority(expr[i]) <= priority(get_top(s_opt)))||
			//此符号的优先级 < = 栈顶符号,		或者
			((expr[i] == ')' && get_top(s_opt) != '(')))
			//此符号是 ')' 并且栈顶符号不是 '('		(表达式入栈时候会出现的情况)						,
		{	/* 就先计算 */
			switch (pop(&s_opt))
			{
				case '+':
					num2 = pop(&s_num);
					num1 = pop(&s_num);
				    push(&s_num,(num1 + num2));//阶段性的计算结果先入栈而不是马上输出是为了后续计算使用
					break;
			    case '-':
					num2 = pop(&s_num);
					num1 = pop(&s_num);
					push(&s_num,(num1 - num2));
					break;
				case '*':
					num2 = pop(&s_num);
					num1 = pop(&s_num);
					push(&s_num,(num1 * num2));
					break;
				case '/':					
					num2 = pop(&s_num);
					num1 = pop(&s_num);
					push(&s_num,(num1 / num2));
					break;
				default :
				    return FAILED;
			}
		}
	}

    printf("reslut is %d\n",get_top(s_num));
	return 0;
}



#if 0
int main()
{
    int ret;
	int i;
	stack_t *top = NULL;

	ret = stack_init(&top);
	if(ret == FAILED)
	{
	    printf("stack_init failed\n");
		return FAILED;
	}

	for(i = 0;i < 5;i++)
	{
	    ret = push(&top, i);
		if(ret == FAILED)
		{
		    printf("push failed\n");
			return FAILED;
		}
	}

    if(stack_isempty(top) == TRUE)
		printf("satck is NULL\n");
	else
		printf("stack is not NULL\n");


	ret = get_top(top);
	if(ret == FAILED)
	{
	    printf("get_top failed\n");
		return FAILED;
	}
	printf("top data is %d\n",ret);
	
	stack_display(top);

	for(i = 0; i< 5;i++)
	{
	    ret = pop(&top);
		if(ret == FAILED)
		{
		    printf("pop failed\n");
			return FAILED;
		}

		printf("pop data is %d\n",ret);
	}

    if(stack_isempty(top) == TRUE)
		printf("satck is NULL\n");
	else
		printf("stack is not NULL\n");
	stack_display(top);
	return 0;
}
#endif

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值