要写一个计算器,如果要进行连续运算,则要将中缀表达式转化为后缀表达式再求解。
步骤:
1) 从中缀表达式中提取每一项、存放到队列中;2) 将中缀表达式转换成后缀表达式;3) 计算后缀表达式的值。
功能:1、+-/*四则运算2、小数运算
先将字符串保存到中缀表达式队列中:
struct node
{
double num;
char symbol;
bool sign;//判断是数字或者符号,false即 为符号
double dot;
int priority;
};
queue<node> Q1; //Q1保存中缀表达式
queue<node> Q2; //Q2保存后缀表达式
stack<node> Sc; //中—后
void save()1) 从中缀表达式中提取每一项、存放到队列中;
{
node tmp;//临时节点
char str[100];
scanf("%s",str);//输入中缀表达式
for(int i=0;str[i]!='\0';i++)
{
if(Q1.empty()==0&&Q1.back().sign==false)//当前队列尾部元素是数值
{
if(str[i]-48<=9&&0<=str[i]-48)//新加入的元素是数值
{
if( Q1.back().dot>0)
{
Q1.back().dot/=10;
Q1.back().num=Q1.back().num+(str[i]-48)*Q1.back().dot;
}
else Q1.back().num=Q1.back().num*10+str[i]-48;
}
else if(str[i]=='.')
{
Q1.back().dot=1;
}
else //新加入的元素是符号
{
tmp.sign=true;
tmp.symbol=str[i];
if(tmp.symbol=='*'||tmp.symbol=='/') tmp.priority=2;
else if(tmp.symbol=='+'||tmp.symbol=='-') tmp.priority=1;
Q1.push(tmp);
}
}
else
{
if(str[i]-48<=9&&0<=str[i]-48)//新加入的元素是数值
{
tmp.sign=false;
tmp.num=str[i]-48;
Q1.push(tmp);
}
else //新加入的元素是符号
{
tmp.sign=true;
tmp.symbol=str[i];
if(tmp.symbol=='*'||tmp.symbol=='/') tmp.priority=2;
else if(tmp.symbol=='+'||tmp.symbol=='-') tmp.priority=1;
Q1.push(tmp);
}
}
}
}
将中缀表达式转换为后缀表达式:
具体算法:
自左至右扫描iQ1,读入每项并分析其对应的语法成分:
1)当输入的是操作数,则直接输出到Q2中。
2)当输入的是运算符op( 四则运算+ - */ 之一)时:
A)循环,当(栈非空 and 栈顶运算符的优先级不低于输入运算符的优先级时),反复操作:将栈顶元素弹出,输出到Q2中。
B)把输入的运算符op压栈。
3)最后,当中缀表达式Q1的符号序列全部读入后,在栈中可能还会一些项,它们是原来压入还没有处理的语法成分。对待它们的方法是:把它们依次从栈中弹出,并输出到后缀表达式Q2的尾部。
void change()//2) 将中缀表达式转换成后缀表达式;
{
while(Q1.empty()==0)
{
if(Q1.front().sign==false)//是数字,放入队列
{
Q2.push(Q1.front());
}
else
{
if(Q1.front().symbol=='(')//当输入的是左括号,则把它压栈。
Sc.push(Q1.front());
else if(Sc.empty()==1)
Sc.push(Q1.front());
else if(Q1.front().priority<=Sc.top().priority)
{
while(Sc.empty()==0&&Q1.front().priority<=Sc.top().priority)
{
Q2.push(Sc.top());
Sc.pop();
}
Sc.push(Q1.front());
}
else
Sc.push(Q1.front());
}
Q1.pop();
}
while(!Sc.empty())
{
Q2.push(Sc.top());
Sc.pop();
}
/*printf("转换为后缀表达式:\n");
while(Q2.empty()==0)
{
if(Q2.front().sign==false) printf("%f ",Q2.front().num);
else if(Q2.front().sign==true) printf("%c ",Q2.front().symbol);
Q2.pop();
}*/
}
后缀表达式的求解:
算法:
1如果读入的是一个操作数,则压栈;
2如果读入的是一个运算符,则从栈中两次取出栈顶的项,按照该运算符对这两个操作数进行计算,然后将计算结果压入栈顶。
double calculate()
{
stack<node> stmp;
double num1=0;
double num2=0;
node tmp;
while(Q2.empty()==0)
{
if(Q2.front().sign==false)
{
stmp.push(Q2.front());
}
else if(Q2.front().sign==true)
{
num2=stmp.top().num;
stmp.pop();
num1=stmp.top().num;
stmp.pop();
if(Q2.front().symbol=='+')
{
tmp.num=num1+num2;
tmp.priority=1;
tmp.sign=false;
}
else if(Q2.front().symbol=='-')
{
tmp.num=num1-num2;
tmp.priority=1;
tmp.sign=false;
}
else if(Q2.front().symbol=='*')
{
tmp.num=num1*num2;
tmp.priority=2;
tmp.sign=false;
}
else if(Q2.front().symbol=='/')
{
tmp.num=num1/num2;
tmp.priority=2;
tmp.sign=false;
}
stmp.push(tmp);
}
Q2.pop();
}
return stmp.top().num;
}
总体代码:
/*步骤:
1) 从中缀表达式中提取每一项、存放到队列中;
2) 将中缀表达式转换成后缀表达式;
3) 计算后缀表达式的值。
功能:
1、+-/*四则运算
2、无()小括号
3、小数运算
*/
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;
struct node
{
double num;
char symbol;
bool sign;//判断是数字或者符号,false即 为符号
double dot;
int priority;
};
queue<node> Q1; //Q1保存中缀表达式
queue<node> Q2; //Q2保存后缀表达式
stack<node> Sc; //中—后
void save()1) 从中缀表达式中提取每一项、存放到队列中;
{
node tmp;//临时节点
char str[100];
scanf("%s",str);//输入中缀表达式
for(int i=0;str[i]!='\0';i++)
{
if(Q1.empty()==0&&Q1.back().sign==false)//当前队列尾部元素是数值
{
if(str[i]-48<=9&&0<=str[i]-48)//新加入的元素是数值
{
if( Q1.back().dot>0)
{
Q1.back().dot/=10;
Q1.back().num=Q1.back().num+(str[i]-48)*Q1.back().dot;
}
else Q1.back().num=Q1.back().num*10+str[i]-48;
}
else if(str[i]=='.')
{
Q1.back().dot=1;
}
else //新加入的元素是符号
{
tmp.sign=true;
tmp.symbol=str[i];
if(tmp.symbol=='*'||tmp.symbol=='/') tmp.priority=2;
else if(tmp.symbol=='+'||tmp.symbol=='-') tmp.priority=1;
Q1.push(tmp);
}
}
else
{
if(str[i]-48<=9&&0<=str[i]-48)//新加入的元素是数值
{
tmp.sign=false;
tmp.num=str[i]-48;
Q1.push(tmp);
}
else //新加入的元素是符号
{
tmp.sign=true;
tmp.symbol=str[i];
if(tmp.symbol=='*'||tmp.symbol=='/') tmp.priority=2;
else if(tmp.symbol=='+'||tmp.symbol=='-') tmp.priority=1;
Q1.push(tmp);
}
}
}
}
void change()//2) 将中缀表达式转换成后缀表达式;
{
while(Q1.empty()==0)
{
if(Q1.front().sign==false)//是数字,放入队列
{
Q2.push(Q1.front());
}
else
{
if(Q1.front().symbol=='(')//当输入的是左括号,则把它压栈。
Sc.push(Q1.front());
else if(Sc.empty()==1)
Sc.push(Q1.front());
else if(Q1.front().priority<=Sc.top().priority)
{
while(Sc.empty()==0&&Q1.front().priority<=Sc.top().priority)
{
Q2.push(Sc.top());
Sc.pop();
}
Sc.push(Q1.front());
}
else
Sc.push(Q1.front());
}
Q1.pop();
}
while(!Sc.empty())
{
Q2.push(Sc.top());
Sc.pop();
}
/*printf("转换为后缀表达式:\n");
while(Q2.empty()==0)
{
if(Q2.front().sign==false) printf("%f ",Q2.front().num);
else if(Q2.front().sign==true) printf("%c ",Q2.front().symbol);
Q2.pop();
}*/
}
double calculate()
{
stack<node> stmp;
double num1=0;
double num2=0;
node tmp;
while(Q2.empty()==0)
{
if(Q2.front().sign==false)
{
stmp.push(Q2.front());
}
else if(Q2.front().sign==true)
{
num2=stmp.top().num;
stmp.pop();
num1=stmp.top().num;
stmp.pop();
if(Q2.front().symbol=='+')
{
tmp.num=num1+num2;
tmp.priority=1;
tmp.sign=false;
}
else if(Q2.front().symbol=='-')
{
tmp.num=num1-num2;
tmp.priority=1;
tmp.sign=false;
}
else if(Q2.front().symbol=='*')
{
tmp.num=num1*num2;
tmp.priority=2;
tmp.sign=false;
}
else if(Q2.front().symbol=='/')
{
tmp.num=num1/num2;
tmp.priority=2;
tmp.sign=false;
}
stmp.push(tmp);
}
Q2.pop();
}
return stmp.top().num;
}
int main()
{
save();//1) 从中缀表达式中提取每一项、存放到队列中;
change();
double result=calculate();
printf("%f ",result);
return 0;
}