【问题描述】
设计一个简单的算术表达式计算器。
【基本要求】
实现标准整数类型的四则运算表达式的求值(包含括号,可多层嵌入).
【测试数据】
(30+2*70)/3-12*3
5+(9*(62-37)+15)*6
要求自行设计非法表达式,进行程序测试,以保证程序的稳定运行。
【实现提示】
可以设计以下辅助函数
status isNumber(char ReadInChar); //视ReadInchar 是否是数字而返回 TRUE 或 FALSE 。
int TurnToInteger(char IntChar); // 将字符’0’.’9’ 转换为整数 9
【思路】使用栈实现四则运算
一般可以将算术表达式求值的过程分为两个过程:
1. 中缀表达式 --> 后缀表达式
思路:从左到右遍历中缀表达式的每个数字和符号
若是数字,直接添加到后缀表达式后边(或保存到某一链表中)
若是符号,则判断其与栈顶符号的优先级
是 右括号 或 优先级 不高于 栈顶符号的优先级,则栈顶元素依次出栈并输出,直到栈顶元素为左括号
并 将当前符号进栈,一直到最终输出后缀表达式为止。
注意:栈顶元素与当前符号优先级相同也要输出!
2. 后缀表达式进行四则运算
思路:把数字压入堆栈,遇到操作符就从栈中取出两个数进行相关运算,把结果在存放入栈中直到最后操作完成,输出最终结果。
逻辑设计
(1)程序包含以下函数
void Initstack(Sqstack_num &s);//初始化运算数栈
void Initstack(Sqstack_char &s);//初始化运算符栈
void Push_num(Sqstack_num &s,char e);//向运算数栈中存放数字
void Pop_num(Sqstack_num &s,char &e);//从运算数栈中取出数字
void Push_char(Sqstack_char &s,char e);//向运算符栈中存放字符
void Pop_char(Sqstack_char &s,char &e);//从运算符栈中取出字符
char Precede(char optrtop,char c);//比较当前栈顶元素和字符c的优先关系
double Operate(int a, unsigned char theta, int b);//进行计算
int getIndex(char c);//将操作符转换成矩阵下标
void EvaluateExpression();//算数表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
(2)算术优先级设计
本程序中定义一个函数来比较运算符的优先级
char Table[7][7] = {//运算符优先级表
// '+' '-' '*' '/' '(' ')' '='
/*'+'*/ '>', '>', '<', '<', '<', '>', '>',
/*'-'*/ '>', '>', '<', '<', '<', '>', '>',
/*'*'*/ '>', '>', '>', '>', '<', '>', '>',
/*'/'*/ '>', '>', '>', '>', '<', '>', '>',
/*'('*/ '<', '<', '<', '<', '<', '=', ' ',
/*')'*/ '>', '>', '>', '>', ' ', '>', '>',
/*'='*/ '<', '<', '<', '<', '<', ' ', '=',
};
(3)将操作符转换为矩阵下标
int getIndex(char c)//将操作符转换成矩阵下标
{
switch(c)
{
case'+': return 0;
case'-': return 1;
case'*': return 2;
case'/': return 3;
case'(': return 4;
case')': return 5;
case'=': return 6;
}
return -1;
}
(4)基础运算函数设计
double Operate(int a, unsigned char theta, int b)
实现相应的加减乘除以及带括号的数学运算并返回结果,其中ab为操作数,theta为操作符。
(5)整个表达式求解函数设计
1.如果当前运算符优先级高,则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,同时两操作数出栈,进行运算,所得结果入操作数栈。
2.重新比较当前运算符与新栈顶运算符。重复上述内容,直到栈顶运算符与当前符号均为“=”,即为运算结束。