数据结构之栈实现计算器

该博客介绍了如何利用数据结构中的栈来实现一个基本的计算器,能够处理包括四则运算及括号在内的数学表达式,实现终端输入表达式并计算其值的功能。
摘要由CSDN通过智能技术生成

在终端输入一个表达式(四则运算及括号),计算表达式的值。

calculator.h

#ifndef __CALCULATOR_H__
#define __CALCULATOR_H__

#define TRUE 1
#define FALSE 0

#define MAX 100
typedef int StackNum;

typedef char StackOp;

typedef struct _num
{
	StackNum data;
	struct _num *next;
}Num_node;

typedef struct _op
{
	StackOp data;
	struct _op *next;
}Op_node;

typedef struct _linkStack
{
	Num_node *numtop;
	Op_node *optop;	
}LinkStack;


//创建链式栈
LinkStack * Create_Stack ();

//判断操作数栈空
int StackEmpty_num (LinkStack *s);

//判断运算符栈空
int StackEmpty_op (LinkStack *s);

//进操作数栈
int Push_num (LinkStack *s,StackNum num);

//进运算符栈
int Push_op (LinkStack *s,StackOp op);

//出操作数栈
int Pop_num (LinkStack *s,StackNum *num);

//出运算符栈
int Pop_op (LinkStack *s,StackOp *op);

//获取运算符栈顶元素
int GetTop_op (LinkStack *s,StackOp *op);

//比较运算符优先级
int Cmp_op (LinkStack *s,StackOp op);

//运算
int Operate (LinkStack *s);



//销毁栈
int Destory(LinkStack *s);


#endif  //__CALCULATOR_H__

calculator.c

#include <stdlib.h>
#include "calculator.h"
#include "error.h"

//创建链式栈
LinkStack * Create_Stack ()
{
	LinkStack * s = (LinkStack *)malloc(sizeof(LinkStack)/sizeof(char));
	if (s == NULL)
	{
		errno = MALLOC_ERROR;
		return NULL;
	}
	s->numtop = NULL;
	s->optop = NULL;
	return s;
}

//判断操作数栈空
int StackEmpty_num (LinkStack *s)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	return s->numtop == NULL;
}

//判断运算符栈空
int StackEmpty_op (LinkStack *s)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	return s->optop == NULL;
}

//进操作数栈
int Push_num (LinkStack *s,StackNum num)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	Num_node * num_node = (Num_node *)malloc(sizeof(Num_node)/sizeof(char));
	if (num_node == NULL)
	{
		errno = MALLOC_ERROR;
		return FALSE;
	}
	num_node->data = num;
	num_node->next = s->numtop;
	s->numtop = num_node;
	return TRUE;
}

//进运算符栈
int Push_op (LinkStack *s,StackOp op)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	Op_node * op_node = (Op_node *)malloc(sizeof(Op_node)/sizeof(char));
	if (op_node == NULL)
	{
		errno = MALLOC_ERROR;
		return FALSE;
	}
	op_node->data = op;
	op_node->next = s->optop;
	s->optop = op_node;
	return TRUE;
}

//出操作数栈
int Pop_num (LinkStack *s,StackNum *num)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	if (StackEmpty_num (s))
	{
		errno = EMPTY_STACK;
		return FALSE;
	}
	Num_node *p = s->numtop;
	*num = p->data;
	s->numtop = p->next;
	free(p);
	return TRUE;
}

//出运算符栈
int Pop_op (LinkStack *s,StackOp *op)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	if (StackEmpty_op (s))
	{
		errno = EMPTY_STACK;
		return FALSE;
	}
	Op_node *p = s->optop;
	*op = p->data;
	s->optop = p->next;
	free(p);
	return TRUE;
}


//获取运算符栈顶元素
int GetTop_op (LinkStack *s,StackOp *op)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	if (StackEmpty_op (s))
	{
		errno = EMPTY_STACK;
		return FALSE;
	}
	*op = s->optop->data;
	return TRUE;
}

//比较运算符优先级
int Cmp_op (LinkStack *s,StackOp op)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	if (StackEmpty_op (s))
	{
		return TRUE;
	}
	StackOp op2;
	GetTop_op (s,&op2);
	switch (op2)
	{
		case '+':
		{
			return TRUE;
		}
		case '-':
		{
			if (op == '-' || op == '+')
			{
				return FALSE;
			}
			return TRUE;
		}
		case '*':
		{
			return FALSE;
		}
		case '/':
		{
			return FALSE;
		}
		default :
			return TRUE;
	}
}

//运算
int Operate (LinkStack *s)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	if (StackEmpty_op (s))
	{
		errno = EMPTY_STACK;
		return FALSE;
	}
	StackOp op;
	Pop_op (s,&op);
	if (op == '(')
	{
		return FALSE;
	}
	StackNum num1,num2;
	Pop_num (s,&num1);
	if (StackEmpty_num (s))
	{
		Push_num (s,num1);
		return FALSE;
	}
	Pop_num (s,&num2);
	StackNum result;
	switch (op)
	{
		case '+':
			result = num2 + num1;
			break;
		case '-':
			result = num2 - num1;
			break;
		case '*':
			result = num2 * num1;
			break;
		case '/':
			result = num2 / num1;
			break;
		default:
			return FALSE;
	}
	Push_num (s,result);
	return TRUE;	
}


//销毁栈
int Destory(LinkStack *s)
{
	if (s == NULL)
	{
		errno = ERROR;
		return FALSE;
	}
	free(s);
	return TRUE;
}

main.c

#include <stdio.h>
#include "calculator.h"
#include "error.h"
#include <stdlib.h>

int main()
{
	LinkStack *s = Create_Stack ();
	char exp[MAX];
	printf ("input an expression:");
	fgets(exp,MAX,stdin);
	if (exp[0] < '0' || exp[0] > '9')
	{
		if (exp[0] != '(')
		{
			errno = INPUT_ERROR;
			MyError ("fgets:");
			printf ("输入错误,第一个字符应该为数字或“(”\n");
			Destory(s);
			return FALSE;
		}
	}
	int i = 0;
	while (exp[i])
	{
		if (exp[i] == '\n')
		{
			exp[i] = '\0';
			break;
		}
		i++;
	}
	i = 0;
	char *p = exp;
	char *tmp = p;
	int flag = 0;
	while (p[i])
	{
		if (p[i] >= '0' && p[i] <= '9')
		{
			i++;
			flag = 1;
			continue;
		}
		if (flag == 1)
		{
			Push_num (s,atoi(p));
			flag = 0;
		}
		p = &p[i];
		i = 0;
		if (p[i] == '(')
		{
			if (p[i+1] == '+' || p[i+1] == '-' || p[i+1] == '*' || p[i+1] == '/' || p[i+1] == ')')
			{
				errno = INPUT_ERROR;
				MyError ("fgets:");
				Destory(s);
				return FALSE;
			}
			Push_op (s,'(');
		}
		else if (p[i] == ')')
		{
			while (Operate (s));
		}
		else
		{
			if (p[i+1] == '+' || p[i+1] == '-' || p[i+1] == '*' || p[i+1] == '/' || p[i+1] == ')')
			{
				errno = INPUT_ERROR;
				MyError ("fgets:");
				Destory(s);
				return FALSE;
			}
			while (Cmp_op (s,p[i]) != TRUE)
			{
				Operate (s);
			}
			Push_op (s,p[i]);	
		}
		p = &p[i+1];
		tmp = p;
	}
	if (flag == 1)
	{
		Push_num (s,atoi(tmp));
	}
	while (Operate (s));
	StackNum result = 0;
	Pop_num (s,&result);
	printf ("result = %d\n",result);
	Destory(s);

    return 0;
}

此项目未完善的地方还有很多,特别是对一些错误输入的识别与处理。希望与大家一起完善。

是一个非常适合实现计算器数据结构,因为它遵循后进先出(LIFO)的原则,与计算表达式的顺序相符合。下面是一个基于实现计算器的示例代码: ```python class Stack: def __init__(self): self.items = [] def is_empty(self): return len(self.items) == 0 def push(self, item): self.items.append(item) def pop(self): if not self.is_empty(): return self.items.pop() else: return None def peek(self): if not self.is_empty(): return self.items[-1] else: return None def size(self): return len(self.items) def calculate(expression): # 将操作符和操作数分别存储在两个中 operator_stack = Stack() operand_stack = Stack() # 定义一个操作符优先级字典 priority = {'+': 1, '-': 1, '*': 2, '/': 2} # 将表达式按空格分割为一个列表 tokens = expression.split() # 遍历表达式中的每个token for token in tokens: if token.isdigit(): # 如果是数字则压入操作数 operand_stack.push(int(token)) elif token in priority: # 如果是操作符则与操作符中的操作符比较优先级 while (not operator_stack.is_empty()) and \ (priority[operator_stack.peek()] >= priority[token]): # 如果操作符顶的优先级比当前操作符高,则进行计算 operand2 = operand_stack.pop() operand1 = operand_stack.pop() operator = operator_stack.pop() result = eval(str(operand1) + operator + str(operand2)) operand_stack.push(result) # 将当前操作符压入操作符 operator_stack.push(token) # 处理剩余的操作符 while not operator_stack.is_empty(): operand2 = operand_stack.pop() operand1 = operand_stack.pop() operator = operator_stack.pop() result = eval(str(operand1) + operator + str(operand2)) operand_stack.push(result) # 返回最终结果 return operand_stack.pop() ``` 这个实现中,我们使用了两个来存储操作符和操作数。具体实现过程如下: 1. 遍历表达式中的每个token。 2. 如果是数字,则将其压入操作数中。 3. 如果是操作符,则与操作符中的操作符比较优先级。如果操作符顶的优先级比当前操作符高,则进行计算,并将结果压入操作数中;否则,将当前操作符压入操作符中。 4. 处理完表达式中的所有token后,将操作符中剩余的操作符依次弹出并进行计算,直到操作符为空。 5. 返回最终结果。 注意,这个实现中使用了Python内置的`eval()`函数来进行计算。在实际应用中,应该使用更为安全的方法,例如手写计算函数或使用第三方库等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值