由于正常情况下一般采用=作为表达式结尾,故本文所示代码将课本中的‘#’改为了‘=’以便更好地应用于现实情况
一、表达式求值所用到的数据结构——栈
首先来实现栈的基本操作,不知道的可以看我之前发过的一篇文章:栈的基本操作
在表达式求值中,只需用到以下列出的几个函数
typedef char SElemType;
typedef char Status;
typedef struct {
SElemType* top;
SElemType* base;
int stacksize;
}Stack;
Status InitStack(Stack& S);
bool StackEmpty(Stack S);
int StackLength(Stack S);
Status DestroyStack(Stack& S);
Status Push(Stack& S, SElemType e);
Status Pop(Stack& S, SElemType& e);
Status GetTop(Stack S);
不再进行额外的解释,下面附上这些函数的代码
Status GetTop(Stack S)
{
if (S.top == S.base)return 0;
Status e = *(S.top - 1);
return e;
}
Status InitStack(Stack& S)
{
S.base = (SElemType*)malloc(sizeof(SElemType) * MAXSIZE);
if (!S.base)return 0;
S.top = S.base;
S.stacksize = MAXSIZE;
return 1;
}
bool StackEmpty(Stack S)
{
return S.top == S.base;
}
int StackLength(Stack S)
{
return S.top - S.base;
}
Status DestroyStack(Stack& S)
{
if (!S.base)return 0;
free(S.base);
S.base = S.top = NULL;
return 1;
}
Status Push(Stack& S, SElemType e)
{
if (!S.base)return 0;
if (S.top - S.base == S.stacksize)return 0;
*S.top++ = e;
return 1;
}
Status Pop(Stack& S, SElemType& e)
{
if (StackEmpty(S))return 0;
e = *--S.top;
return 1;
}
二、表达式求值核心函数
1.核心函数
int EvaluateExpression()
{
char x;
Stack OPTR, OPND;
InitStack(OPTR);
InitStack(OPND);
Push(OPTR, '=');
char c = getchar();
while (c != '=' || GetTop(OPTR) != '=')
{
printf("OPTR:"); for (int i = 0; i < OPTR.top - OPTR.base; i++)printf("%c ", OPTR.base[i]); puts("");
printf("OPND:"); for (int i = 0; i < OPND.top - OPND.base; i++)printf("%d ", OPND.base[i]); puts("\n");
if (!In(c)){Push(OPND, c-'0'); c = getchar(); }
else
{
switch (Precede(GetTop(OPTR), c))
{
case'<':
Push(OPTR, c);
c = getchar();
break;
case'=':
Pop(OPTR, x);
c = getchar();
break;
case'>':
char theta, p, q;
Pop(OPTR, theta);
Pop(OPND, p);
Pop(OPND, q);
Push(OPND, Operate(p, theta, q));
}
}
}
int g = (int)GetTop(OPND);
DestroyStack(OPTR);
DestroyStack(OPND);
return g;
}
在这个函数中用到了一些除了栈的基本操作外的其他函数,下面逐一说明这些函数的功能
2.判断字符函数
在主函数中用此函数用来判断最后一个输入的字符是否是运算符
bool In(char c)
{
if (c <= '9' && c >= '0')return 0;
else return 1;
}
3.判断优先级的函数
在主函数中用来判断两个运算符的优先级谁大谁小
Status Precede(char a, char b)
{
char x[10] = {'+','-','*','/','(',')','='};
char OP[10][10] = { {'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=',' '},
{'>','>','>','>',' ','>','>'},
{'<','<','<','<','<',' ','='} };
for (int i = 0; i < 7; i++)
{
if (a == x[i])a = i;
if (b == x[i])b = i;
}
return OP[a][b];
}
4.运算函数
用来运算,注意在出栈的时候后者先出,故减和除的运算数需要颠倒,其次注意除法分母不为零
char Operate(char p, char theta, char q)
{
if (theta == '+')return p + q;
else if (theta == '-')return q - p;
else if (theta == '*')return p * q;
else if (theta == '/')
{
if (p == 0)
{
printf("输入不合法!");
return INF;
}
return q / p;
}
else return INF;
}
三、总代码和运行结果展示
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
#define INCREAMENTSIZE 10
#define INF 1e9
typedef char SElemType;
typedef char Status;
typedef struct {
SElemType* top;
SElemType* base;
int stacksize;
}Stack;
Status InitStack(Stack& S);
bool StackEmpty(Stack S);
int StackLength(Stack S);
Status DestroyStack(Stack& S);
Status Push(Stack& S, SElemType e);
Status Pop(Stack& S, SElemType& e);
Status GetTop(Stack S);
int EvaluateExpression();
char Operate(char p, char theta, char q);
bool In(char c);
Status Precede(char a, char b);
int main()
{
printf("请输入一串表达式,以等号“=”结尾:");
printf("最终结果为:%d", EvaluateExpression());
return 0;
}
int EvaluateExpression()
{
char x;
Stack OPTR, OPND;
InitStack(OPTR);
InitStack(OPND);
Push(OPTR, '=');
char c = getchar();
while (c != '=' || GetTop(OPTR) != '=')
{
printf("OPTR:"); for (int i = 0; i < OPTR.top - OPTR.base; i++)printf("%c ", OPTR.base[i]); puts("");
printf("OPND:"); for (int i = 0; i < OPND.top - OPND.base; i++)printf("%d ", OPND.base[i]); puts("\n");
if (!In(c)){Push(OPND, c-'0'); c = getchar(); }
else
{
switch (Precede(GetTop(OPTR), c))
{
case'<':
Push(OPTR, c);
c = getchar();
break;
case'=':
Pop(OPTR, x);
c = getchar();
break;
case'>':
char theta, p, q;
Pop(OPTR, theta);
Pop(OPND, p);
Pop(OPND, q);
Push(OPND, Operate(p, theta, q));
}
}
}
int g = (int)GetTop(OPND);
DestroyStack(OPTR);
DestroyStack(OPND);
return g;
}
Status Precede(char a, char b)
{
char x[10] = {'+','-','*','/','(',')','='};
char OP[10][10] = { {'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=',' '},
{'>','>','>','>',' ','>','>'},
{'<','<','<','<','<',' ','='} };
for (int i = 0; i < 7; i++)
{
if (a == x[i])a = i;
if (b == x[i])b = i;
}
return OP[a][b];
}
char Operate(char p, char theta, char q)
{
if (theta == '+')return p + q;
else if (theta == '-')return q - p;
else if (theta == '*')return p * q;
else if (theta == '/')
{
if (p == 0)
{
printf("输入不合法!");
return INF;
}
return q / p;
}
else return INF;
}
bool In(char c)
{
if (c <= '9' && c >= '0')return 0;
else return 1;
}
Status GetTop(Stack S)
{
if (S.top == S.base)return 0;
Status e = *(S.top - 1);
return e;
}
Status InitStack(Stack& S)
{
S.base = (SElemType*)malloc(sizeof(SElemType) * MAXSIZE);
if (!S.base)return 0;
S.top = S.base;
S.stacksize = MAXSIZE;
return 1;
}
bool StackEmpty(Stack S)
{
return S.top == S.base;
}
int StackLength(Stack S)
{
return S.top - S.base;
}
Status DestroyStack(Stack& S)
{
if (!S.base)return 0;
free(S.base);
S.base = S.top = NULL;
return 1;
}
Status Push(Stack& S, SElemType e)
{
if (!S.base)return 0;
if (S.top - S.base == S.stacksize)return 0;
*S.top++ = e;
return 1;
}
Status Pop(Stack& S, SElemType& e)
{
if (StackEmpty(S))return 0;
e = *--S.top;
return 1;
}
运行结果: