由于代码中的注释已较为详尽,在此就只贴代码了
ExprCPro.cpp
#include "pch.h"
#include"Expr.h"
#include
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
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;
}