表达式求值

表达式求值(中缀表达式)

刚刚学完数据结构中表达式求值,写完表达式求值代码后的一个总结!

基本要求

  1. 熟悉栈的基本操作

  2. 了解算符间优先关系

  3. 掌握getchar()函数的功能。下面是getchar()函数的功能

    https://www.cnblogs.com/jiangjun/archive/2012/05/16/2503676.html

思路

  1. 定义一个变量。利用getchar()函数将字符转换为数字。getchar()可以取函数缓存区的元素,利用这点可以使用户直接输入一个表达式,然后getchar()逐个取元素。

    注意:getchar()对于数字也是一位一位的取,所以之后需要对数字进行处理

  2. 算数运算规则

    • 先乘除后加减

    • 从左算到右

    • 先括号内,后括号外

  1. image-20210412171245917

    • 01<02 01的优先级低于02

    • 01=02 01的优先级等于02

    • 01>02 01的优先级高于02

代码

/*
Name: 表达式求值
Author: 小神
Date: 30/03/21 21:03
Description:暂时只能进行整数表达式求值
*/
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define STACK_INIT_SIZE 100//栈的初始长度
#define STACKINCREMENT 10//当栈空间不够时,每次增加栈长

typedef int ElemType;
typedef int Status;

//定义一个栈
typedef struct {
ElemType *base;
ElemType *top;
int stacksize;//栈的实际长度
}SqStack;

//构造一个空栈
Status InitStack(SqStack &OP) {
OP.base = (ElemType*)malloc(STACK_INIT_SIZE*sizeof(ElemType));
if(!OP.base) exit(OVERFLOW);
OP.top = OP.base;
OP.stacksize = STACK_INIT_SIZE;
return OK;
}

//若栈不空,用e返回栈顶元素,并返回OK,否则返回ERROR
Status GetTop(SqStack OP, ElemType &e) {
// if(OP.base = OP.top) return ERROR;//这里我也不懂为啥要注释,反正注释了程序可执行
e = *(OP.top - 1);
return OK;
}

//插入元素e为新栈顶元素
Status Push(SqStack &OP, ElemType e) {
if(OP.top - OP.base >= OP.stacksize) {
OP.base = (ElemType*)realloc(OP.base, (OP.stacksize + STACKINCREMENT) * sizeof(ElemType));
if(!OP.base) exit(OVERFLOW);
OP.top = OP.stacksize + OP.base + 1;
OP.stacksize += STACKINCREMENT;
}
*OP.top++ = e;
return OK;
}

//若栈不空,删除栈顶元素,用e返回其值,并返回OK,否则返回ERROR
Status Pop(SqStack &OP, ElemType &e) {
if(OP.base == OP.top) return ERROR;
e = *(--OP.top);
return OK;
}

//判断是数字还是字符,字符返回0,数字返回1    
//字符0-9对应的ASCLL为48-57
int In(int c) {
if(c >= 48 && c <= 57) return OK;
return ERROR;
}

//算符栈的栈顶元素与c的算符比较,得出">","=","<"
char Precede(ElemType cc, ElemType c) {
int i, j;
int b[7][7] = {{'>', '>', '<', '<', '<', '>', '>'}, {'>', '>', '<', '<', '<', '>', '>'},
{'>', '>', '>', '>', '<', '>', '>'}, {'>', '>', '>', '>', '<', '>', '>'},
{'<', '<', '<', '<', '<', '=', ' '}, {'>', '>', '>', '>', ' ', '>', '>'},
{'<', '<', '<', '<', '<', ' ', '='}};
int a[7] = {'+', '-', '*', '/', '(', ')', '#'};
for(j = 0; j < 7; j++) //寻找栈顶元素下标
if(cc == a[j]) break;
for(i = 0; i < 7; i++) //寻找输入元素的下标
if(c == a[i]) break;
return b[j][i];//返回优先权
}

//若连续出现数字,返回其真实值,c1是数字栈的栈顶元素,c2是连续的数
//getchar()对于数字也是一位一位的读入
ElemType original(ElemType c1, ElemType c2) {
c1 = c1 * 10 + (c2 - 48);
return c1;
}

//在算符栈顶元素的优先权大于输入元素时进行的操作
//a,b为数字栈的栈顶元素,theta为算符栈栈顶元素
ElemType Operate(ElemType a, ElemType theta, ElemType b) {
switch(theta) {
case 43:return a + b;//'+'的ASCLL为43
case 45:return a - b;
case 42:return a * b;
case 47:return a / b;
default:return ERROR;
}
}

//表达式求值算法
ElemType EvaluateExpression() {
SqStack OPTR, OPND;//构造一个运算符栈OPTR和运算数栈OPND
int i = 1;//记录是否有连续的数输入
ElemType c, e, cc, a, b, theta, sum, x;//c从左向右逐个取表达式的元素
//e用于返回值,cc用于返回运算符栈顶元素,sum为表达式最后的值,x用于消除栈中没用的元素
InitStack(OPTR);//创建运算符栈,
Push(OPTR,'#');//规定#为结束符
InitStack(OPND);//创建运算数栈
c = getchar();
GetTop(OPTR, cc);
while(c != '#' || cc != '#') {
if(In(c)) {
//当出现两位以上数字时
if(i > 1) {
Pop(OPND, e);
c = original(e, c);
Push(OPND, c);
}
else {
Push(OPND, c - 48);
i++;
}
c = getchar();
}
else {
i = 1;
GetTop(OPTR, cc);
switch(Precede(cc, c)) {
case '<':Push(OPTR, c); c = getchar(); break;
case '=':Pop(OPTR, x); c = getchar(); break;
case '>':{
Pop(OPTR, theta);
Pop(OPND, b);
Pop(OPND, a);
Push(OPND,Operate(a, theta, b));
break;
}
}
}
GetTop(OPTR, cc);
}
GetTop(OPND, sum);
return sum;
}

int main() {
ElemType sum, e;
printf("请输入要求的表达式(以'#'表示输入结束,不要输入'='):\n");
sum = EvaluateExpression();
printf("%d", sum);
return 0;
}

 

posted @ 2021-04-12 17:40  小神成长之路!  阅读(80)  评论(0编辑  收藏  举报