Files
2019-10-22 18:16:48 +08:00

140 lines
4.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*==============
* 表达式计算
*
* 包含算法: 3.4
===============*/
#include "Expression.h" //**▲03 栈和队列**//
/*
* ████████ 算法3.4 ████████
*
* 从exp读入表达式并计算表达式的运算结果
*
*【注】
* 1.教材使用的是控制台输入,这里为了便于测试,直接改为从形参接收参数
* 2.该计算功能有限,理论上仅支持对个位数运算,且要求每一步的运算结果也是个位数。
* 教材提供此算法的目的是验证栈的使用,如果想扩展对运算符的支持,并扩大对操作数的支持,
* 则可以顺着此思路进行改版
*/
OperandType EvaluateExpression(const char exp[]) {
SElemType c; // 输入序列
SqStack OPTR; // 运算符栈
SqStack OPND; // 操作数栈
OperatorType theta, x; // 运算符
OperandType a, b; // 操作数
int i = 0;
// 初始化运算符栈,并将一个界限符'#'入栈
InitStack(&OPTR);
Push(&OPTR, '#');
// 初始化操作数栈,并开始读取输入
InitStack(&OPND);
c = exp[i++];
// 当输入中遇到界限符'#',且运算符栈的栈顶元素也是界限符'#'时,则表示读取结束,且运算结束
while(c != '#' || GetTop(OPTR) != '#') {
// 如果ch不是运算符则视其为操作数将其入栈
if(!In(c, OP)) {
Push(&OPND, c); // 将操作数入栈
c = exp[i++]; // 获取下一个输入字符
} else {
switch(Precede(GetTop(OPTR), c)) {
// 栈中运算符优先级低,继续进栈
case '<':
Push(&OPTR, c);
c = exp[i++];
break;
// 优先级相等时,说明这里遇到括号,需要脱括号
case '=':
Pop(&OPTR, &x);
c = exp[i++];
break;
/*
* 栈中运算符优先级高时,先计算,再将计算结果压入栈
*
* 注这儿没有读字符c保留的还是刚才读到的字符
*/
case '>':
Pop(&OPTR, &theta); // 弹出运算符
Pop(&OPND, &b); // 弹出右边的操作数
Pop(&OPND, &a); // 弹出左边的操作数
Push(&OPND, Operate(a, theta, b));
break;
}
}
}
return GetTop(OPND);
}
// 判断指定的运算符是否合规
Status In(SElemType c, const char OP[]) {
SElemType* e = strchr(OP, c);
// 如果运算符c不在合规范围内说明指定的运算符不合规
if(e == NULL) {
return FALSE;
} else {
return TRUE;
}
}
/*
* 判断运算符栈中操作符o1与表达式中的操作符o2的优先级。
*
* 返回'>'、'<'、'='以指示o1和o2的优先级
*/
OperatorType Precede(OperatorType o1, OperatorType o2) {
int x, y;
// 获取指定的运算符在运算符表中的位置
char* p1 = strchr(OP, o1);
char* p2 = strchr(OP, o2);
// 计算出一个运算符优先级表坐标
x = p1 - OP;
y = p2 - OP;
return PrecedeTable[x][y];
}
/*
* 对操作数进行运算
*
* a、b是操作数theta是运算符。
* 对于操作数和运算结果,仅保证对个位数的支持
*/
OperandType Operate(OperandType a, OperatorType theta, OperandType b) {
int x, y, z = CHAR_MAX - 48;
// 先从字符型转为整型
x = a - '0';
y = b - '0';
switch(theta) {
case '+':
z = x + y;
break;
case '-':
z = x - y;
break;
case '*':
z = x * y;
break;
case '/':
z = x / y;
break;
}
// 计算完成后,将整型转换为字符型返回
return z + 48;
}