最近在网上看到一个求解数学表达式程序,感觉很不错,故拿出来修改之后供大家一起分享.
程序如下:
#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; //输出最终结果
}

该程序的缺点是不能处理存在小数的表达式.


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


posts - 4, comments - 4, trackbacks - 0, articles - 0

Copyright © 疯蝶雨人