您的位置:首页 > 编程语言 > C语言/C++

栈实现带括号的浮点型四则运算C++

2012-09-20 15:00 267 查看
/*

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: