/*
Function: 带括号的四则运算表达式的求值(栈实现)
Description: 利用栈这种数据结构来实现一个加减乘除以及带括弧的混合数学表达式的计算,
对于数学表达式的计算,可以设置一个运算符栈和一个数字栈,分别来保存运算符、数字或者中间计算得到的结果。
将整个表达式看做一个字符串,从开头依次判断每个字符是运算符还是数字,若是运算符,
则根据运算符优先级来确定是将其压栈还是弹栈进行计算;若是数字,则先将其转化并计入一个临时int型变量中,看下一个字符是否为运算符栈,
若是,则将临时变量压进数字栈,否则读取下一个数字字符并进行相关处理后累加到临时变量中,直到下一个字符为运算符,将临时变量压进数字栈。
最后,当字符为"="时,结束计算,得到计算结果。本算法需要先设置一个运算符优先级表,下表可供参考:
运算符优先级表:
+ - * / ( ) =
+ > > < < < > >
- > > < < < > >
* > > > > < > >
/ > > > > < > >
( < < < < < =
) > > > > > >
= < < < < < =
参考代码如下:
注:本代码输入表达式时末尾不需要“=”,程序中会自动添加
*/
#include "stdafx.h"
#include <stack>
#include <cstring>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <cmath>
using namespace std;
/***********************************************
* Function Name : Precede
* Create Date 2012/9/20
* Author: young
* Description:
* Parameter:
* Input
* a --- the first Operator a
* b --- teh second Operator b
* Output:
* return char type ( '>' or '<' or '=' or ' ')
************************************************/
char Precede(char a,char b)
{
int i,j;
char table[8][8] = {
{' ','+','-','*','/','(',')','='},
{'+','>','>','<','<','<','>','>'},
{'-','>','>','<','<','<','>','>'},
{'*','>','>','>','>','<','>','>'},
{'/','>','>','>','>','<','>','>'},
{'(','<','<','<','<','<','=',' '},
{')','>','>','>','>',' ','>','>'},
{'=','<','<','<','<','<',' ','='}
};
for (i=0;i<8;i++) // the first row, different columns
if(table[0][i] == a)
break;
for(j=0;j<8;j++)
if(table[j][0]== b) // the first column, different rows
break;
return table[j][i]; // locate the row, and column
}
/***********************************************
* Function Name : Calcu_temp
* Create Date 2012/9/20
* Author: young
* Description:
* Parameter:
* Input
* a --- the first Operator a
* theta --- operator
* b --- teh second Operator b
* &r --- store the calculating result
* Output: return bool type
* true --- Calculate the temperate value successfully
* false --- Calculate failure
************************************************/
bool Calcu_temp(double a,char theta,double b,double &r)
{
if(theta == '+')
r = a + b;
else
if(theta == '-')
r = a - b;
else
if(theta == '*')
r = a * b;
else
{
if(abs(b-0.0)<1e-8)
return false;
else
r = a /b;
}
return true;
}
/***********************************************
* Function Name : Calcu_temp
* Create Date 2012/9/20
* Author: young
* Description: Check if ch is a operator
* Parameter:
* Input
* ch --- operator that will be checked!
* Output: return bool type
* true --- ch is a operator
* false --- ch isn't a operator
************************************************/
bool IsOper(char ch)
{
char ptr[7] = {'+','-','*','/','(',')','='};
int i;
for(i=0;i<7;i++)
{
if(ch == ptr[i])
return true;
}
return false;
}
/***********************************************
* Function Name : Calcu_temp
* Create Date 2012/9/20
* Author: young
* Description: Check if ch is a operator
* Parameter:
* Input
* s[] --- expression string
* result --- referenced to the calculated result
* Output: return bool type
* true --- calculate successfully
* false --- failure!
************************************************/
bool Calculate(char s[], double &result) //计算表达式的结果
{
char theta;
int i = 0, j, point = 0;
double a, b, r, num = 0;
stack<double> num_stack; //数字栈
stack<char> oper_stack; //运算符栈
oper_stack.push('=');
while(s[i]!= '=' || oper_stack.top()!= '=') //对表达式a进行计算
{
if((s[i]>='0' && s[i]<='9') || s[i]=='.') //字符是数字或者小数点
{
num = 0; //初始化数字为0
point = 0; //point用来标记是否出现小数点以及当前处于小数点后第x位,point==10^x
if(s[i]=='.')
point = 10;
else
num = s[i] - '0';
j = i + 1;
while(!IsOper(s[j])) //继续往后查找并记录该数字,直到该数字结束遇到运算符为止
{
if(s[j]=='.')
{
point = 10;
j++;
continue;
}
if(!point) //整数部分
num = num * 10 + ( s[j] - '0');
else //小数部分
{
num = num + 1.0 * ( s[j] - '0' ) / point; //小数部分
point *= 10; //小数位数后移一位
}
j++;
}
i = j;
num_stack.push(num); //将该数字压入栈中
}
else if(IsOper(s[i])) //字符是运算符
{
switch(Precede(s[i],oper_stack.top())) //该运算符和栈顶运算符进行优先级比较并做相关处理
{
case '<':
oper_stack.push(s[i++]);
break;
case '=':
oper_stack.pop();
i++;
break;
case '>':
theta = oper_stack.top(); //从栈中弹出一个运算符进行计算
oper_stack.pop();
b = num_stack.top(); //弹出两个数字,注意顺序,先弹出的数是第二个操作数
num_stack.pop();
a = num_stack.top();
num_stack.pop();
if ( Calcu_temp(a, theta, b, r) ) //计算并判断是否有除数等于0的情况
num_stack.push(r); //若正常,则将结果压入栈中
else
return false; //出现除数为0的情况,返回错误信息
break;
}
}
}
result = num_stack.top(); //最后数字栈中的数即为表达式的最终结果
return true;
}
bool Check(char s[]) //检查表达式括号是否匹配
{
int flag=0, i;
for(i=0; s[i]!=0; i++) {
if(s[i]=='(')
flag++;
if(s[i]==')')
flag--;
}
if(flag!=0)
return false;
else
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
//freopen("in.txt", "r", stdin);
int i, j;
char s1[210], s2[210];
double result;
while(gets(s1)!=NULL) //输入表达式
{
if(strlen(s1)==1 && s1[0]=='0') // 输入为 ‘0’或只有一个字符时,重新输入
break;
for(i=0,j=0; s1[i]!=0; i++) //将表达式转换为规格化的表达式,并在末尾加上“=”,保存在s2中
{
if(s1[i]==' ')
continue;
s2[j++] = s1[i];
}
s2[j++] = '=';
s2[j] = '\0';
if(Check(s2)) //检查括号是否匹配
{
if(Calculate(s2, result)) //计算并检查表达式中是否出现除数为0的情况
printf("%lf\n",result);
else
printf("The divisor cannot be zero!\n");
}
else
printf("The parentheses do not match!\n");
}
return 0;
}
Function: 带括号的四则运算表达式的求值(栈实现)
Description: 利用栈这种数据结构来实现一个加减乘除以及带括弧的混合数学表达式的计算,
对于数学表达式的计算,可以设置一个运算符栈和一个数字栈,分别来保存运算符、数字或者中间计算得到的结果。
将整个表达式看做一个字符串,从开头依次判断每个字符是运算符还是数字,若是运算符,
则根据运算符优先级来确定是将其压栈还是弹栈进行计算;若是数字,则先将其转化并计入一个临时int型变量中,看下一个字符是否为运算符栈,
若是,则将临时变量压进数字栈,否则读取下一个数字字符并进行相关处理后累加到临时变量中,直到下一个字符为运算符,将临时变量压进数字栈。
最后,当字符为"="时,结束计算,得到计算结果。本算法需要先设置一个运算符优先级表,下表可供参考:
运算符优先级表:
+ - * / ( ) =
+ > > < < < > >
- > > < < < > >
* > > > > < > >
/ > > > > < > >
( < < < < < =
) > > > > > >
= < < < < < =
参考代码如下:
注:本代码输入表达式时末尾不需要“=”,程序中会自动添加
*/
#include "stdafx.h"
#include <stack>
#include <cstring>
#include <cstdio>
#include <stdio.h>
#include <cstdlib>
#include <cmath>
using namespace std;
/***********************************************
* Function Name : Precede
* Create Date 2012/9/20
* Author: young
* Description:
* Parameter:
* Input
* a --- the first Operator a
* b --- teh second Operator b
* Output:
* return char type ( '>' or '<' or '=' or ' ')
************************************************/
char Precede(char a,char b)
{
int i,j;
char table[8][8] = {
{' ','+','-','*','/','(',')','='},
{'+','>','>','<','<','<','>','>'},
{'-','>','>','<','<','<','>','>'},
{'*','>','>','>','>','<','>','>'},
{'/','>','>','>','>','<','>','>'},
{'(','<','<','<','<','<','=',' '},
{')','>','>','>','>',' ','>','>'},
{'=','<','<','<','<','<',' ','='}
};
for (i=0;i<8;i++) // the first row, different columns
if(table[0][i] == a)
break;
for(j=0;j<8;j++)
if(table[j][0]== b) // the first column, different rows
break;
return table[j][i]; // locate the row, and column
}
/***********************************************
* Function Name : Calcu_temp
* Create Date 2012/9/20
* Author: young
* Description:
* Parameter:
* Input
* a --- the first Operator a
* theta --- operator
* b --- teh second Operator b
* &r --- store the calculating result
* Output: return bool type
* true --- Calculate the temperate value successfully
* false --- Calculate failure
************************************************/
bool Calcu_temp(double a,char theta,double b,double &r)
{
if(theta == '+')
r = a + b;
else
if(theta == '-')
r = a - b;
else
if(theta == '*')
r = a * b;
else
{
if(abs(b-0.0)<1e-8)
return false;
else
r = a /b;
}
return true;
}
/***********************************************
* Function Name : Calcu_temp
* Create Date 2012/9/20
* Author: young
* Description: Check if ch is a operator
* Parameter:
* Input
* ch --- operator that will be checked!
* Output: return bool type
* true --- ch is a operator
* false --- ch isn't a operator
************************************************/
bool IsOper(char ch)
{
char ptr[7] = {'+','-','*','/','(',')','='};
int i;
for(i=0;i<7;i++)
{
if(ch == ptr[i])
return true;
}
return false;
}
/***********************************************
* Function Name : Calcu_temp
* Create Date 2012/9/20
* Author: young
* Description: Check if ch is a operator
* Parameter:
* Input
* s[] --- expression string
* result --- referenced to the calculated result
* Output: return bool type
* true --- calculate successfully
* false --- failure!
************************************************/
bool Calculate(char s[], double &result) //计算表达式的结果
{
char theta;
int i = 0, j, point = 0;
double a, b, r, num = 0;
stack<double> num_stack; //数字栈
stack<char> oper_stack; //运算符栈
oper_stack.push('=');
while(s[i]!= '=' || oper_stack.top()!= '=') //对表达式a进行计算
{
if((s[i]>='0' && s[i]<='9') || s[i]=='.') //字符是数字或者小数点
{
num = 0; //初始化数字为0
point = 0; //point用来标记是否出现小数点以及当前处于小数点后第x位,point==10^x
if(s[i]=='.')
point = 10;
else
num = s[i] - '0';
j = i + 1;
while(!IsOper(s[j])) //继续往后查找并记录该数字,直到该数字结束遇到运算符为止
{
if(s[j]=='.')
{
point = 10;
j++;
continue;
}
if(!point) //整数部分
num = num * 10 + ( s[j] - '0');
else //小数部分
{
num = num + 1.0 * ( s[j] - '0' ) / point; //小数部分
point *= 10; //小数位数后移一位
}
j++;
}
i = j;
num_stack.push(num); //将该数字压入栈中
}
else if(IsOper(s[i])) //字符是运算符
{
switch(Precede(s[i],oper_stack.top())) //该运算符和栈顶运算符进行优先级比较并做相关处理
{
case '<':
oper_stack.push(s[i++]);
break;
case '=':
oper_stack.pop();
i++;
break;
case '>':
theta = oper_stack.top(); //从栈中弹出一个运算符进行计算
oper_stack.pop();
b = num_stack.top(); //弹出两个数字,注意顺序,先弹出的数是第二个操作数
num_stack.pop();
a = num_stack.top();
num_stack.pop();
if ( Calcu_temp(a, theta, b, r) ) //计算并判断是否有除数等于0的情况
num_stack.push(r); //若正常,则将结果压入栈中
else
return false; //出现除数为0的情况,返回错误信息
break;
}
}
}
result = num_stack.top(); //最后数字栈中的数即为表达式的最终结果
return true;
}
bool Check(char s[]) //检查表达式括号是否匹配
{
int flag=0, i;
for(i=0; s[i]!=0; i++) {
if(s[i]=='(')
flag++;
if(s[i]==')')
flag--;
}
if(flag!=0)
return false;
else
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
//freopen("in.txt", "r", stdin);
int i, j;
char s1[210], s2[210];
double result;
while(gets(s1)!=NULL) //输入表达式
{
if(strlen(s1)==1 && s1[0]=='0') // 输入为 ‘0’或只有一个字符时,重新输入
break;
for(i=0,j=0; s1[i]!=0; i++) //将表达式转换为规格化的表达式,并在末尾加上“=”,保存在s2中
{
if(s1[i]==' ')
continue;
s2[j++] = s1[i];
}
s2[j++] = '=';
s2[j] = '\0';
if(Check(s2)) //检查括号是否匹配
{
if(Calculate(s2, result)) //计算并检查表达式中是否出现除数为0的情况
printf("%lf\n",result);
else
printf("The divisor cannot be zero!\n");
}
else
printf("The parentheses do not match!\n");
}
return 0;
}