表达式求解

来源:互联网 发布:吉他入门 知乎 编辑:程序博客网 时间:2024/05/17 03:39


/*---------------------------------------------------------------------------------------------------
目的:编程实现表达式的求值,例如:4+2*3-10/5 = 8
思路:1.表达式是由操作数(operand),运算符(operator)和定界符组成的。
   2.用顺序栈来实现,那么就需要构造两个栈:OPTR栈和OPND栈
   3.扫描表达式,遇到operand就压入栈OPND,遇到operator就压入栈OPTR
   4.判断运算符的优先级,当后一个运算符的优先级高于前一个运算符的优先级时,就弹出运算符和操作数,
  运算后的结构压入到opnd中. 
----------------------------------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define STACK_INTI_SIZE 100  //存储空间初始分配量
#define STACKINCREMENT 10  //存储空间的分配增量
#define N 11
typedef int SElemType;
/*算符间的优先关系表(+,-,*,/,(,),#)*/
char cpri[7][7]={
     {'>','>','<','<','<','>','>' },
     {'>','>','<','<','<','>','>' },
     {'>','>','>','>','<','>','>' },
     {'>','>','>','>','<','>','>' },
     {'<','<','<','<','<','=',' '},
     {'>','>','>','>',' ','>','>'},
     {'<','<','<','<','<',' ','='}
    };


/*定义栈的函数*/
typedef struct
{
 SElemType *base; //栈底指针
 SElemType *top;  //栈顶指针 
 int stacksize;  //当前已分配的存储空间,以元素为单位
}Sqstack;


/*栈的初始化,分配失败返回0,否则返回让栈顶指针指向栈顶指针,并返回1*/
int InitStack(Sqstack &s)
{
 s.base = (SElemType *)malloc(STACK_INTI_SIZE * sizeof(SElemType));
 if(!s.base)
  return 0;  //存储分配失败,返回error
 s.top = s.base;  //分配成功则让栈顶指针指向栈底指针
 s.stacksize = STACK_INTI_SIZE;
 return 1;
}

/*若栈不为空,则用e返回s的栈顶元素,并返回OK,否则返回error*/
int Gettop(Sqstack &s)
{ int e;
 if(s.top == s.base) return 0;
 e = *(s.top - 1); //注意这条语句,是先让top-1指向栈顶元素,再取元素的。
 return e;
}

/*插入元素e为新的栈顶元素,注意栈满的操作*/
int push(Sqstack &s,SElemType e)
{
 if(s.top - s.base >= s.stacksize) //栈满,追加存储空间
 {
  //新分配空间的栈底
  s.base = (int*)realloc(s.base, (s.stacksize +STACKINCREMENT)*sizeof(int)) ;
  if(!s.base) return 0; //存储分配失败
 /*realloc函数分配内存的方式:开辟一个新的空间,并且将原有空间的内容复制到新分配的空间中,
  *但新分配的空间s.base = s.top的,所以才有s.top= s.base+ s.stacksize*/
  s.top = s.base + s.stacksize;
  s.stacksize += STACKINCREMENT;//给新分配的存储空间分配存储容量
 }
 *s.top++ = e; //注意指针*与++的优先级,top指针先上移
 return 1;
}

/*出栈操作:若栈不为空,则删除栈顶元素,用e返回其值,否则返回error*/
int pop(Sqstack &s,SElemType *e)
{
 if(s.top == s.base) return 0;//栈空
 *e = *(--s.top);//注意此步操作
 return 1;
}
/*判断输入的是否为包含在指定字符集中,如果是则返回1,否则返回0*/
int is_optr(char c)
{
 switch(c) 
    { 
        case '+': 
        case '-': 
        case '*': 
        case '/': 
        case '(': 
        case ')': 
        case '#': 
            return 1;
        default: 
            return 0; 
    } 
}
/*返回运算符在数组中的索引*/
int index(char c)
{
 int in;
 switch(c)
 {
  case '+':
   in =  0;
   break;
  case '-':
   in =  1;
   break;
  case '*':
   in =  2;
   break;
  case '/':
   in =  3;
   break;
  case '(':
   in =  4;
   break;
  case ')':
   in =  5;
   break;
  case '#':
   in =  6;
   break;
 }
 return in;
}
/*运算符优先级的判定*/
char precede(char top,char c)
{
 int i,j;
 i=index(top);
 j=index(c);
 return cpri[i][j];
}

//运算函数
int operate(int a,char theta,int b)
{
 int result;
 switch(theta)
 {
  case '+':
   result = a+b;
   break;
  case '-':
   result = a-b;
   break;
  case '*':
   result = a*b;
   break;
  case '/':
   result = a/b;
   break;
 }
 return result;
}

/*算术表达式的求值过程*/
int evaluate()
{
 int k = 0;
 int num = 0;
 char c=0,theta=0;
 char a=0,b=0;
 Sqstack OPND;
 Sqstack OPTR;
 InitStack(OPTR);
 InitStack(OPND);
 push(OPTR,'#');
 char exp[11]; //表达式
 gets(exp); 
 c = exp[k];
 k++;
 while(c != '#' || Gettop(OPTR) != '#')
 {
  //不是运算符则进操作数栈
  if(!is_optr(c))
  {
   num = c - '0'; //字符转换成十进制数
   c = exp[k]; //读取下一字符
   k++;
   while(!is_optr(c)) //下一字符仍是数字
   {
    num = num * 10 + c - '0'; //转换成多位整数
    c = exp[k];
    k++;
   }
   push(OPND,num);
  }
  else
   switch(precede(Gettop(OPTR),c))
   {
    case '<':
     push(OPTR,c);
        c = exp[k];//栈顶元素的优先权低
     k++;
     break;
    case '=': //脱括号并接受下一字符
     pop(OPTR,(int*)&c);
     c = exp[k];
     k++;
     break;
    case '>': //退栈并将运算结果入栈
     pop(OPTR,(int*)&theta);       
     pop(OPND,(int*)&b);
     pop(OPND,(int*)&a);
     push(OPND,operate(a,theta,b));  
     break;
       
   }
 }
 return Gettop(OPND);
}
void main()
{
 printf("请输入表达式以#结尾: ");
 
 printf("%d\n",evaluate());
}