VC下实现多项式的加减乘除

来源:互联网 发布:1942河南大饥荒 知乎 编辑:程序博客网 时间:2024/06/11 21:52

#include"stdio.h"
#include "stdlib.h"
#define  ERROR  99999
#define  LFTE_BRACE  5
#define  RIGHT_BRACE 6
#define  END         7
float calc_two(char sybol,float number1,float number2);
/*------------------------------------*/
typedef struct NODE
{
 float data;
 struct NODE *next;
}sign_data;
/*-------------------------------------
进栈函数push_stack()
---------------------------------------*/
int push_stack(float data,sign_data** data_top)
{
 sign_data* p=NULL;
 p = (void *)malloc(sizeof(sign_data));
 if(p==NULL) return 0;
 (*p).data = data;//把要送入的数据给节点
 (*p).next = (*data_top);//节点的指针指向
 (*data_top) = p;
 return 1;
}
/*----------------------------------------
出栈函数pop_stack()
-----------------------------------------*/
float pop_stack(sign_data **data_top)
{
    sign_data pop_data;
 if(*data_top==NULL) return 0;
 pop_data.data = (*data_top)->data;
 pop_data.next = (*data_top)->next;
 free(*data_top);
 *data_top = pop_data.next;
 return pop_data.data;
}
typedef struct oper
{
 char symbol[2];
 int number;
}symbol_data;

symbol_data express_sign[]={
 {{' ',' ' },0},
 {{'+','/0'},1},
 {{'-','/0'},2},
 {{'*','/0'},3},
 {{'/','/0'},4},
 {{'(','/0'},5},
 {{')','/0'},6},
 {{'/0','/0'},7},
};

/*----------------------------------------------------
优先级的设计:
优先级分为:当前优先级和栈顶优先级
只有当当前的优先级小于栈顶的优先级才能够进行出栈的操作
-------------------------------------------------------*/
int fr_pri[] = {0,2,2,3,3,4,1,1};//当前的优先级
int bre_pri[]= {0,2,2,3,3,1,4,1};//栈顶的优先级

int get_token(char *express,int *postion,float *data);

float calc(char *express)
{
 float data=0.0;//用来存储返回的数字
 int postion=0;
 float reasult;
    sign_data  *number_top;//用来存储数字
 sign_data  *symbol_top;//用来存储运算符号
 float symbol;
 float data1;
 float data2;
    //char *express="4+4+((4+8)*9-230)";
    int c=0;
 unsigned int flag=1;

 /*------------------------------
 首先是左括号进栈
 --------------------------------*/
 push_stack(LFTE_BRACE,&symbol_top);

 //while(express[postion]!='/0')
 while(flag==1)
 {
      c = get_token(express,&postion,&data);
    if(c==0)
    {
   push_stack(data,&number_top);
    }
    /*-------------------------------------------
    这是获取的是符号的情况,我们获取的是符号的编号
    符号进栈的条件是:
          比栈顶的符号的优先级要高
  符号出栈的条件是:
       当前符号的优先级比栈顶符号优先级要高,那么
    符号就可以出栈
    ----------------------------------------------*/
    else
    {
   if(fr_pri[c] > bre_pri[(int)symbol_top->data])
   {
    push_stack((float)c,&symbol_top);//如果当前的优先级大于运算符号栈顶的优先级那么就压入堆栈。
   }
   else
   {
    /*------------------------------------------------------------------------------
    条件语句是:判断当前符号的优先级要比符号栈顶的优先级要低,并且符号栈顶的元素不是(
    这里最好要用while循环,
    --------------------------------------------------------------------------------*/
    while((fr_pri[c] <= bre_pri[(int)symbol_top->data])&&(symbol_top->data!=5))
    {
     data2=pop_stack(&number_top);

     data1=pop_stack(&number_top);

                    symbol = pop_stack(&symbol_top);

     reasult = calc_two(express_sign[(int)symbol].symbol[0] ,data1,data2);

     push_stack(reasult,&number_top);
    }
                /*-------------------------------------------------------
    对括号的处理:删除左括号:如果栈顶是'('当前的符号是')'那么就要删除栈顶的(
    ---------------------------------------------------------*/
    if(symbol_top->data==LFTE_BRACE&&(c==RIGHT_BRACE))
    {
     pop_stack(&symbol_top);
    }
    /*---------------------------------------------------------------
    对当前符号的处理:如果当前的符号不是右括号那么这个符号就要进栈
    -----------------------------------------------------------------*/
    if(c!=RIGHT_BRACE&&c!=END)
    {
     push_stack((float)c,&symbol_top);
    }
    /*--------------------------------------------------------------
    对结果的处理:当栈顶元素是(,当前的符号是/0表示的是计算的结果
    ----------------------------------------------------------------*/
    if((int)symbol_top->data==5&&c==7)
    {
     return pop_stack(&number_top);
     flag=0;
    }
   }
    }
 }
 return ERROR;
}
/*-----------------------------------------------------------------
函数名称:int get_token(char *express,int *postion,int *data)
函数的功能:获取在express里面的符号和数字
函数的返回值: 0表示的是从express里面获取的是数字并且存放到变量data里面
              !0表示的运算符号的标号,他的标号是从1开始的
--------------------------------------------------------------------*/
int get_token(char *express,int *postion,float *data)
{
 unsigned int i;
    if((express[*postion]<'0')||(express[*postion]>'9'))
 {
        for(i=1;i<8;i++)
  {
   if(express[*postion]==express_sign[i].symbol[0])
   {
    *postion = (*postion)+1;
    return express_sign[i].number;
   }
  }
 }
 else
 {
  float number_data=0.0;
  while(1)
  {
   number_data=express[*postion] -'0'+ number_data;
   *postion=(*postion)+1;
   if((express[*postion]>='0')&&(express[*postion]<='9'))
   {
    number_data=number_data*10;
   }
   else
   {
    *data = number_data;
    return 0;
   }
  }
 }
 return ERROR;
}
/*---------------------------------
实际的运算过程
-----------------------------------*/
float calc_two(char sybol,float number1,float number2)
{
    float result;
 switch(sybol)
 {
  case '+': result = number1 + number2;
         break;
  case '-':result = number1 - number2;
         break;
  case '*': result = number1 * number2;
             break;
    case  '/': result = number1/number2;
             break;
 }
 return result;
}
/*-------------------------------
用来测试进栈和出栈的函数
--------------------------------*/
ceshi_main()
{
 sign_data *number;
    unsigned int i;
 for(i=0;i<20;i++)
 {
      push_stack((float)i,&number);
 }
 while(i!=0)
 {
  (float)i=pop_stack(&number);
  printf("%d",i);
 } 
}
main()
{
 char express[100];
 printf("请输入要计算的多项式表达式:");
 gets(express);
 printf("%f",calc(express));
}

原创粉丝点击