算数表达式求值
算术表达式的求解
软件综合课程设计算术表达式的求解&车厢调度二〇一四年六月目录算数表达式的求解 (3)一、前言 (3)二、问题陈述 (3)三、需求分析 (3)四、概要设计 (4)五、详细设计和编码 (6)六、上级调试过程 (10)七、总结与心得 (12)八、参考文献 (13)附录(源程序): (13)车厢调度 (20)一、问题陈述 (20)二、问题分析与设计 (20)三、运行结果 (20)四、设计体会与总结 (21)附录(源程序) (21)算数表达式的求解一、前言表达式计算是实现程序设计语言的基本问题之一,也是栈的应用的一个典型例子。
设计一个程序,演示用算符优先法对算术表达式求值的过程。
在计算机中,算术表达式由常量、变量、运算符和括号组成。
由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。
因而在程序设计时,借助栈实现。
算法输入:一个算术表达式,由常量、变量、运算符和括号组成(以字符串形式输入)。
为简化,规定操作数只能为正整数,操作符为+、-*、/,用#表示结束。
算法输出:表达式运算结果。
算法要点:设置运算符栈和操作数栈辅助分析算符优先关系。
在读入表达式的字符序列的同时,完成运算符和运算数的识别处理,以及相应运算。
二、问题陈述(算数表达式的求解)给定一个算数表达式,通过程序求出最后的结果。
要求如下:1、从键盘输入要求解的算术表达式;2、采用栈结构进行算数表达式的求解过程;3、能够判断算数表达式的正确与否;4、对于错误表达式给出提示;5、对于正确表达时给出最后的结果。
三、需求分析有题目可知,程序要求给定一算数表达式并计算最后的结果,我们知道,在高级语言中,任何一个表达式都是有操作数、运算符和界限符组成。
在计算过程中,还要考虑表达式中有无括号以及左右括号之分。
由于运算符有优先级的高低,因此一个算数表达是不可能总是按顺序执行。
通过以上可知,可以用栈来实现运算符的优先级完成算术表达式的求解。
数据结构-算术表达式求值(含需求分析和源代码)
需求分析(附代码)一、需求分析(1)首先定义两个栈OPTR、OPND,栈OPTR用于存放运算符,栈OPND 用于存放操作数;定义一个一维数组expr【】存放表达式串。
(2)主函数主要包括两部分:(1)判断运算符优先权,返回优先权高的;(2)操作函数。
(3)开始将‘#’入操作符栈,通过一个函数来判别算术运算符的优先级。
且规定‘#’的优先级最低。
在输入表达式的最后输入‘#’,代表表达式输入结束。
在表达式输入过程中,遇操作数则直接入栈。
遇到运算符则与栈顶运算符比较优先级,当前运算符优先级高(前面的运算还不应执行)则当前运算符入栈,扫描下一符号;否则栈顶运算符出栈,两操作数出栈,进行运算,所得结果入数栈,重新比较当前运算符(注意当前运算符未变)与新栈顶运算符。
如此重复直到栈顶运算符与当前符号均为‘#’,运算结束。
(4)最初实现的加、减、乘、除及带小括号的基本运算,但考虑到实用性,后来的设计中有加上了乘方运算。
在乘方运算中借用了C库中自带的乘方函数pow。
二、概要设计1、设定栈的抽象数据类型定义:ADT Stack {数据对象:D={ ai | ai∈ElemSet, i=1,2,...,n,n≥0 }数据关系:R1={ <ai-1, ai >| ai-1, ai∈D, i=2,...,n }约定an端为栈顶,a1端为栈底。
基本操作:InitStack(&S)操作结果:构造一个空栈S。
DestroyStack(&S)初始条件:栈S已存在。
操作结果:栈S被销毁。
StackEmpty(S)初始条件:栈S已存在。
操作结果:若栈S为空栈,则返回TRUE,否则FALE。
StackLength(S)初始条件:栈S已存在。
操作结果:返回S的元素个数,即栈的长度。
GetTop(S, &e)初始条件:栈S已存在且非空。
操作结果:用e返回S的栈顶元素。
ClearStack(&S)初始条件:栈S已存在。
c语言算术表达式求值
c语言算术表达式求值C语言是一种广泛应用的编程语言,其强大的算术表达式求值功能使其在科学计算、数据处理、游戏开发等领域有着重要的应用。
本文将介绍C语言中算术表达式求值的相关知识,包括运算符、运算符优先级、表达式求值的顺序等内容。
我们需要了解C语言中常用的算术运算符。
C语言支持的算术运算符包括加法(+)、减法(-)、乘法(*)、除法(/)和求余(%)等。
这些运算符用于对数值进行基本的加减乘除运算。
在C语言中,运算符的优先级决定了表达式求值的顺序。
常见的运算符优先级从高到低依次为:1. 括号(()):括号中的表达式具有最高的优先级,可以改变默认的运算次序。
2. 一元运算符:包括正号(+)和负号(-),用于表示正负数。
3. 乘法、除法和求余:乘法(*)、除法(/)和求余(%)的优先级相同,从左到右依次计算。
4. 加法和减法:加法(+)和减法(-)的优先级相同,从左到右依次计算。
在使用C语言进行算术表达式求值时,我们需要遵循这些运算符的优先级规则,以保证表达式的正确求值。
如果表达式中包含多个运算符,我们需要根据优先级确定运算的顺序,可以使用括号来改变默认的运算次序。
下面我们将通过几个例子来说明C语言中算术表达式求值的过程。
例1:求解一个简单的算术表达式假设我们需要计算表达式 3 + 4 * 2,根据运算符优先级规则,先计算乘法,再计算加法。
具体的求解过程如下:1. 计算4 * 2,得到8。
2. 计算3 + 8,得到11。
所以,表达式3 + 4 * 2的值为11。
例2:使用括号改变运算次序假设我们需要计算表达式(3 + 4) * 2,根据运算符优先级规则,先计算括号内的加法,再计算乘法。
具体的求解过程如下:1. 计算3 + 4,得到7。
2. 计算7 * 2,得到14。
所以,表达式(3 + 4) * 2的值为14。
通过以上两个例子,我们可以看到,C语言中的算术表达式求值是按照运算符优先级和运算次序进行的,遵循从左到右的计算规则。
c语言算术表达式求值
c语言算术表达式求值【实用版】目录1.引言2.C 语言算术表达式的基本概念3.C 语言算术表达式的求值方法4.实际应用示例5.总结正文【引言】在 C 语言编程中,算术表达式是用来进行数值计算的重要工具。
本篇文章将为大家介绍 C 语言算术表达式的求值方法。
【C 语言算术表达式的基本概念】C 语言中的算术表达式主要包括以下几种:1.一元运算符:例如+、-、*、/等,用于对一个数值进行操作。
2.二元运算符:例如+、-、*、/等,用于对两个数值进行操作。
3.关系运算符:例如<、>、<=、>=、==、!=等,用于比较两个数值的大小或相等性。
4.逻辑运算符:例如&&、||、! 等,用于进行逻辑判断。
【C 语言算术表达式的求值方法】C 语言中,算术表达式的求值主要遵循以下规则:1.先进行括号内的运算,再进行括号外的运算。
2.先进行乘除法运算,再进行加减法运算。
3.关系运算符和逻辑运算符的优先级较低,从左到右依次进行运算。
【实际应用示例】下面我们通过一个实际的 C 语言程序,来演示算术表达式的求值过程。
```c#include <stdio.h>int main() {int a = 10, b = 5;int result;result = a + b * (a - b) / (a * b);printf("The result is: %d", result);return 0;}```在这个程序中,我们定义了两个整数变量 a 和 b,并通过算术表达式计算 result 的值。
根据我们之前提到的算术表达式求值规则,我们可以将这个表达式分解为以下几个步骤:1.计算括号内的值:a - b = 10 - 5 = 52.计算乘法运算:b * (a - b) = 5 * 5 = 253.计算除法运算:(a * b) / (a * b) = 14.计算加法运算:a + 25 = 10 + 25 = 355.输出结果:printf("The result is: %d", result); 输出 35【总结】通过本篇文章的介绍,相信大家已经对 C 语言算术表达式的求值方法有了更加深入的了解。
简单算术表达式求值
简单算术表达式求值01:简单算术表达式求值
总时间限制:
1000ms
内存限制:
65536kB
描述
两位正整数的简单算术运算(只考虑整数运算),算术运算为:
+,加法运算;
-,减法运算;
*,乘法运算;
/,整除运算;
%,取余运算。
算术表达式的格式为(运算符前后可能有空格):
运算数运算符运算数
请输出相应的结果。
输⼊
⼀⾏算术表达式。
输出
整型算数运算的结果(结果值不⼀定为2位数,可能多于2位或少于2位)。
样例输⼊
32+64
样例输出
96
#include<stdio.h>
int a(int x,char y,int z)
{
int sum,b;
b=y;
if(b==43)
{
sum=x+z;
}
else if(b==45)
{
sum=x-z;
}
else if(b==42)
{
sum=x*z;
}
else if(b==47)
{
sum=x/z;
}
else if(b==37)
{
sum=x%z;
}
return sum;
}
int main()
{
unsigned int A,C;
char B;
scanf("%u %c %u",&A,&B,&C);//注意字符两侧可能有空格printf("%d",a(A,B,C));
return 0;
}。
黑龙江大学数据结构考试题
《数据结构课程设计》讲义一、表达式求值问题1.1 问题定义及设计要求表达式求值是程序设计语言编译中的一个最基本问题。
人们在书写表达式时通常采用将运算符放在两个操作数中间的“中缀”表示形式,称为中缀表达式。
但是这种表达式形式对计算机处理来说是不太适合的。
在计算机领域,经常将算术表达式表示成“后缀”表示形式,称为后缀表达式。
如: 中缀表达式3+2*(7-5)对应的后缀表达式为3275-*+。
要求实现(1)算数四则运算中缀表达式到后缀表达式的转换;(2)后缀表达式的求值;(3)中缀表达式的求值。
要求以字符序列的形式从终端输入语法正确的、不含变量的整数表达式。
要求演示在求值过程中运算符栈、操作数栈、输入字符和主要操作过程及运算结果。
要求配备菜单,含如下选项:------------------------------------------------------1. 中缀表达式到后缀表达式的转换2. 后缀表达式的计算3. 中缀表达式的计算4. 退出-------------------------------------------------------1.2 中缀表达式到后缀表达式的转换(1)问题分析假设在算术表达式中只含四种基本运算符,操作数是10以内的整数。
假设一个中缀表达式中没有括号(如4+2*3,它的后缀表达式为423*+)。
在扫描到中缀表达式中的2后,能立即输出+,因为*具有较高优先级,必须必须先运算,因此需先保存+。
也就是说,新扫描运算符优先级必须与前一个运算符的优先级做比较,如果新的运算符优先级高,就要像前一个运算符那样保存它,直到扫描到第二个操作数,将它输出后才能将该运算符输出。
因此,在转化中必须保存两个运算符,后保存的运算符先输出。
用计算机来实现这个转化过程,就需要用到能后进先出的数据结构----栈。
如果在中缀表达式中含小括号,那么由于括号隔离了优先级规则,它在整个表达式的内部产生了完全独立的子表达式。
C#算术表达式求值(后缀法),看这一篇就够了
C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。
⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。
1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。
因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。
⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。
⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。
举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。
2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。
在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。
3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。
他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。
因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。
注意:逆波兰记法并不是简单的波兰表达式的反转。
因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。
利用栈来实现算术表达式求值的算法
利用栈来实现算术表达式求值的算法利用栈来实现算术表达式求值的算法算术表达式是指按照一定规则组成的运算式,包含数字、运算符和括号。
在计算机中,求解算术表达式是一项基本的数学运算任务。
根据算术表达式的性质,我们可以考虑利用栈这一数据结构来实现求值算法。
一、算法思路首先,我们需要明确一个重要概念——逆波兰表达式(ReversePolish notation)。
逆波兰表达式是一种没有括号的算术表达式,其运算规则是先计算后面的数字和运算符,再计算前面的数字和运算符。
例如,对于算术表达式“3+4*5-6”,其对应的逆波兰表达式为“3 45 * +6 -”。
那么,我们可以利用栈来实现将中缀表达式转化为逆波兰表达式的过程,具体步骤如下:1. 创建两个栈——操作数栈和操作符栈。
2. 从左到右扫描中缀表达式的每一个数字和运算符,遇到数字则压入操作数栈中,遇到运算符则进行如下操作:(1)如果操作符栈为空或当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符压入操作符栈中。
(2)如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符弹出并加入操作数栈中,重复此过程直到遇到优先级较低的运算符或操作符栈为空为止,然后将当前运算符压入操作符栈中。
3. 扫描完中缀表达式后,若操作符栈不为空,则将其中所有运算符弹出并加入操作数栈中。
4. 最终,操作数栈中存放的就是逆波兰表达式,我们可以按照逆波兰表达式的计算规则来计算其结果。
二、算法优点利用栈来实现算术表达式求值的算法具有以下优点:1. 代码简洁易懂,易于实现和维护。
2. 由于将中缀表达式转化为逆波兰表达式后,可以减少运算符的优先级关系而消除括号,从而减少求值的复杂度,提高程序的执行效率。
三、代码实现下面是利用栈来实现算术表达式求值的算法的Python代码实现:```pythonclass Stack:def __init__(self):self.items = []def push(self, item):self.items.append(item)def pop(self):return self.items.pop()def peek(self):return self.items[-1]def is_empty(self):return len(self.items) == 0def size(self):return len(self.items)def calculate(op_num1, op_num2, operator):if operator == "+":return op_num1 + op_num2elif operator == "-":return op_num1 - op_num2elif operator == "*":return op_num1 * op_num2elif operator == "/":return op_num1 / op_num2def infix_to_postfix(infix_expr):opstack = Stack()postfix_expr = []prec = {"+": 1, "-": 1, "*": 2, "/": 2, "(": 0} token_list = infix_expr.split()for token in token_list:if token.isdigit():postfix_expr.append(token)elif token == '(':opstack.push(token)elif token == ')':top_token = opstack.pop()while top_token != '(':postfix_expr.append(top_token)top_token = opstack.pop()else:while (not opstack.is_empty()) and(prec[opstack.peek()] >= prec[token]):postfix_expr.append(opstack.pop())opstack.push(token)while not opstack.is_empty():postfix_expr.append(opstack.pop())return " ".join(postfix_expr)def postfix_eval(postfix_expr):opstack = Stack()token_list = postfix_expr.split()for token in token_list:if token.isdigit():opstack.push(int(token))else:op_num2 = opstack.pop()op_num1 = opstack.pop()result = calculate(op_num1, op_num2, token) opstack.push(result)return opstack.pop()infix_expr = "3 + 4 * 5 - 6"postfix_expr = infix_to_postfix(infix_expr)print(postfix_expr)print(postfix_eval(postfix_expr))```四、总结算术表达式求值是一项常见的数学运算任务,利用栈这一数据结构来实现求值算法是一种简单有效的方法,它将中缀表达式转化为逆波兰表达式后,可以消除括号并减少运算符的优先级关系,从而提高程序的执行效率。
表达式求值(数据结构)
结束算法,此时在OPND栈的栈顶得到 运算结果。
① 若ch是操作数,进OPND栈,从中缀表达式 取下一字符送入ch; ② 若ch是操作符,比较栈外icp(ch)的优先级和 栈内isp(OPTR)的优先级: 若icp(ch) > isp(OPTR),则ch进OPTR栈, 从中缀表达式取下一字符送入ch; 若icp(ch) < isp(OPTR),则从OPND栈退出 a2 和 a1 , 从 OPTR 栈 退 出 θ, 形 成 运 算 指 令 (a1)θ(a2),结果进OPND栈; 若icp(ch) == isp(OPTR) 且ch == “)”,则从 OPTR栈退出栈顶的“(”,对消括号,然后从 中缀表达式取下一字符送入ch;
优先级 操作符
1
单目-、!
2
*、/、%
3
+、-
4 <、<=、>、>=
5
==、!=
6
&&
7
||
一般表达式的操作符有4种类型:
1 算术操作符 如双目操作符(+、-、 *、/ 和%)以及单目操作符(-);
2 关系操作符 包括<、<=、==、!=、 >=、>。这些操作符主要用于比较;
3 逻辑操作符 如与(&&)、或(||)、非 (!);
38
icp (栈外) 0 8 6 4
21
isp叫做栈内(in stack priority)优先数。
icp叫做栈外(in coming priority)优先数。
操作符优先数相等的情况只出现在括号 配对或栈底的“;”号与输入流最后的“;” 号配对时。
算术表达式求值问题课程设计报告
合肥学院算术表达式求值演示一、问题分析和任务定义实验题目:算术表达式求值:一个算术表达式是由操作数(operand),运算符(operator)和界限符(delimiter)组成的。
假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始,结束符“#”,如:#(7+15)*(23-28/4)#。
引入表达式起始、结束符是为了方便。
编程利用“算符优先法”求算术表达式的值。
要求:(1)从键盘读入一个合法的算术表达式,输出正确的结果。
(2)显示输入序列和栈的变化过程。
选作内容:操作数类型扩充到实数。
问题分析:在带括号的的算术表达式中,界限符包括左右括号以及表达式起始、结束符“#”。
假设运算符只有加、减、乘、除4种,则对一个简单的算术表达式的运算规则如下:(1)从左至右运算表达式。
(2)先乘、除,后加、减。
(3)先括号内,后括号外。
要想能够实现这个问题,首先,你要从键盘中输入一个字符并判别该字符是运算符还是运算数。
如果是运算数就直接进运算数栈。
如果是运算符,则与运算符栈的栈顶元素进行优先级的比较(可以单独写一个优先级比较函数,将每个运算符与其他运算符之间的优先级一一比较出来,可以设置为“>”、“<”、“=”),如果比较后为“>”,则将运算数栈依次出栈两次,将该运算符和刚出栈的两个运算数进行计算(单独写一个函数,将“+”、“-”、“*”、“/”四种情况一一写出来),然后将计算的结果入运算数栈,将读入的运算符入运算符栈;如果比较后为“<”,则将该运算符入运算符栈;如果是“=”,同“>”,但要注意如果从运算符栈出栈的元素为“#”和“(”,则运算数栈无需出栈,并且运算符栈也无需入栈。
按照上面的步骤,一一读完所有的字符。
这样,运算数栈中最后剩下的元素就是该算术表达式的最终结果。
注意:整个算法结束的条件是运算符栈为空。
(即表达式的起始、结束符相遇) 任务定义:为统一算法的描述,将运算符和界限符统称为算符。
shell脚本四种数值计算方式
shell脚本四种数值计算方式在shell脚本中,可以使用四种不同的计算方式来进行数值计算:表达式求值、命令替换、算术运算和高级数学函数。
1.表达式求值:表达式求值是最简单的一种计算方式,只需要将数学表达式放在$(())中。
例如:```result=$(( 5 + 3 ))echo $result```在这个例子中,表达式求值计算了5 + 3,并将结果赋给变量result。
然后,使用echo命令打印出了结果。
2.命令替换:命令替换是一种在数学计算中使用shell命令的方式。
通过将命令放在$(中,shell会先执行该命令,然后将命令的输出结果作为数值计算的一部分。
例如:```result=$(expr 5 + 3)echo $result```在这个例子中,命令替换使用了expr命令来计算5 + 3的结果,并将结果赋给变量result。
然后,使用echo命令打印出了结果。
3.算术运算:除了使用$(( ))和$(进行计算,shell还提供了一些算术运算符来进行数值计算。
例如:```result=`expr 5 + 3`echo $result```在这个例子中,使用了expr命令和反引号(``)来执行数学计算。
结果与前两种方式相同。
4.高级数学函数:在shell脚本中,可以使用数学函数来执行更复杂的数值计算。
有一些内置的数学函数,如sqrt、sin、cos等,可以通过shell的数学库调用。
例如:```result=$(echo "sqrt(4)" , bc -l)echo $result```在这个例子中,先使用echo命令将数学表达式"sqrt(4)"输出给bc 命令,bc命令会执行计算并将结果输出。
然后,命令替换将结果赋给变量result,并使用echo命令打印出了结果。
总结:以上是四种常用的shell脚本中进行数值计算的方式。
表达式求值、命令替换和算术运算是最常见的方式,适合于简单的数学计算。
简单算术表达式的二叉树的构建和求值
一、概述二、算术表达式的二叉树表示1. 什么是二叉树2. 算术表达式的二叉树表示方法三、算术表达式二叉树的构建1. 中缀表达式转换为后缀表达式2. 后缀表达式构建二叉树四、算术表达式二叉树的求值五、应用举例六、总结一、概述在数学和计算机科学中,处理算术表达式是一个常见的问题。
在计算机中,算术表达式通常以中缀、前缀或后缀的形式出现,其中中缀表达式最为常见。
而采用二叉树来表示和求解算术表达式,是一种常见且高效的方法。
二、算术表达式的二叉树表示1. 什么是二叉树二叉树是一种树形数据结构,它的每个节点最多只能有两个子节点,分别是左子节点和右子节点。
二叉树可以为空,也可以是非空的。
2. 算术表达式的二叉树表示方法在二叉树中,每个节点要么是操作符,要么是操作数。
操作符节点的左子节点和右子节点分别表示运算符的两个操作数,而操作数节点则不包含任何子节点。
通过这种方式,可以将算术表达式表示为一个二叉树结构。
三、算术表达式二叉树的构建1. 中缀表达式转换为后缀表达式为了构建算术表达式的二叉树,首先需要将中缀表达式转换为后缀表达式。
中缀表达式是人们常见的形式,例如"2 + 3 * 5",而后缀表达式则更适合计算机处理,例如"2 3 5 * +"。
将中缀转后缀的算法即为中缀表达式的后缀转换法则。
2. 后缀表达式构建二叉树构建二叉树的过程通常采用栈来辅助完成。
从左到右扫描后缀表达式,对于每个元素,如果是操作数,则入栈;如果是操作符,则弹出栈顶两个元素作为其左右子节点,然后将操作符节点入栈。
最终栈中只剩一个节点,即为构建的二叉树的根节点。
四、算术表达式二叉树的求值算术表达式二叉树的求值是递归进行的。
对于二叉树的每个节点,如果是操作符节点,则递归求解其左右子节点的值,并进行相应的操作;如果是操作数节点,则直接返回其值。
最终得到根节点的值,即为整个算术表达式的值。
五、应用举例以中缀表达式"2 + 3 * 5"为例,首先将其转换为后缀表达式"2 3 5 * +",然后根据后缀表达式构建二叉树,最终求得二叉树的根节点即为算术表达式的值。
表达式求值(数据结构)(2023版)
表达式求值(数据结构) 表达式求值(数据结构)1.引言1.1 目的1.2 背景1.3 范围2.表达式类型2.1 算术表达式2.1.1 运算符2.1.2 运算数2.2 逻辑表达式2.2.1 逻辑运算符2.2.2 逻辑运算数2.3 字符串表达式2.3.1 字符串连接运算符2.3.2 字符串操作函数3.表达式求值算法3.1 递归下降分析法3.2 栈表达式求值法3.2.1 中缀表达式转后缀表达式3.2.2 后缀表达式求值4.数据结构4.1 操作数栈4.2 运算符栈4.3 后缀表达式栈5.算法实现步骤5.1 输入表达式5.2 初始化栈5.3 处理表达式字符串5.4 根据算法选择相应的方法求值5.5 输出结果6.实例演示6.1 算术表达式求值示例6.2 逻辑表达式求值示例6.3 字符串表达式求值示例7.测试与验证7.1 正常表达式测试7.2 异常表达式测试7.3 性能测试8.总结与展望8.1 本文主要工作8.2 结果评估8.3 存在问题8.4 后续工作附件:附件1、算术表达式求值示例代码附件2、逻辑表达式求值示例代码附件3、字符串表达式求值示例代码法律名词及注释:1.递归下降分析法: 一种基于上下文无关文法进行递归分析的方法,用于处理表达式求值等问题。
2.栈表达式求值法: 使用栈数据结构进行表达式求值的方法。
3.中缀表达式: 常见的数学表达式写法,运算符位于运算数之间。
4.后缀表达式: 也称为逆波兰表达式,运算符位于运算数之后。
5.操作数栈: 用于存储表达式中的操作数的栈。
6.运算符栈: 用于存储表达式中的运算符的栈。
7.后缀表达式栈: 用于存储后缀表达式的栈。
C语言表达式求值
C语言表达式求值
c语言有丰富的表达式,这是它的特点之一,表达式主要有4类,算术表达式,赋值表达式,逗号表达式,关系表达式1.算术表达式就是包含算术运算符(如+-/*%等)的表达式(不是语句,后面没有分号),如:a+b,a%b,a+b-c*d,3+5等,算术表达式的值就是最后算出的结果,如3+5这个表达式的值就是82.赋值表达式,就是含有赋值运算符=的表达式,如a=5,b=3,c='A'等,=左边的a,b,c称为左值,必须为变量,=右边的5,3,'A'称为右值,必须为常量,赋值表达式的值为右值,如a=3的值为3,c='A'的值为字母A的ascii码65(当然也可以认为它的值就是字母A)3.逗号表达式就是含有逗号的表达式,形式:表达式1,表达式2,表达式3.......如a,b,c3,5,7a=3,b=4,c=63,a=5,b=6等逗号表达式的值为,最右边的表达式的值,如3,4,5的值就是5,表达式
a=3,b=4,c=6的值就是表达式b=6的值,
由上述分析知,表达式b=6的值就是6,所以表达式
a=3,b=4,c=6的值就是64.关系表达式,指含有关系运算符
(如><>====<等)的表达式(其实也是算术表达式的一种)如
a>b,a>6,6>5,3<2,4==6等,如果表达式的关系是正确的,那么表达式的值为1,否则为0如6>5正确,表达式的值为1,3<2,和4==6错误,表达式的值为0当然可以细分为很多种表达式,不过主要也就是这几种的变型。
数据结构课程设计之算术表达式求值
1【实验题目及要求】[问题描述]一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。
假设操作数是正实数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,如:#(7+15)*(23-28/4)#。
引入表达式起始、结束符是为了方便。
编程利用“算符优先法”求算术表达式的值。
[基本要求](1)从键盘或文件读入一个合法的算术表达式,输出正确的结果。
(2)显示输入序列和栈的变化过程。
(3)考虑算法的健壮性,当表达式错误时,要给出错误原因的提示。
(4) 实现非整数的处理(可选功能)。
2【源代码(C语言)】#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAXSIZE 20#define OK 1#define ERROR 0#define OVERLOW 0#define YES 1#define NO 0typedefstruct{char * base;char * top;int stacksize; //最大存储量}OPTR; //字符存储栈typedefstruct{float *base;float *top;int stacksize; //最大存储量}OPND; //数值存储栈int InitOptrStack(OPTR *); //字符栈初始化函数int OptrPush(OPTR *, char); //进字符栈操作int OptrPop(OPTR*, char *); //出字符栈操作int OptrEmpty(OPTR ); //判断字符栈是否为空char GetOptrTop(OPTR); //返回字符栈顶元素int InitOpndStack(OPND *); //数值栈初始化函数int OpndPush(OPND *, float); //进数值栈操作int OpndPop(OPND*, float*); //出数值栈操作int OpndEmpty(OPND ); //判断数值栈是否为空int JudgeChar(char); //判断是否为字符float GetFloat(char *); //接收一个数字char Precede(char, char); //判断优先级操作float Caculate(float,float,char);//计算数值{char ch, noMean, ci;float num, number1, number2;OPTR optr;OPND opnd;//system("color 30");InitOptrStack(&optr);InitOpndStack(&opnd);while(1){printf(" 请输入表达式以“#”开始,以“#”结束\n ");do{ch = getchar();}while(ch !='#'); //忽略前面非‘#’字符OptrPush(&optr, ch);ch = getchar();while(ch != '#' || GetOptrTop(optr) != '#'){if(!JudgeChar(ch)){ //如果输入的是数字num = GetFloat( &ch );OpndPush(&opnd, num);else{ //输入的是字符switch(Precede(GetOptrTop(optr),ch)){case'<':OptrPush(&optr,ch); //栈顶优先级低ch = getchar();break;case'=':OptrPop(&optr,&noMean); //左右括号,把左括号出栈ch = getchar ();break;case'>': //栈顶优先级高if(OpndPop(&opnd, &number2) && OpndPop(&opnd,&number1)){OptrPop(&optr, &ci);num = Caculate(number1, number2, ci ); //出栈计算OpndPush(&opnd, num);}else{printf(" 输入过多运算符!\n");system ("PAUSE");exit(0);}break;}//witch}//else}if(opnd.top -opnd.base >= 2){printf(" 俩个括号之间缺少运算符!\n ");system ("PAUSE");exit( 0 );}OpndPop(&opnd,&num); //直接把OPND的栈元素赋值给numprintf(" 运算结果为%.3f\n", num);}system ("PAUSE");}int InitOptrStack(OPTR * OP){OP->base = (char*)malloc((MAXSIZE+1)*sizeof(char));OP->top = OP->base;OP->stacksize = MAXSIZE;return OK;}int OptrPush(OPTR *OP, char ch){*(OP->top) = ch;OP->top++;return OK;}int OptrPop(OPTR *OP, char *ch){if(OP->base == OP->top)return ERROR;else{OP->top--;*ch = *(OP->top);return OK;}}int OptrEmpty(OPTR OP){if(OP.top == OP.base )return YES;elsereturn NO;}char GetOptrTop(OPTR OP){return *(OP.top -1);}int InitOpndStack(OPND * OP){if(!(OP->base = (float*)malloc((MAXSIZE+1)*sizeof(float)))) exit(OVERLOW);OP->top = OP->base;OP->stacksize = MAXSIZE;return OK;}int OpndPush(OPND *OP, float number) {*(OP->top) = number;OP->top++;return OK;}int OpndPop(OPND *OP, float* number) {if(OP->top == OP->base)return ERROR;else{OP->top--;*number = *(OP->top);return OK;}}int OpndEmpty(OPND OP){if(OP.top == OP.base )return YES;elsereturn NO;}int JudgeChar(char ch){if(ch>='0'&&ch<= '9')return NO;elsereturn YES;}float GetFloat(char* ch){int i;float num = 0;for( i = 0; *ch>= '0'&& *ch<= '9'; i++){ num = num*10 + *ch - '0';*ch = getchar();}return num;}char Precede(char a, char b){char ch;switch(a){case'+':case'-': if(b == '*' || b == '/' || b == '(')ch = '<';elsech = '>';break;case'*':case'/': if( b == '(')ch = '<';elsech = '>';break;case'(': if(b == ')')ch = '=';elseif(b == '#'){printf(" 缺少反括号\n");system ("PAUSE");exit(0);}elsech = '<';break;case')': if(b == '('){printf(" 两个括号之间没有符号相连!\n");system("PAUSE");exit(0);}ch = '>';break;case'#': if(b == '#')ch = '=';elseif(b == ')'){printf(" 没有左括号!\n ");system("PAUSE");exit(0);}elsech = '<';break;default: printf(" 输入运算符超出范围! \n ");system ("PAUSE");exit(0);break;}return ch;}float Caculate(float number1, float number2, char ci){float num;switch( ci){case'+': num = number1 + number2; break;case'-': num = number1 - number2; break;case'*': num = number1 * number2; break;case'/': num = number1 / number2; break;}return num;}3【算法思想】根据栈的原理,建立数字栈OPND和运算符号栈OPTR,对读入的字符进行判断,存入不同的栈内,每次读入一个字符就把该字符和运算符栈顶的优先级进行比较,然后选择相应的操作,这是这个程序的核心代码,如下:switch(Precede(GetOptrTop(optr),ch)){case '<':OptrPush(&optr,ch); //栈顶优先级低ch = getchar();break;case '=':OptrPop(&optr,&noMean); //左右括号,把左括号出栈ch = getchar ();break;case '>': //栈顶优先级高if(OpndPop(&opnd, &number2) && OpndPop(&opnd, &number1)){OptrPop(&optr, &ci);num = Caculate(number1, number2, ci ); //出栈计算OpndPush(&opnd, num);}else{printf(" 输入过多运算符!\n");system ("PAUSE");exit(0);}break;}//witch4【实现效果】完全可以实现题目的要求,除了下图的错误提示,本程序还可以提示的错误有:输入过多运算符,缺少反括号,两个括号之间缺少运算符相连,缺少左括号,输入的运算符超出范围等提示。
表达式求值算法
表达式求值算法表达式求值是一种将数学表达式转换为计算结果的算法。
在计算机程序中,表达式是由操作符和操作数组成的,操作符是执行特定计算操作的符号,操作数是参与计算的数值。
在表达式求值算法中,我们需要处理不同类型的表达式,例如算术表达式、逻辑表达式和位运算表达式等。
算术表达式包含加法、减法、乘法、除法等操作符,逻辑表达式包含与、或、非等操作符,位运算表达式包含位与、位或、位取反等操作符。
实现一个通用的表达式求值算法需要将所有这些操作符纳入考虑,并按照特定的规则进行计算。
在表达式求值算法中,首先需要对表达式进行解析,将其拆分为操作符和操作数。
通过使用逆波兰表达式或分析树等数据结构,我们可以更方便地对表达式进行计算。
逆波兰表达式是一种将操作符放在操作数后面的表达式表示方法。
例如,中缀表达式"3 + 4 * 2"可以转换为逆波兰表达式"3 4 2 * +"。
逆波兰表达式的好处是可以通过一个栈来进行计算。
遍历逆波兰表达式的每个元素,当遇到操作数时,将其压入栈中;当遇到操作符时,从栈中弹出相应数量的操作数进行计算,并将结果压入栈中。
最后,栈中剩下的唯一一个元素就是表达式的结果。
另一种求值算法是使用分析树。
分析树是一种用树结构表示表达式的方法,树的每个节点都是一个操作符,而叶子节点是操作数。
通过遍历分析树,从叶子节点开始计算,并将结果返回给父节点,直到整个树的根节点成为最终结果。
这种方法可以递归地处理任意复杂的表达式。
除了使用逆波兰表达式和分析树,我们还可以使用其他方法来实现表达式求值算法。
例如,我们可以使用栈来存储操作数,并在遍历表达式时进行计算。
当遇到操作符时,从栈中弹出相应数量的操作数进行计算,并将结果压入栈中。
在表达式求值算法中,需要注意处理运算符的优先级和结合性。
不同的运算符可能有不同的优先级,例如乘法和除法的优先级高于加法和减法。
结合性指的是同一级别的运算符如何进行计算,例如加法和减法是左结合的,而赋值运算符是右结合的。
算术运算符与算术表达式
9. 求字节数运算符 size of 10. 强制类型转换运算符 (类型) 11. 分量运算符 •, , 12. 下标运算符 [ ] 13. 其它运算符 如函数的调用( )
若i=3, 若参数计算从左至右, 则输出 3, 3 若从右至左, 则输出4, 3
上述问题看似复杂,最好上机实践.
§3.8 赋值运算符和 赋值表达式
符号" = "为赋值运算符。
赋值时,两边类型若不一致,则按以下规则转换:
1. 将实型数据(无论单,双精度)赋给整型变量时,舍 弃小数.
2. 整型数据赋给实型变量,数值不变,但按实数形 式存放.
例: x=(y=10) 相当于 y=10;x=y 由于赋值号为右结合性,于是" ( ) "可省略, 即为:x=y=10;
又: a=5+(c=6) c=6, a=11 a=(b=4)+(c=6) b=4, c=6, a=10 a=(b=10)/ (c=2)b=10,c=2, a=5
进一步,还可用复合赋值运算符作下列运算:
实际运行结果:i=6,j=9
但Turbo C. MSC 都是先取三个原值
相加: i+i+i=9 i6 如果表达式j=(i++)+(i++)+(i++);改为:
j=(++i)+(++i)+(++i);
则运行结果: i=6,j=18
编程中表达式的求值规则与示例
编程中表达式的求值规则与示例在计算机编程中,表达式是由操作数和操作符组成的数学或逻辑式子,用于执行各种计算和操作。
表达式的求值是指根据特定的规则和优先级计算表达式的结果。
本文将介绍一些常见的表达式求值规则,并提供一些示例来帮助读者更好地理解这些概念。
1. 算术表达式的求值规则算术表达式是最常见的表达式类型之一,用于执行数学运算。
在算术表达式中,我们通常使用加法、减法、乘法和除法等基本算术运算符。
求值规则:- 先计算括号内的表达式。
- 乘法和除法的优先级高于加法和减法。
按照从左到右的顺序计算乘法和除法。
- 加法和减法的优先级相同,按照从左到右的顺序计算。
示例:1. 2 + 3 * 4 - 1首先计算乘法:3 * 4 = 12然后计算加法和减法:2 + 12 - 1 = 132. (2 + 3) * 4 / 2首先计算括号内的表达式:2 + 3 = 5然后计算乘法和除法:5 * 4 / 2 = 102. 逻辑表达式的求值规则逻辑表达式用于执行逻辑运算,例如判断条件是否为真或假。
在逻辑表达式中,我们通常使用与、或和非等逻辑运算符。
求值规则:- 先计算括号内的表达式。
- 非运算符的优先级最高,其次是与运算符,最后是或运算符。
- 与运算符在计算时,只有当两个操作数都为真时,结果才为真。
- 或运算符在计算时,只有当两个操作数都为假时,结果才为假。
示例:1. (2 > 1) && (3 < 5)首先计算括号内的表达式:2 > 1 和 3 < 5 都为真然后计算与运算符:真 && 真 = 真2. (2 > 1) || (3 > 5)首先计算括号内的表达式:2 > 1 为真,但 3 > 5 为假然后计算或运算符:真 || 假 = 真3. 字符串连接表达式的求值规则字符串连接表达式用于将多个字符串拼接在一起。
在字符串连接表达式中,我们使用加号 (+) 运算符来实现字符串的连接。
算术表达式求值算法解析
迭代算法在处理复杂表达式时效率较高,因为避免了重复计算,但在处理简单表达式时,由于需要遍历整个表达 式,效率较低。
算法适用范围比较
递归算法
递归算法适用于处理简单的算术表达式 ,如加减乘除等。
VS
迭代算法
迭代算法适用于处理复杂的算术表达式, 如包含括号、指数、对数等运算的表达式 。
算法优缺点比较
预测分析法的优点是处理效率较高,适用于大规模的算术 表达式处理,但缺点是需要使用大量的栈空间,且对于复 杂的算术表达式处理能力有限。
逆波兰表示法
逆波兰表示法是一种不需要括号来表示运算符优先级的方法,通 过将操作数放在前面,运算符放在后面来表示算术表达式。
逆波兰表示法将算术表达式转换为逆波兰表示形式后,可以直接 从左到右依次读取并计算表达式的值。
高程序的执行效率。例如,通过消除冗余计算、简化表达式等手段来优
化代码。
在数学计算器中的应用
表达式求值
数学计算器需要能够对用户输入的算术表达式进行求值,以便得到计算结果。算术表达式求值算法可以用于实现这一 功能,快速准确地计算表达式的值。
符号计算
数学计算器可能需要支持符号计算,即对包含未知数的算术表达式进行求解。算术表达式求值算法可以用于实现符号 计算,通过迭代和近似方法求解表达式的根或极值等。
多精度计算
在一些情况下,数学计算器需要支持多精度计算,以避免浮点数精度问题。算术表达式求值算法可以用 于实现多精度计算,提供更高的计算精度和可靠性。
在人工智能领域的应用
机器学习
数据推理
在机器学习领域,算术表达式求值算 法可以用于实现特征工程和模型训练 过程中的数值计算。例如,在神经网 络训练中,需要对权重、偏差等参数 进行迭代更新,算术表达式求值算法 可以高效地完成这些计算任务。
C语言_算术表达式求值_代码
C语言_算术表达式求值_代码源代码://用来存储字符的结点类型typedef struct CharNode{char c;struct CharNode *next;}CharNode;//用来存储数的结点类型typedef struct IntNode{long double i;struct IntNode *next;}IntNode;//用来存储数的结点类型typedef struct Node{long double n;struct Node_ys_char *next;}Node;//用来存储运算符的结点类型typedef struct Node_ys_char{char c;struct Node_ys_char *next_c;struct Node *next;}Node_ys_char;char Precede(char x,char y)//运算符优先级判断{ int i,j;int from[5][5]={{0,0,-1,-1,0},{0,0,-1,-1,0},{1,1,0,0,1},{1,1,0,0,1},{0,0,-1,-1,0}};//定义一个二维数组存放算术符号的优先级switch(x){case '+':i=0;break;case '-':i=1;break;case '*':i=2;break;case '/':i=3;break;case '#':i=4;break;}switch(y){case '+':j=0;break;case '-':j=1;break;case '*':j=2;break;case '/':j=3;break;case '#':j=4;break;}if(from[i][j]==1)//说明运算符i的优先级比j的优先级高return '>';if(from[i][j]==-1)return '<';elsereturn '=';}//输入表达式,并对特殊情况做处理CharNode *CreatRegister(){CharNode *top,*p,*q,*e;top=(CharNode *)malloc(sizeof(CharNode)); p=q=top;scanf("%c",&p->c);scanf("%c",&p->c);if(q->c=='-'){p=(CharNode *)malloc(sizeof(CharNode)); p->c='0';p->next=q;top=p;p=q;}if(q->c=='('){e=(CharNode *)malloc(sizeof(CharNode)); e->c='0';p=(CharNode *)malloc(sizeof(CharNode)); p->c='+';e->next=p;p->next=q;p=q;top=e;}while(p->c!='#'){q=(CharNode *)malloc(sizeof(CharNode)); scanf("%c",&q->c);if((p->c=='(')&&(q->c=='-')){e=(CharNode *)malloc(sizeof(CharNode));e->c='0';e->next=q;p->next=e;p=q;}else{p->next=q;p=q;}}p->c='+';p->next=(CharNode *)malloc(sizeof(CharNode)); p->next->c='0';p=p->next;p->next=(CharNode *)malloc(sizeof(CharNode)); p->next->c='#';return top;}//将数与运算符分开,并将其他进制转化为10进制Node *StackChange(CharNode *top,int m){CharNode *p,*q;long double x=0,y=0;char a[10],b[10];int n=0,i=0,JiWei,max,min=47,mark_1=0,mark_2=0,h,k=0; Node *node,*head;Node_ys_char *node_char;switch(m){case 2:JiWei=2;max=50;break;case 8:JiWei=8;max=56;break;case 10:JiWei=10;max=97;break;case 16:JiWei=16;max=103;break;}p=q=top;while(p->c !='#'){while((q->c>min)&&(q->cc==46)) {if(q->c==46){mark_1=1;q=q->next;}if(mark_1==0){a[n]=q->c;q=q->next;n++;}if(mark_1==1){b[i]=q->c;q=q->next;i++;}}for(h=n-1;h>=0;h--){x=(a[n-h-1]-48)*pow(JiWei,h)+x;// }for(h=0;h<i;h++)< p="">{y=y+(b[h]-48)*pow(JiWei,(-(h+1)));//}node=(Node *)malloc(sizeof(Node));//node->n=x+y;mark_1=0;n=0;i=0;if(mark_2==1)node_char->next=node;node_char=(Node_ys_char *)malloc(sizeof(Node_ys_char)); node_char->c=q->c;node->next=node_char;node_char->next_c=NULL;node_char->next=NULL;if(q->c=='#'){node->next=(Node_ys_char *)malloc(sizeof(Node_ys_char));node->next->c='#';return head;}q=q->next;if(q->c<=min)while(q->c<=min){node_char->next_c=(Node_ys_char*)malloc(sizeof(Node_ys_char));node_char->next_c->c=q->c;q=q->next ;//node->next=node_char;node_char=node_char->next_c;node_char->next_c=NULL;node_char->next=NULL;}else{node->next=node_char;node_char->next_c=NULL;node_char->next=NULL;}p=q;n=0;x=0;y=0;if(mark_2==0){head=node;mark_2=1;}}return head;}//作只有加减乘除运算的表达式求值Node *Compute(Node *p){int mark=0;Node *m,*n;char max_char,min_char;m=n=p;while(p->next->c!='#'){max_char=n->next->c;n=n->next->next;min_char=n->next->c;if((Precede(max_char,min_char)=='<'||Precede(max_char,min _char)=='=')&&mark!=1) {m=n;}if(Precede(max_char,min_char)=='>'||mark==1){switch(m->next->c){case '+':m->n =m->n + n->n ;break;case '-':m->n =m->n - n->n ;break;case '*':m->n =m->n * n->n ;break;case '/':m->n =m->n / n->n ;break;}m->next=n->next;n=m;}if(m->next->c=='#'){m=n=p;mark=1;}}return m;}//求用户输入表达式的值Node *GetOutcome(Node *head){Node *p,*q,*R;Node_ys_char *m,*n,*t,*k;n=(Node_ys_char *)malloc(sizeof(Node_ys_char)); n->c='(';p=q=head;while((n->c!=')')&&(q->next->c!='#')){if(q->next->c=='('){m=q->next;k=m;}else if(q->next->next_c==NULL) q=q->next->next;else{m=q->next->next_c;k=q->next;// t=q->next;if(m->c=='('){t=k;k=m;}while(m->next_c!=NULL){m=m->next_c;if(m->c=='('){t=k;k=m;}}q=m->next ;}if(q->next->c==')'){n=q->next;}}if(n->c==')'){p=k->next;q->next->c='#';R=Compute(p);t->next =R;t->next_c=NULL;R->next=n->next_c;GetOutcome(head);}else{R=Compute(head);return R;}}main(){int m;//进制char a;CharNode *top_1;Node *top_2,*R;printf("\n\n");printf("███████████████████████████████████████\n");printf("████\n");printf("██表达式求值系统██\n");printf("████\n");printf("███████████████████████████████████████\n");printf("本程序可分别进行2进制,8进制,10进制,16进制的加减乘除运算:\n");loop:printf("...............请输入进制..............\n");printf("你选的进制为:");scanf("%d",&m);printf("请输入表达式,表达式请以#结尾:\n");top_1=CreatRegister();//录入表达式,并对特殊情况作处理,将头指针带回;top_2=StackChange(top_1,m);//进制转换,将数与运算符分开,将头指针带回;R=GetOutcome(top_2);得出结果printf("运算结果的十进制形式为:\n");printf("%lf",R->n);printf("\n继续进行运算请输入y否则退出:\n");scanf("%c",&a);scanf("%c",&a);if(a=='y'||a=='Y')goto loop;}</i;h++)<>。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
试验一:算术表达式求值班级:计算机科学与技术一班姓名:马贺学号:1125116020 完成日期:2012.12.011.实验要求:(1)实验目的:使学生深入了解栈和队列的特性,以便在实际问题背景下灵活运用它们,同时还将巩固对这两种结构的构造方法的掌握及基本操作的实现。
(2)实验内容:1.问题描述:表达式计算是实现程序设计语言的基本问题之一,也是栈的应用的一个典型的例子。
设计一个程序,演示用算符优先法对算术表达式求值的过程。
2.基本要求:以字符序列的形式从终端输入语法正确的、不含变量的整数表达式。
利用教科书表3.1给出的算符优先关系,实现对算术四则混合运算表达式的求值,并仿照教科书的例3-1演示在求值中运算符栈、运算数栈、输入字符和主要操作的变化过程。
3.测试数据:教科书例3-1的算术表达式3*(7-2),以及下列表达式8;1+2+3+4 ;88-1*5 ;1024/4*8 ;(20+2)*(6/2) ;3-3-3 ;8/(9-9) ;2*(6+2*(3+6*(6+6)));(((6+6)*6+3)*2+6)*2;4.实现提示:(1)、采用优先级法,设置运算符栈和运算数栈,先将表达式转换成后缀表示,然后求值。
(2)、在读入表达式的字符序列的同时,完成运算符和运算数(整数)的识别处理,以及相应的运算。
(3)、在识别出运算数的同时,要将其字符序列形式转换成整数形式。
(4)、在程序的适当位置输出运算符栈、运算数栈、输入字符和主要操作的内容。
2.程序分析(1)存储结构:栈存储结构(2) 算法分析:程序中包括两个抽象数据类型:1.ADT SqStack-f{数据对象:D={a i| a i∈R,i属于N+}数据关系:R1={< a i , a i -1>| a i-1, a i∈D,i=2,3…….n}基本操作:InitStack-c(&S)GetTop-c(&S,&c)Push-c(&S,ch)Pop-c(&S,&c)}ADT SqStack-c.2.结点类型,指针类型typedef stract{float *base;float *top;int stactsize;}Sq-Stack-f;typedef stract{char *base;char *top;int stactsize;}Sq-Stack-f;void InitStack-f(Sq-Stack-f*s)void InitStack-c(Sq-Stack-f*s)void GetTop-f(Sq-Stack-f*s,float *e)void GetTop-c(Sq-Stack-f*s,float *e)void Push-f(Sq-Stack-f*s,float *e)void Push-c(Sq-Stack-f*s,float *e)void Pop-f(Sq-Stack-f*s,float *e)void Pop-c(Sq-Stack-f*s,float *e) }ADT SqStack-c.3.判断算符优先级的算法:4.表达式求值运算的算法:(1)读入无括号的后缀表达式(2)若为数值和小数点则将其联合转化为浮点型后进栈(3)若为运算符,让栈顶元素和次顶元素与次运算符进行相应的运算运算结果打印并进栈(4)重复2.3步骤,直到出现运算符“#”,此时栈中的结果就是表达式的值5.代码:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#define TTACK_INIT_SIZE 100#define STACKINCREMENT 10typedef struct{float *base;float *top;int stacksize;}SqStack_f;typedef struct{char *base;char *top;int stacksize;}SqStack_c;void InitStack_f(SqStack_f *s){s->base=(float*)malloc(TTACK_INIT_SIZE*sizeof(float));if(!s->base)exit(1);s->top=s->base;s->stacksize=TTACK_INIT_SIZE;}void InitStack_c(SqStack_c *s){s->base=(char*)malloc(TTACK_INIT_SIZE*sizeof(char));if(!s->base)exit(1);s->top=s->base;s->stacksize=TTACK_INIT_SIZE;}void GetT op_f(SqStack_f *s,float *e){if(s->top==s->base){printf("ERROR!\n");exit(1);}*e=*(s->top-1);}void GetT op_c(SqStack_c *s,char *e){if(s->top==s->base){printf("ERROR!\n");exit(1);}*e=*(s->top-1);}void Push_f(SqStack_f *s,float e){if(s->top-s->base>=s->stacksize){s->base=(float*)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeo f(float));if(!s->base){printf("OVERFLOW!\n");exit(1);}s->top=s->base+s->stacksize;s->stacksize+=ST ACKINCREMENT;}*s->top++=e;}void Push_c(SqStack_c *s,char e){if(s->top-s->base>=s->stacksize){s->base=(char*)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeo f(char));if(!s->base){printf("OVERFLOW!\n");exit(1);}s->top=s->base+s->stacksize;s->stacksize+=ST ACKINCREMENT;}*s->top++=e;}void Pop_f(SqStack_f *s,float *e){if(s->top==s->base)exit(1);*e=*--s->top;}void Pop_c(SqStack_c *s,char *e){if(s->top==s->base)exit(1);*e=*--s->top;}int precede(char T op_char,char s1_char) {int i,pre[2];char op[2];op[0]=T op_char;op[1]=s1_char;for(i=0;i<2;i++)switch(op[i]){case'(':case')':pre[i]=0;break;case'+':case'-':pre[i]=1;break;case'*':case'/':pre[i]=2;break;case'^':pre[i]=3;break;}if(pre[0]>=pre[1])return 1;elsereturn 0;}void Translate(char *s1){char s2[80];SqStack_c Optr;int i=0,j=0;char t;InitStack_c(&Optr);Push_c(&Optr,'(');while(s1[i]!='#'){if(s1[i]>='0' && s1[i]<='9' || s1[i]=='.'){s2[j++]=s1[i];if((s1[i+1]<'0' || s1[i+1]>'9') && s1[i+1]!='.') s2[j++]=' ';}elseswitch(s1[i]){case'(':Push_c(&Optr,s1[i]);break;case')':Pop_c(&Optr,&t);while(t!='('){s2[j++]=t;Pop_c(&Optr,&t);}break;default:while(GetT op_c(&Optr,&t),precede(t,s1[i])) {Pop_c(&Optr,&t);s2[j++]=t;}Push_c(&Optr,s1[i]);}i++;}Pop_c(&Optr,&t);while(t!='('){s2[j++]=t;Pop_c(&Optr,&t);}for(i=0;i<j;i++)s1[i]=s2[i];s1[i]='#';s1[i+1]='\0';}void Calculate(SqStack_f *s,char *s2){float m,x,y,z;int i=0,j=0;while(s2[i]!='#'){if(s2[i]>='0' && s2[i]<='9' || s2[i]=='.'){m=0;while(s2[i]!=' ' && s2[i]!='.')m=m*10+(float)(s2[i++]-'0');if(s2[i]=='.'){j=0;i++;while(s2[i]!=' '){m=m*10+(float)(s2[i++]-'0');j++;}while(j>0){m/=10;j--;}}i++;Push_f(s,m);GetT op_f(s,&m);printf("The result is:%g\n",m);}else{Pop_f(s,&x);Pop_f(s,&y);switch(s2[i]){case '+':z=y+x;printf("The result is:%g\n",z);break;case '-':z=y-x;printf("The result is:%g\n",z);break;case '*':z=y*x;printf("The resultis:%g\n",z);break;case '/':if(x==0){printf("表达式出错,除数为‘0’,无意义\n");exit(1);}else{z=y/x;printf("The result is:%g\n",z);break;}case '^':z=1;for(j=1;j<=x;j++){z=z*y;printf("The result is:%g\n",z);}}Push_f(s,z);i++;}}}void result(SqStack_f *s){float v;GetT op_f(s,&v);printf("The final result is:%g\n",v);}void main(){SqStack_f stack;char str[80],c='Y';while(c=='y' || c=='Y'){printf("请输入算术表达式[本程序支持实数的加减乘除乘方运算],结束前请输入‘#’号!\n");gets(str);InitStack_f(&stack);Translate(str);printf("转化后的后缀表达式为:\n");puts(str);Calculate(&stack,str);result(&stack);printf("你想继续吗?'Y'或'y'为继续,其余为退出程序\n");c=getchar();getchar();}}。