表达式求值

  • 一、实验题目
    • 1.案例分析
    • 2.案例实现
    • 3.算法步骤
    • 4.算法描述
  • 二、工具环境
  • 三、实验问题
  • 四、实验代码

一、实验题目

1.案例分析

任何一个表达式都是由操作数(operand)运算符(operator)和界限符(delimiter)组成的,统称它们为单词。一般地,操作数既可以是常数,也可以是被说明为变量或常量的标识符;运算符可以分为算术运算符、关系运算符和逻辑运算符 3 类;基本界限符 有左右括号和表达式结束符等。为了叙述的简洁,在此仅讨论简单算术表达式的求值问题,这种表达式只含加、减、乘、除4种运算符。读者不难将它推广到更一般的表达式上。
下面把运算符和界限符统称为算符。
我们知道,算术四则运算遵循以下 3条规则:
(1)先乘除,后加减;
(2)从左算到右;
(3)先括号内,后括号外。
根据上述 3条运算规则,在运算的每一步中,任意两个相继出现的算符θ1和θ2之间的优先关系,至多是下面 3 种关系之一 :
θ1 < θ2 θ1的优先权低于θ2
θ1 = θ2 θ1的优先权等于θ2
θ1 > θ2 θ1的优先权高于θ2
表 3.1 定义了算符之间的这种优先关系。

由规则(1), 先进行乘除运算,后进行加减运算,所以有 “+” < “*”; “+” < “/”; “*” >"+"; “/” > “+” 等。
由规则(2), 运算遵循左结合性,当两个运算符相同时,先出现的运算符优先级高,所以有"+" > “+”; “-” > “-”; “*” > “*”; “/” > “/”。
由规则(3), 括号内的优先级高,+、-、*和/为θ1时的优先性均低千 (" “但高于 " )”。
表中的 “(” = “)” 表示当左右括号相遇时,括号内的运算已经完成。为了便千实现,假设每个表达式均以"#“开始,以”#" 结束。所以"#" = “#” 表示整个表达式求值完毕。")“与 “(”、"#”与”)" 以及"(“与”#" 之间无优先关系,这是因为表达式中不允许它们相继出现,一旦遇到这种情况,则可以认为出现了语法错误。在 下面的讨论中,我们暂假定所输人的表达式不会出现语法错误。

2.案例实现

为实现算符优先算法,可以使用两个工作栈,一个称做OPTR,用以寄存运算符;另一个称作OPND, 用以寄存操作数或运算结果。

3.算法步骤

1.初始化OPTR栈和OPND栈,将表达式起始符“#”压入OPTR栈。
2.扫描表达式,读人第一个字符ch,如果表达式没有扫描完毕至“#”或OPTR的栈顶元素不为“#”时,则循环执行以下操作:
若ch不是运算符,则压入OPND栈,读入下一字符ch;
若ch是运算符,则根据OPTR 的栈顶元素和ch的优先级比较结果,做不同的处理:
若是小于,则ch 压入OPTR栈,读入下一字符ch;
若是大于,则弹出OPTR栈顶的运算符,从 OPND栈弹出两个数,进行相应运算,结果压入OPND栈;
若是等于,则OPTR 的栈顶元素是“(”且ch是“)”,这时弹出OPTR栈顶的“(”,相当于括号匹配成功,然后读人下一字符ch。
3.OPND栈顶元素即为表达式求值结果,返回此元素。

4.算法描述

char EvaluateExpression ()
{//算术表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和操作数栈InitStack(OPND); //初始化OPND栈InitStack(OPTR); //初始化OPTR栈Push (OPTR,'#') ; // 将表达式起始符"#" 压人OPTR栈cin>>ch; while(ch!='#' | | GetTop(OPTR) !='#' ) //表达式没有扫描完毕或OPTR的栈顶元素不为"# "{if (!In (ch)) {Push (OPND, ch); cin»ch;} //ch不是运算符则进OPND栈else switch (Precede (GetTop (OPTR) , ch))  //比较OPTR的栈顶元素和ch的 优先级{case'<': Push(OPTR,ch);cin>>ch; //当前字符ch压入OPTR栈,读入下一字符chbreak; case'>': Pop(OPTR,theta); //弹出OPTR栈顶的运算符Pop(OPND,b);Pop(OPND,a); //弹出OPND栈顶的两个运算数Push (OPND, Operate (a, theta, b·)); / /将运算结果压入OPND栈break; case'=': //OPTR的栈顶元素是"("且ch是")"Pop(OPTR,x) ;cin>>ch; //弹出OPTR栈顶的"(", 读入下一字符chbreak; }//switch }//while return GetTop (OPND) ; //OPND栈顶元素即为表达式求值结果
}

算法调用的三个函数需要读者自行补充完成。其中函数In是判定读入的字符ch是否为运算符,Precede 是判定运算符栈的栈顶元素与读入的运算符之间优先关系的函数,Operate为进行二元运算的函数。

二、工具环境

Window10操作系统,Microsoft Visual C++2010学习版 集成开发环境,C语言

三、实验问题

另外需要特别说明的是,上述算法中的操作数只能是一位数,因为这里使用的OPND栈是字符栈,如果要进行多位数的运算,则需要将OPND栈改为数栈,读入的数字字符拼成数之后再入栈。 读者可以改进此算法,使之能完成多位数的运算。

四、实验代码

#include<stdio.h>
#include<stdlib.h>#define MAXSIZE 100    //顺序栈存储空间的初始分配址
#define OK  1
#define ERROR  0
#define OVERFLOW -2typedef int  Status;
typedef char SElemType;typedef struct
{char *base;      //栈底指针char *top;       //栈顶指针int stacksize;   //栈可用的最大容量
}SqStack;Status InitStack(SqStack *S);//构造一个空栈s
Status Push(SqStack *S,char e);//插入元素e为新的栈顶元素
Status Pop(SqStack *S,char *e);//删除s的栈顶元素,用e返回其值
SElemType GetTop(SqStack S);//返回s的栈顶元素,不修改栈顶指针
Status In(char e);//判断读入字符是否为运算符
SElemType Precede(char a,char b);//比较运算符的优先级,a为纵轴值,b为横轴值
int Operate(int i,char theta,int j);//计算a(theta)b结果
char EvaluateExpression();//算术表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和操作数栈int main()
{printf("请输入算术表达式,并以#结束(操作数只能是一位数):");printf("表达式结果是:%d",EvaluateExpression());return 0;
}Status InitStack(SqStack *S)
{//构造一个空栈sS->base=(char *)malloc(MAXSIZE*sizeof(char));//为顺序栈动态分配一个最大容量为MAXSIZE的数组空间if(!S->base) exit(OVERFLOW);         //存储分配失败S->top=S->base;            //top初始为base,空栈S->stacksize=MAXSIZE;     //stacksize置为栈的最大容量MAXSIZEreturn OK;
}Status Push(SqStack *S,char e)
{//插入元素e为新的栈顶元素if(S->top-S->base==S->stacksize) return ERROR;    //栈满*S->top++=e;           //元素e压入栈顶,栈顶指针加1return OK;
}Status Pop(SqStack *S,char *e)
{//删除s的栈顶元素,用e返回其值if(S->top==S->base) return ERROR;   //栈空*e=*--S->top;    //栈顶指针减1,将栈顶元素赋给ereturn OK;
}     SElemType GetTop(SqStack S)
{//返回s的栈顶元素,不修改栈顶指针if(S.top!=S.base)   //栈非空return *(S.top-1);   //返回栈顶元素的值,栈顶指针不变
}Status In(char e)
{//判断读入字符是否为运算符if(e=='+'||e=='-'||e=='*'||e=='/'||e=='('||e==')'||e=='#')return OK;//是elsereturn ERROR;//不是
}SElemType Precede(char a,char b)
{//比较运算符的优先级,a为纵轴值,b为横轴值char f;if(a=='+'||a=='-'){if(b=='+'||b=='-'||b==')'||b=='#')f='>';else if(b=='*'||b=='/'||b=='(')f='<';}else if(a=='*'||a=='/'){if(b=='+'||b=='-'||b=='*'||b=='/'||b==')'||b=='#')f='>';else if(b=='(')f='<';}else if(a=='('){if(b=='+'||b=='-'||b=='*'||b=='/'||b=='(')f='<';else if(b==')')f='=';}else if(a==')'){if(b=='+'||b=='-'||b=='*'||b=='/'||b==')'||b=='#')f='>';}else if(a=='#'){if(b=='+'||b=='-'||b=='*'||b=='/'||b=='(')f='<';else if(b=='#')f='=';}return f;
}int Operate(int i,char theta,int j)
{//计算a(theta)b结果int result;switch(theta)   {case '+': result = i + j; break;case '-': result = i - j; break;case '*': result = i * j; break;case '/': result = i / j; break;}return result;
}char EvaluateExpression()
{//算术表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和操作数栈SqStack OPND,OPTR;int ch; //把读入的字符转换为整数型,即ASCII表值char a,b,theta,x; //ch为当前读入字符, theta为运算符,x仅仅只是变量寄存弹出值,对计算表达式无影响InitStack(&OPND); //初始化OPND栈,寄存操作数和运算结果InitStack(&OPTR); //初始化OPTR栈,寄存运算符Push(&OPTR,'#');ch=getchar();while(ch!='#'||GetTop(OPTR)!='#'){printf(" %c\n",ch);if(!In(ch))//ch不是运算符则进OPND栈{ch=ch-48;//数字字符转换为对应整数Push(&OPND,ch);ch=getchar();}else{switch(Precede(GetTop(OPTR),ch)){//优先级选择case '<':Push(&OPTR,ch);ch=getchar();break;case '>':Pop(&OPTR,&theta);Pop(&OPND,&b);Pop(&OPND,&a);Push(&OPND,Operate(a,theta,b));break;case '=':Pop(&OPTR,&x);ch=getchar();break;}}}return GetTop(OPND);
}

表达式求值(数据结构栈,c语言版)相关推荐

  1. c语言作业算术表达式求值,算术表达式求值演示(C语言版)

    //头文件预处理命令 #include #include //----------函数结果状态代码----------------- #define TRUE 1 #define FALSE 0 #d ...

  2. c语言求不定式的最大值,C语言之四则运算表达式求值(链栈)—支持浮点型数据,负数, 整型数据运算...

    运算符间的优先级关系: 链栈结构体定义: 数据域使用字符串长度为20的字符数组(故需要注意判断读取的字符串是运算符还是数值) 可支持浮点型数据,负数, 整型数据的运算 float EvaluateEx ...

  3. c语言表达式的算法,表达式求值--数据结构C语言算法实现

    这篇博客介绍的表达式求值是用C语言实现的,只使用了c++里面的引用. 数据结构课本上的一个例题,但是看起来很简单,实现却遇到了很多问题. 这个题需要构建两个栈,一个用来存储运算符OPTR, 一个用来存 ...

  4. c语言程序设计报告表达式求值,数据结构 课程设计表达式求值 实验报告

    <数据结构 课程设计表达式求值 实验报告>由会员分享,可在线阅读,更多相关<数据结构 课程设计表达式求值 实验报告(21页珍藏版)>请在人人文库网上搜索. 1.实验课程名称 级 ...

  5. 【数据结构】栈的应用-算术表达式求值#数据结构实验任务书

    实验题目:栈的应用-算术表达式求值 正文 实验环境: Visual C++ 2010 实验目的: 1.掌握栈的定义及实现: 2.掌握利用栈求解算术表达式的方法. 实验内容: 通过修改完善教材中的算法3 ...

  6. linux算术表达式求值数据结构,数据结构:算数表达式求值演示

    题目:设计一个程序,演示用算符优先法对算数表达式求值的过程. 一.需求分析 以字符序列的形式从终端读入输入语法正确.不含变量的整数表达式.利用教科书表3.1给出的算符优先关系,实现对算数四则混合运算表 ...

  7. python 表达式求值数据结构_python 数据结构与算法

    python 数据结构与算法 1 python常见数据结构性能 1.1 List 1.1.1 安索引取值和赋值 1.1.2 列表append和__add__() 1.1.3 使用timeit模块测试执 ...

  8. (补)算法训练Day13 | LeetCode150. 逆波兰表达式求值(栈应用);LeetCode239. 滑动窗口最大值(单调队列);LeetCode347. 前K个高频元素(小顶堆,优先级队列)

    目录 LeetCode150. 逆波兰表达式求值 1. 思路 2. 代码实现 3. 复杂度分析 4. 思考 LeetCode239. 滑动窗口最大值 1. 思路 2. 代码实现 3. 复杂度分析 4. ...

  9. 【NYOJ-35】表达式求值——简单栈练习

    表达式求值 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min(2 ...

最新文章

  1. js数组去重的四种方法
  2. Java后端WebSocket的Tomcat实现(转载)
  3. spark的内存过小报错
  4. Lec 16 Projection matrices and least squares
  5. [Erlang危机](5.1.0)VM检测概述
  6. 前端开发常用又好用的几个软件
  7. programmer-common-word-pronunciation 程序员常用单词发音
  8. R 计算平均值标准误差
  9. 卸载windows激活码
  10. 计算机时钟周期的概念,指令周期、时钟周期、总线周期概念辨析
  11. 今天您大数据营销了吗?
  12. 谷歌浏览器chrome翻译插件完美解决开发者模式插件问题
  13. 深入 JavaScript 中的默认参数!
  14. HDU - 2121 Ice_cream’s world II(朱刘算法+虚根)
  15. java根据word模板导出_java根据模板生成,导出word和pdf(aspose.words实现word转换pdf)...
  16. 03.JavaScript-数据类型和数据类型转换
  17. 线性代数 --- 线性相关与线性无关(个人学习笔记)
  18. Linux df命令怎么使用
  19. 总文件夹下含有多个sdf,批量转换为SMILES并保存到csv中
  20. Exception in thread “main“ java.io.FileNotFoundException: test\mybatis-config.xml (系统找不到指定的路径。)

热门文章

  1. Java位运算符浅析
  2. Mac开发环境搭建之Watchman
  3. 秒传 php,文件上传之秒传文件
  4. 青年艺术家孙亮联名NFT数字藏品会员卡最新上线“数字藏品会员”微信小程序
  5. 什么是服务网格service-mesh?
  6. 时间序列——R语言基础
  7. @WebServlet注解无效访问servlet接口时报404
  8. 安卓应用开发 MyWeChat(一)
  9. 强化学习中好奇心机制
  10. JAVA计算机毕业设计校园摄影爱好者交流网站计算机(附源码、数据库)