链式栈实现四则运算,表达式可包含括号,可计算小数

 

由于代码中的注释已较为详尽,在此就只贴代码了

 

 

ExprCPro.cpp 

#include "pch.h"
#include"Expr.h"
#include <iostream>
using namespace std;

int main()
{
	cout << "-------------表达式求值--------------" << endl;
	cout << "1.支持四则运算符:+ - * /" << endl;
	cout << "2.支持括号()"<< endl;
	cout << "3.支持浮点数" << endl;
	cout << "例如:5*(3+4)/2" << endl;
	cout << "请输入您要计算的表达式" << endl;
	char expr[100] = { 0 };
	cin >> expr;
	cout << "最后的计算结果为:" << endl;
	cout << parse(expr);

	return 0;

}

 Expr.h(头文件)

#include<iostream>
using namespace std;

//操作数栈
typedef struct StackNodeOPND
{
	double value;
	StackNodeOPND * next;

}*OPND;

//操作符栈
typedef struct StackNodeOPTR
{
	char op;
	StackNodeOPTR * next;
}*OPTR;
int init(OPND& opnd);//初始化操作数栈函数
int init(OPTR& optr);//初始化操作符栈函数
int push(OPND& opnd, double value);//入操作数栈
int push(OPTR&optr, char c);//入操作符栈
double parse(const char expr[]);//解析表达式,将操作数和操作符分别压入操作数栈和操作符栈
int getTop(OPTR&optr, char&c);//获得操作符栈的栈顶操作符
char preorder(char a, char b);//比较当前运算符和栈顶运算符的优先级
int pop(OPTR&optr, char &c);//运算符栈顶元素出栈,并获取栈顶元素
int pop(OPND&opnd, double &value);//操作数栈顶元素出栈,并获取栈顶元素
double cal(double a, double b, char op);//计算函数
bool isEmpty(OPTR&optr);//判断运算符栈中是否还有运算符

Expr.cpp

#include"Expr.h"
int init(OPND& opnd)
{
	//保证链表为空,消除链表中的元素
	while (opnd != NULL) {
		OPND temp = opnd;
		opnd = temp->next;
		delete(temp);
	}
	opnd = NULL;
	return 0;
}
int init(OPTR& optr) {
	//保证链表为空,消除链表中的元素
	while (optr != NULL) {
		OPTR temp = optr;
		optr= temp->next;
		delete(temp);
	}
	optr= NULL;
	return 0;
}
//入操作数栈函数
int push(OPND& opnd, double value) {
	OPND temp = (OPND)malloc(sizeof(StackNodeOPND));
	if (!temp) {
		return -1;
	}
	temp->value = value;
	temp->next = opnd;
	opnd = temp;
	return 0;
}
//入操作符栈函数
int push(OPTR& optr, char c) {
	OPTR temp = (OPTR)malloc(sizeof( StackNodeOPTR));
	if (!temp) {
		return -1;
	}
	temp->op = c;
	temp->next = optr;
	optr= temp;
	return 0;
}
//弹出操作符栈顶元素,并同时获取栈顶元素
int pop(OPTR&optr, char& c) {
	if (optr == NULL) {
		return -1;
	}
	OPTR temp = optr;
	c = optr->op;
	optr = optr->next;
	delete(temp);
	return 0;
}
int pop(OPND&opnd, double &value) {
	if (opnd == NULL) {
		return -1;
	}
	OPND temp = opnd;
	value = temp->value;
	opnd = opnd->next;
	delete(temp);
	return 0;
}
//解析表达式
double parse(const char expr[])
{
	OPND opnd = NULL;//操作数栈
	OPTR optr = NULL;//操作符栈
	init(opnd);
	init(optr);
	for (int i = 0; expr[i] != '\0'; i++) {
		//读一个字符
		char c = expr[i];
		if ((c >= '0'&&c <= '9') || c == '.') {
			char token[50] = { 0 };
			int j = 0;
			while ((expr[i + j] > '0'&&expr[i + j] < '9') || expr[i + j] == '.') {
				token[j] = expr[i + j];
				j++;
			}
			i = i + j - 1;
			token[j] = '\0';
			double value = atof(token);
			push(opnd, value);
		}
		else {
			char op = 0;
			getTop(optr, op);
			if (op != 0) {
				switch (preorder(op, c))
				{
				case'<'://当前操作符入栈
					push(optr, c);
					break;
				case'='://括号相遇,弹出括号
					pop(optr, op);
					break;
				case'>'://取操作符栈顶元素并取操作数栈顶两个运算
					double a = 0;
					double b = 0;
					pop(opnd, a);
					pop(opnd, b);
					pop(optr, op);
					push(opnd, cal(a, b, op));
					i--;//仍要比较当前操作符和下一个栈顶操作符
					break;
				}
			}
			else {
				push(optr, c);
			}			
		}
	}
	if (!isEmpty(optr)) {
		double a = 0;
		double b = 0;
		char op = 0;
		pop(opnd, a);
		pop(opnd, b);
		pop(optr, op);
		push(opnd, cal(a, b, op));
		}
	double result = 0;
	pop(opnd, result);
	return result;
}
int getTop(OPTR&optr, char&c) {
	if (optr == NULL) {
		return -1;
	}
	c = optr->op;
	return 0;
}
//a是栈顶操作符,b是当前操作符
char preorder(char a, char b) {
	//用一个二维数组来保存两两运算符之间的优先级关系
	//返回类型有三种">,<,="
	char compre[6][6]{
		//当前左括号和栈顶右括号比其他运算符优先级都高,两者相等
		//当前右括号和栈顶左括号比其他运算符优先级都低,两者相等
		//+ - * / ( )
		{'>','>','>','>','<','>'},//+
	    {'>','>','>','>','<','>'},//-
		{'<','<','>','>','<','>'},//*
		{'<','<','>','>','<','>'},// /
		{'<','<','<','<','<','='},//(
		{'>','>','>','>','=','>'}// )
	};
	int x=-1, y = -1;
	char allch[7] = "+-*/()";
	for (int i = 0; i < 6; i++) {
		if (a == allch[i]) {
			x = i;
		}
		if (b == allch[i]) {
			y = i;
		}
	}
	return compre[x][y];
}
double cal(double a, double b, char op) {
	double result;
	switch (op) {
	case'*':
		result = b * a;
		break;
	case'/':
		result = b / a;
		break;
	case'+':
		result = b + a;
		break;
	case'-':
		result = b - a;
		break;
	default:
	{
		cout << "您输入的表达式符号有误,请重新输入!";
		exit(0);
	}
	}
	return result;
}
bool isEmpty(OPTR&optr) {
	if (optr == NULL) {
		return 1;
	}
	else
		return 0;
}

 

 最后运行效果为:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值