中缀表达式
Posted friedcoder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了中缀表达式相关的知识,希望对你有一定的参考价值。
不含括号的中缀表达式
代码实现
//直接计算中缀表达式
//不含括号
#include<iostream>
#include<stack>
#include<string>
using namespace std;
//运算符号优先级比较
//加减为低级运算,乘除是高级运算;先算乘除
//return 1 means can calculate, else can not.
int getPriority( stack<char> operators )
{
if( !operators.empty() && ( operators.top() == '*' || operators.top() == '/') ){
return 1;
}
return 0;
}
//输入操作符栈 和 操作数栈 进行计算
void calculate(stack<double> &operands, stack<char> &operators)
{
double op1, op2, res;
char operation;
op2 = operands.top();
operands.pop();
op1 = operands.top();
operands.pop();
operation = operators.top();
operators.pop();
switch( operation ){
case '+':
res = op1 + op2;
break;
case '-':
res = op1 - op2; //对顺序有要求
break;
case '*':
res = op1 * op2;
break;
case '/':
res = op1 / op2; //这个顺序不能反
break;
}
//cout << op1 << operation << op2 << "=" << res << endl; //test
operands.push(res);
}
int main()
{
stack<double> operands; //除法运算可能会出现小数
stack<char> operators;
string formula;
string number;
const string numbers = "0123456789";
const string operation = "+-*/";
cin >> formula;
for( string::iterator c = formula.begin(); c != formula.end(); c++ ){
//处理数字
if( numbers.find(*c) != string::npos ){
while( numbers.find(*c) != string::npos ){
number += *c;
c++;
}
operands.push( stod(number) );
number.clear();
//读完最后一个数字
if ( c == formula.end() ){
if( getPriority(operators) == 1 ){ //最后一个操作符可能是乘除
calculate(operands, operators);
}
break;
}
}
//calculate, 先算乘除
if( operation.find(*c) != string::npos ){
if ( getPriority(operators) == 1 ){
calculate( operands, operators );
}
operators.push((*c));
}
}
//处理剩余的加减
while( !operators.empty() ){
char operation = operators.top();
//减法有顺序要求;1-2+3,先执行1-2=-1,再执行-1+3
if( operation == '+' ){
operators.pop();
if( !operators.empty() && operators.top() == '-' ){
double tmp = operands.top();
operands.pop();
calculate( operands, operators );
operators.push(operation);
operands.push(tmp);
}
else{
operators.push(operation);
calculate( operands, operators );
}
}
else{
calculate( operands, operators );
}
}
cout << formula << " = " << operands.top() << endl;
return 0;
}
含括号的中缀表达式代码实现
//直接计算中缀表达式
//含括号
#include<iostream>
#include<deque>
#include<string>
using namespace std;
//运算符号优先级比较
//return 1 means can calculator, else can not.
int getPriority( deque<char> operators )
{
if( !operators.empty() && ( operators.back() == '*' || operators.back() == '/') ){
return 1;
}
return 0;
}
double calculate( double op1, double op2, char operation )
{
double res;
switch( operation ){
case '+':
res = op1 + op2;
break;
case '-':
res = op1 - op2; //对顺序有要求
break;
case '*':
res = op1 * op2;
break;
case '/':
res = op1 / op2; //这个顺序不能反
break;
}
//cout << op1 << operation << op2 << "=" << res << endl; //test
return res;
}
void calculator(deque<double> &operands, deque<char> &operators)
{
double op1, op2, res;
char operation;
operation = operators.back();
operators.pop_back();
//这个糟糕的顺序
if( operation == '-' ){
op1 = operands.back();
operands.pop_back();
op2 = operands.back();
operands.pop_back();
}else{
op2 = operands.back();
operands.pop_back();
op1 = operands.back();
operands.pop_back();
}
res = calculate( op1, op2, operation );
operands.push_back(res);
}
int main()
{
deque<double> operands; //除法运算可能会出现小数; 使用deque,比栈更灵活
deque<char> operators;
string formula;
string number;
const string numbers = "0123456789";
const string Operation = "+-*/";
cin >> formula;
for( string::iterator c = formula.begin(); c != formula.end(); c++ ){
//处理数字
if( numbers.find(*c) != string::npos ){
while( numbers.find(*c) != string::npos ){
number += *c;
c++;
}
operands.push_back( stod(number) );
number.clear();
//读完最后一个数字
if ( c == formula.end() ){
if( getPriority(operators) == 1 ){ //最后一个可能是乘除
calculator(operands, operators);
}
break;
}
}
//处理 + - * /
if( Operation.find(*c) != string::npos ){
//calculator, 先算乘除
if ( getPriority(operators) == 1 ){
calculator( operands, operators );
}
operators.push_back((*c));
}
//处理括号
else{
if( *c == '(' ){
operators.push_back((*c));
}
//遇到)”时,算出()内算式的值
else{
//)前面可能是乘除
if( getPriority(operators) == 1 ){
calculator(operands, operators);
}
//此时括号内已经没有乘除
deque<double> tmp_oprands;
deque<char> tmp_operators;
//把()内的算式pop到新的栈
while( operators.back() != '(' ){
tmp_oprands.push_back(operands.back());
operands.pop_back();
tmp_operators.push_back(operators.back());
operators.pop_back();
}
tmp_oprands.push_back(operands.back());
operands.pop_back();
operators.pop_back(); //弹出“(”
while(!tmp_operators.empty()){ //计算括号内的算式
calculator( tmp_oprands, tmp_operators );
}
operands.push_back( tmp_oprands.back() ); //push结果
tmp_oprands.pop_back();
}
}
}
//处理剩余的加减
double op1, op2, res;
char operation;
while( !operators.empty() ){
//因为前面使用的是deque结构而不是stack,所以这里可以从栈底开始读取
//(考虑到减法运算过程中的y顺序要求)
op1 = operands.front();
operands.pop_front();
op2 = operands.front();
operands.pop_front();
operation = operators.front();
operators.pop_front();
res = calculate( op1, op2, operation);
operands.push_front(res);
}
cout << formula << " = " << operands.back() << endl;
return 0;
}
改进
前面的算法将加减与乘除分开处理,导致后面运算加减的时候还要考虑减法的运算顺序问题,变得麻烦了。
下面是改进后的代码
以上是关于中缀表达式的主要内容,如果未能解决你的问题,请参考以下文章