最近在网上看到一个求解数学表达式程序,感觉很不错,故拿出来修改之后供大家一起分享.
程序如下:
#include <ctype.h> //打开库文件
#include <stdio.h>
#include <iostream.h>
#include <malloc.h>
#include <process.h>
#include <string.h>
#define error 0
#define ok 1
typedef struct{
int *base;
int *top;
int stacksize;
}sqstack;
class CExpression
{
public:
CExpression();
~CExpression();
public:
void initstack(sqstack &s);
int gettop(sqstack &s);
void push(sqstack &s,int e);
int pop(sqstack &s,int &e);
int setfind(char a,char b[]); //查找a在b中的位置
char precede(char op1,char op2,int &flag); //比较op1和op2的优先级
int numlink(int opd,int ops,int &flag); //数字与字符串的连接
int operate(int n1,char o,int n2,int &flag);//运算
/*
flag为一个标志变量,
1为表达式有误!除数为0!
2为表达式的值过大或过小
3为未知类型的错误,可能没有这一点
但为了容错,还是要加上这一点
-*/
public:
sqstack opnd;
sqstack optr;
private:
sqstack s;
};
CExpression::CExpression()
{
s.top=s.base;
}
CExpression::~CExpression()
{
}
void CExpression::initstack(sqstack &s)
{
s.base=(int *)malloc(10*sizeof(int));
if(!s.base) exit(1);
s.top=s.base;
s.stacksize=100;
}
int CExpression::gettop(sqstack &s)
{
int e;
e=*(s.top-1);
return e;
}
void CExpression::push(sqstack &s,int e)
{
if(s.top-s.base>=s.stacksize)
{
s.base=(int*)realloc(s.base,(s.stacksize+10*sizeof(int)));
if(!s.base)
exit(2);
s.top=s.base+s.stacksize;
s.stacksize+=10;
}
*s.top++=e;
}
int CExpression::pop(sqstack &s,int &e)
{
if(s.top==s.base)return error;
e=*--s.top;
return ok;
}
int CExpression::setfind(char a,char b[])
{
int i,j;
i=-1,j=0;
while(b[j]!='\0')
if(a==b[j++]) {i=j-1;break;}
return i;
}
char CExpression::precede(char op1,char op2,int &flag) //比较op1和op2的优先级
{
int i,j;
char st1[8]={"+-*/()#"}; //运算符初始化
char st2[7][8]={">><<<>>",">><<<>>",">>>><>>", //比较操作初始化
">>>><>>","<<<<<= ",">>>> >>","<<<<< ="};
i=setfind(op1,st1);j=setfind(op2,st1);
if (i>-1 && j>-1) //如果你所输入的运算符不在+-*/()#内,返回ERROR
{return st2[i][j];flag=ok;}
else flag=error;
return error;
}
int CExpression::numlink(int opd,int ops,int &flag){ //数字与字符串的连接
int aa=ops;
ops=ops*10+opd-48;
if (ops<0 && aa>0 || aa>214748364)
flag=error; else flag=ok; //flag=0,说明ops已经过大,
return ops;
}
int CExpression::operate(int n1,char o,int n2,int &flag){ //运算
/*
flag为一个标志变量,
1为表达式有误!除数为0!
2为表达式的值过大或过小
3为未知类型的错误,可能没有这一点
但为了容错,还是要加上这一点
-*/
int result=0;
switch (o){
case '+': //加法运算
flag=0;result=n1+n2;
if (n1>=0 && n2>=0 && result<0 || n1<=0 && n2<=0 && result>0)
//两个大于0的数相加,和小于0,或两个小于0的数相加,和大于0,返回错误
{flag=2;return error;}
else
{flag=0;return result;}
break;
case '-': //减法运算
flag=0;result=n1-n2;
if (n1>=0 && n2<0 && result<0 || n1<=0 && n2>0 && result>0)
//一个大于0的数减一个小于0 的数,和小于0或一个小于0 的数减去一个大于0的数,返回错误
{flag=2;return error;}
else
{flag=0;return result;}
break;
case '*': //乘法运算
flag=0;result=n1*n2;
if (n1>=0 && n2>=0 && result<0 || n1<=0 && n2<=0 && result>0)
//两个大于0的数相乘,积小于0,或两个小于0的数相乘,积大于0,返回错误
{flag=2;return error;}
else
{flag=0;return result;}
break;
case '/': //除法运算
if(n2!=0) //如果被除数为0要返加ERROR
{flag=0;return n1/n2;break;}
else
//除数为0,返回错误
{flag=1;return error;break;}
}
flag=3;return error;
}
void main()
{
CExpression expression;
// sqstack opnd; //用于存放运算数
// sqstack optr; //用于存放运算符
int theta; //用于存放一个运算符
int a,b; //用于存放用于操作的两个数
int temp; //一个临时的变量
int flag2=0; //一个标志变量,用于判断是否要连接数字
int flag1; //一个标志变量,用于判断表达式是否是无效的
int cn=0; //用于存放字符的位置
int ops=0; //用于存放当前的操作数
char st1[255]; //表达式中最多有255个字符
char c; //用于表示当前的字符
for (a=0;a<255;a++) st1[a]='#'; //对数组初始化
expression.initstack(expression.opnd); //对栈OPND初始化
expression.initstack(expression.optr); //对栈OPTR初始化
expression.push(expression.optr,'#');
cin>>st1;
temp=strlen(st1);
if (st1[temp-1]!='#') st1[temp]='#'; //对表达式的结尾加入一个#
c=st1[0];
while(c!='#' || expression.gettop(expression.optr)!='#'){ //cout<<st1;
c=st1[cn];
if(isdigit(c)) {
ops=expression.numlink(c,ops,temp);
if (temp==ok)
{
if (flag2) expression.pop(expression.opnd,temp);
flag2=1;
expression.push(expression.opnd,ops);
cn++;
continue;
}
else
{cout<<"表达式的值过大,无法计算!"<<endl;return;}
}
else{
ops=0;
flag2=0;
temp=expression.precede(expression.gettop(expression.optr),c,temp); //temp为precede中的一个代号,为ok为正确的运算符比较,为error为错误的运算符比较
if (temp==error) {cout<<"表达式有误!无法求解!"<<endl;return;} //错误的运算符比较时,返回.
switch (temp){
case '<':
expression.push(expression.optr,c);cn++;break; //如果为<,操作符入栈
case '=':
expression.pop(expression.optr,temp);cn++;break; //如果为=,操作符出栈
case '>': //如果为>,执行运算操作
expression.pop(expression.optr,theta);
expression.pop(expression.opnd,b);
expression.pop(expression.opnd,a);
expression.operate(a,theta,b,flag1);
if (flag1==1) {cout<<"表达式有误!除数不能为0!"<<endl;return;}
else if(flag1==2) {cout<<"表达式的值过大或过小,无法计算!"<<endl;return;}
else if(flag1==3) {cout<<"未知道类型的错误!"<<endl;return;}
expression.push(expression.opnd,expression.operate(a,theta,b,flag1));
break;
case ' ':
cout<<"表达式有误!无法求解!"<<endl;return;
} //end switch
} //end if
} //end while
a=expression.gettop(expression.opnd);
cn=0;
while(st1[cn]!='#') cout<<st1[cn++]; //输出你所输入字符串
cout<<"=";
cout<<a<<endl; //输出最终结果
}
该程序的缺点是不能处理存在小数的表达式.