问题描述
从键盘上输入中缀表达式,包括括号,计算出表达式的值
- 基本要求:
(1)程序能对输入的表达式做简单的判断,如表达式是否有错,能给出适当的提示。
(2)能处理单目运算符:+(正号) -(负号)
一、分析与实现
1.题目分析
(1)先乘方^,再乘除,最后做加减;
(2)同级运算从左算到右;
(3)先括号内,再括号外。
2.算法分析
- 初始化两个栈:新建两个栈分别用于储存操作符和操作数
- 读取用户输入的表达式,存储在一个string类 str中
- 对输入字符串进行简单处理,避免边缘情况发生
- 遍历表达式:对str的字符逐个判断
- 若为(,直接压入操作符栈。
- 若为数字,创建临时存储字符串,逐步存下数字,将临时字符串转换为double类型压入操作数栈
- 若为运算符,比较运算符栈顶元素与次运算符的优先级,若栈顶运算符优先级较高,则从操作数栈中获取到两个操作数进行运算,并将结果压入操作数栈中,同时进行相关出栈操作,当栈顶元素优先级小于当前元素时,将当前元素压入运算符栈;
- 若为),则从操作数栈中获取到两个操作数进行运算,并将结果压入操作数栈中,同时进行相关出栈操作。
二、代码实现
#include<iostream>
#include<string>
#include<stack>
using namespace std;
class MyCalculator {
private:
//计算器的数据成员
stack <double>opnd; //操作数栈
stack <char>optr; //操作符栈
double left;
double right;
//辅助函数模板
int OperPrior(char op);// 操作符优先级
void Get2Operands(double& left, double& right);//从栈 opnd中退出两个提作数
double Operate(double left, char op, double right); // 执行运算 left op right
bool IsOperator(char ch); //判断ch是否为操作符
public:
//计算器类方法声明
MyCalculator(); //无参数的构造函数模板
~MyCalculator(); //析构函数模板
int Run();//运算表达式
};
MyCalculator::MyCalculator()
{
}
MyCalculator::~MyCalculator()
{
}
int MyCalculator::OperPrior(char op)
{
int prior = -1;
switch (op)
{
case '+':
case '-':
prior = 1;
break;
case '*':
case '/':
case '%':
prior = 2;
break;
case '^':
prior = 3;
break;
}
return prior;
}
void MyCalculator::Get2Operands(double& left,double& right)
{
right = opnd.top();
opnd.pop();
left = opnd.top();
opnd.pop();
}
double MyCalculator::Operate(double left, char op, double right)
{
if (op == '+') opnd.push(left + right);
else if (op == '-') opnd.push(left - right);
else if (op == '*') opnd.push(left * right);
else if (op == '/')
{
if (right == 0.0)
{
cout << "表达式有误,除数不能为0";
return 1;
}
opnd.push(left / right);
}
else if (op == '%')
{
if (right == 0.0)
{
cout << "表达式有误,取余的数不能为0";
return 1;
}
if (right != (int)right||left!=(int)left)
{
cout << "表达式有误,取余的数不能为小数" << endl;
return 1;
}
opnd.push((int)left % (int)right);
}
else if (op == '^') opnd.push(pow(left, right));
return 0;
}
bool MyCalculator::IsOperator(char ch)
{
switch (ch)
{
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
case '.':
return true;
}
return false;
}
int MyCalculator::Run()
{
string str;
string ss;
char priorChar;
double operand; //操作数
char op; //操作符
cout << "输入表达式:" << endl;
cin >> str;
str.erase(str.length()-1,1);
str = '(' + str + ')';
for (int i = 0; i < str.length(); i++)
{
if (str[i] == '(') optr.push(i);
else if (str[i] == ')')
{
if (optr.empty())
{
cout << "表达式有误,括号不匹配";
return 1;
}
optr.pop();
}
else if (!((str[i] >= '0' && str[i] <= '9') || IsOperator(str[i]) ))
{
cout << "表达式有误,存在不支持的运算符";
return 1;
}
}
if (!optr.empty())
{
cout << "表达式有误,括号不匹配";
return 1;
}
for (int i = 0; i < str.length(); i++)
{
if (str[i] == '(' && str[i + 1] == '-') str.insert(i + 1, "0");
if (str[i] == '(' && str[i + 1] == '+') str.insert(i + 1, "0");
}
for (int i = 0; i < str.length(); i++)
{
if (str[i] == '(')
optr.push(str[i]);
else if ((str[i] <= '9' && str[i] >= '0'))
{
ss += str[i];
if (str[i + 1] == '.') { ss += '.'; i++; }
else if (!(str[i + 1] <= '9' && str[i + 1] >= '0'))
{
operand = stof(ss);
opnd.push(operand);
ss = "";
}
}
else if (OperPrior(str[i]) > 0)
{
if (OperPrior(str[i + 1]) > 0)
{
cout << "表达式有误" << endl;
return 1;
}
while (OperPrior(optr.top()) >= OperPrior(str[i]))
{
Get2Operands(left, right);
op = optr.top(); optr.pop();
if(Operate(left, op, right))
return 1;
}
optr.push(str[i]);
}
else
{
while (optr.top() != '(')
{
Get2Operands(left, right);
op = optr.top(); optr.pop();
if(Operate(left, op, right))
return 1;
}
optr.pop();
}
}
cout << "计算结果为" << opnd.top() << endl;
return 0;
}
int main()
{
MyCalculator m;
char ans = 'y';
while (ans == 'y')
{
if(m.Run())
return 0;
cout << "是否继续(y/n)?";
cin >> ans;
}
return 0;
}
运行截图:

程序有待进一步测试与改进。
3083

被折叠的 条评论
为什么被折叠?



