算术表达式有三种:中缀表达式、前缀表达式、后缀表达式,日常用的算术表达式为中缀表达式,其计算数值虽然一目了然,却不容易被计算机解释,其主要原因是在中缀表达式中,各运算符的优先级不同,不能简单地从表达式的左边直接计算到右边。所以要用两个栈实现,一个用来放操作数,一个用来放运算符。
算法步骤:
1.初始化并简历两个栈,一个用来放操作数OPND,一个用来放运算符OPTR,首先将操作数栈置为空栈,表达式起始符’#’为运算符栈底元素。
2.输入一个后缀表达式(以#结束),依次读入表达式中每个字符,若是操作数进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先级后做相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为’#’)。
3.算法中还调用了两个函数。其中Precede是判定运算符栈顶运算符θ1与读入运算符θ2之间优先关系的函数;Operateo为进行具体运算的函数,计算aθb并返回运算结果。
功能实现
1.元素类型,结点类型
typedef struct Stack
{
int* top;
int* base;
int capacity;
}SqStack1;//操作数栈
typedef struct Stack
{
char* top;
char* base;
int capacity;
}SqStack2;//运算符栈
2.栈的基本操作
Status Initstack(SqStack* S)//栈初始化
{
S->base = (int*)malloc(MAXSIZE * sizeof(int));
if (!S->base) exit(OVERFLOW);
S->top = S->base;
S->capacity = MAXSIZE;
return OK;
}
Status Push(SqStack* S, ElemType e)//入栈
{
if (S->top - S->base >= S->capacity)
{
S->base = (int*)realloc(S->base, (YICHUHOU + S->capacity) * (sizeof(int)));
if (!S->base) exit(OVERFLOW);
S->top = S->base + S->capacity;
S->capacity += YICHUHOU;
}
*S->top = e;
S->top++;
return OK;
}
Status Pop(SqStack* S, ElemType& e)//出栈
{
if (S->top == S->base)return ERROR;
--S->top;
e = *S->top;
return OK;
}
Status Gettop(SqStack* S, ElemType& e)//取栈顶元素
{
if (S->top == S->base)return ERROR;
e = *(S->top - 1);
return e;
}
核心代码讲解
4. 运算函数
int Operator(int a, char ch,int b)//对操作数进行相应计算
{
int c;
switch (ch)
{
case '*':
c = a * b;
break;
case '-':
c = b-a;
break;
case '+':
c = b + a;
break;
case '/':
c = b / a;
break;
default:
break;
}
return c;
}
运算符优先级
char Precede(char a,char b)//判段运算符优先级
{
int i,j;
//用二维数组存储运算符的优先级
char Table[8][8]={
' ','+','-','*','/','(',')','#',
'+','>','>','<','<','<','>','>',
'-','>','>','<','<','<','>','>',
'*','>','>','>','>','<','>','>',
'/','>','>','>','>','<','>','>',
'(','<','<','<','<','<','=',' ',
')','>','>','>','>','>',' ','>',
'#','<','<','<','<','<',' ','=',
};//优先级表格(根据上图)
for(i=0;i<8;i++)//纵坐标寻找
if(Table[0][i]==a)
break;
for(j=0;j<8;j++)//横坐标寻找
if(Table[j][0]==b)
break;
return Table[j][i];//返回查找到的字符,即优先级>,<或=
}
计算函数
int result(SqStack1 *OPND,SqStack2 *OPTR)
{
char a=0;
char theta;
int b,c,number=0;
IntInitstack(OPND);
CharInitstack(OPTR);
CharPush(OPTR,'#');// 表达式起始符’#’为运算符栈底元素
a=getchar();//输入一个字符
while(a!='#'||CharGettop(OPTR)!='#')
{
if(a>=’0’&&a<=’9’)//判断是否为数字
{
number=0;
while(!Is(a))
{
number=number*10+(a-48);//处理多位整数
a=getchar();
}
IntPush(OPND,number);//如果为个位数直接入数字栈
}
Else if(Is(a))//Is()是定义的一个判断是否为运算符的函数
switch(Precede(a,CharGettop(OPTR))//如果是运算符则比较优先级
{
case'>'://如果字符a的优先级小于栈顶元素
CharPush(OPTR,a);
a=getchar();
break;
case'=':
CharPop(OPTR);
a=getchar();
break;
case'<':
theta=CharPop(OPTR);
c=IntPop(OPND);
b=IntPop(OPND);
IntPush(OPND,Operate(b,theta,c));
break;
}
Else
printf("表达式不合法");//如果输入表达式有除数字和字符以外其他字符则不合法
break;
}
printf("结果:%d\n",IntGettop(OPND));
return OK;
}
完整代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MAXSIZE 100
#define YICHUHOU 10
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int ElemType;
typedef struct intStack
{
int* top;
int* base;
int capacity;
}SqStack1;
typedef struct charStack
{
char* top;
char* base;
int capacity;
}SqStack2;
Status IntInitstack(SqStack1* S1)
{
S1->base = (int*)malloc(MAXSIZE * sizeof(int));
if (!S1->base) exit(OVERFLOW);
S1->top = S1->base;
S1->capacity = MAXSIZE;
return OK;
}
Status IntPush(SqStack1* S1, ElemType e)
{
if (S1->top - S1->base >= S1->capacity)
{
S1->base = (int*)realloc(S1->base, (YICHUHOU + S1->capacity) * (sizeof(int)));
if (!S1->base) exit(OVERFLOW);
S1->top = S1->base + S1->capacity;
S1->capacity += YICHUHOU;
}
*S1->top = e;
S1->top++;
return e;
}
Status IntPop(SqStack1* S1)
{
ElemType e;
if (S1->top == S1->base)return ERROR;
--S1->top;
e = *S1->top;
return e;
}
Status IntGettop(SqStack1* S1)
{
ElemType e;
if (S1->top == S1->base)return ERROR;
e = *(S1->top - 1);
return e;
}
Status CharInitstack(SqStack2* S2)
{
S2->base = (char*)malloc(MAXSIZE * sizeof(char));
if (!S2->base) exit(OVERFLOW);
S2->top = S2->base;
S2->capacity = MAXSIZE;
return OK;
}
Status CharPush(SqStack2* S2,char e)
{
if (S2->top - S2->base >= S2->capacity)
{
S2->base = (char*)realloc(S2->base, (YICHUHOU + S2->capacity) * (sizeof(char)));
if (!S2->base) exit(OVERFLOW);
S2->top = S2->base + S2->capacity;
S2->capacity += YICHUHOU;
}
*S2->top = e;
S2->top++;
return OK;
}
char CharPop(SqStack2* S2)
{
char e;
if (S2->top == S2->base)return ERROR;
--S2->top;
e = *S2->top;
return e;
}
char CharGettop(SqStack2* S2)
{
char e;
if (S2->top == S2->base)return ERROR;
e = *(S2->top - 1);
return e;
}
int Operate(int a, char ch,int b)//对操作数进行相应计算
{
int c;
switch (ch)
{
case '*':
c = a * b;
break;
case '-':
c = a-b;
break;
case '+':
c = b + a;
break;
case '/':
c = a / b;
break;
default:
break;
}
return c;
}
char Precede(char a,char b)//判段运算符优先级
{
int i,j;
char Table[8][8]={
' ','+','-','*','/','(',')','#',
'+','>','>','<','<','<','>','>',
'-','>','>','<','<','<','>','>',
'*','>','>','>','>','<','>','>',
'/','>','>','>','>','<','>','>',
'(','<','<','<','<','<','=',' ',
')','>','>','>','>','>',' ','>',
'#','<','<','<','<','<',' ','=',
};//优先级表格
for(i=0;i<8;i++)//纵坐标寻找
if(Table[0][i]==b)
break;
for(j=0;j<8;j++)//横坐标寻找
if(Table[j][0]==a)
break;
return Table[j][i];
}
int Is(char c)
{
if(c=='('||c=='+'||c=='-'||c=='*'||c=='/'||c==')'||c=='#'||c=='^')
return 1;//如果是操作符返回1
else
return 0;//否则返回0
}
int result(SqStack1 *OPND,SqStack2 *OPTR)
{
char a=0;
char theta;
int b,c,number=0;
IntInitstack(OPND);
CharInitstack(OPTR);
CharPush(OPTR,'#');
a=getchar();
while(a!='#'||CharGettop(OPTR)!='#')
{
//printf("输入字符:%c",a);
if(a>='0'&&a<='9')
{
number=0;
while(!Is(a))
{
number=number*10+(a-48);//处理多位整数
a=getchar();
}
IntPush(OPND,number);
}
else if(Is(a))
switch(Precede(a,CharGettop(OPTR)))
{
case '>':
CharPush(OPTR,a);
a=getchar();
break;
case '=':
CharPop(OPTR);
a=getchar();
break;
case '<':
theta=CharPop(OPTR);
c=IntPop(OPND);
b=IntPop(OPND);
IntPush(OPND,Operate(b,theta,c));
break;
}
else
printf("表达式不合法");
break;
}
printf("结果:%d\n",IntGettop(OPND));
return OK;
}
int main()
{
SqStack1 OPND;
SqStack2 OPTR;
IntInitstack(&OPND);
CharInitstack(&OPTR);
printf("输入以#结尾的表达式:\n");
result(&OPND,&OPTR);
return 0;
}
运行结果