逆波兰式的产生及计算

预习报告

实验题目:逆波兰式的产生及计算

一、实验目的

(1)实验目的深入理解算符优先分析法;

(2)掌握利用FIRSTVT和LASTVT集合构造算符优先关系表的方法;

(3)掌握利用算符优先分析法完成中缀表达式到逆波兰式的转化;

(4)理解利用逆波兰式求解表达式的方法。

、实验原理

逆波兰表达式的产生原理:

1.从左到右依次扫描中缀表达式;

2.如果输入带当前元素为数字 ,直接输出到输出带中;

3.如果输入带当前元素为运算符

(1)如果当前操作符堆栈为空, 不管是什么运算符都直接push压入堆栈中;

(2)如果当前输入带操作符为 ‘)’,一直pop弹出栈顶元素到输出带中,直到遇到’(’ tip: 括号不输出;

(3)如果当前输入带操作符不为’)’,当操作符堆栈中栈顶运算符的优先级大于等于输入带当前运算符优先级,则将操作符堆栈栈顶pop弹出,并输出到输出带中,直到栈顶优先级小于当前优先级;如果操作符堆栈中栈顶运算符的优先级小于输入带当前运算符优先级,则将当前运算符push压栈。

4.当输入带扫描完成,将操作符堆栈中剩余运算符pop弹出到输出带中。

逆波兰表达式的计算原理:

对输入带从左到右依次扫描如果输入带当前元素为数字,将其push压入运算数堆栈如果输入带当前元素为运算符,取出运算数堆栈栈顶的两个元素,第一个栈顶元素为右运算数,第二个栈顶元素为左运算数,再将运算结果压入栈顶扫描结束后,运算数堆栈剩余的一个元素就是结果

、实验要求

1. 单词分类

将中缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值。例如:

(1)输入以#结束的中缀表达式(包括+—*/()数字#):(12+20)*8#

(2)逆波兰式为:12 20 + 8*#

(3)逆波兰式12 20 + 8* 计算结果是: 256

2. 待分析的源程序的输入形式和识别后单词的输出形式

明确本实验的输入为文件输入,注意文件要放在文档根目录下,否则无法识别。输出二元组中单词种别码的表述形式。

  1. 函数关系图

4. 算法设计

函数首部

主要功能

isDigit

判断字符是否为数字

readNum

读取连续的数字构成整数返回

readFile

读取文件函数,返回一个string动态数组,以行数分割

isValid

判断表达式是否有效(只能包含+-* /()数字)

compute

计算逆波兰表达式的值

printPostfixExp

输出逆波兰表达式

isOperate

判断是否为 + - * /

sti

字符串转数字

printExp

输出中缀表达式

getPostfixExp

中缀表达式转逆波兰表达式

实验报告

实验题目:逆波兰式的产生及计算

概述

    在本次实验中,我们成功地实现了逆波兰式的产生及计算。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序。本次实验主要功能包括将中缀式用来表示的算术表达式转换为用逆波兰式来表示的算术表达式,并计算用逆波兰式来表示的算术表达式的值(输入算术表达式、将中缀表达式转换为逆波兰式、计算逆波兰式并输出结果)。在实验的过程中还设计了错误检测和处理、支持多种运算符和函数等功能,为本次实验增添了一些亮点。

    逆波兰式可以有效地避免中缀表达式的优先级问题,使得计算过程更加简单和直观。其次,逆波兰式的计算速度比中缀表达式要快,因为逆波兰式不需要进行括号匹配和优先级比较等操作。

二、实验方案

1. 逆波兰式的产生和求解规则

(1)逆波兰式产生规则

使用了运算符栈。通过对当前字符的判断进行不同的操作,如果是数字则直接存储,如果是运算符则进入运算符栈中,最后根据运算符优先级的规则使中缀表达式转化为逆波兰式。逆波兰式的语法更加简单,不需要使用括号来指定操作顺序,减少了解析表达式的复杂性等。

(2)求解规则

使用了数字栈。通过键盘一些字符与操作数,利用一个字符串来保存,并同时定义一个栈与字符串指针,每次栈里面保存当前输入的操作数,而当遇到运算符时将栈顶与栈的上个元素进行相应的运算,并将栈顶元素弹出同时保存进入新的栈顶中,在最后进行判断从而实现对输入正确的逆波兰表达式输出其运算结果。

3. 逆波兰式的产生的程序流程图

三、实验过程及结果分析

1.测试过程

(1)单条中缀表达式转换为逆波兰式求值计算测试

①测试用例

92*(2+3-6*(3+2))+6*8#

②测试结果

(2)错误中缀表达式提示信息测试

①测试用例

92*(2+3-6*(3+2))+6*#

(正确应为:92*(2+3-6*(3+2))+6*8#,这里删除一个8测试正确性)

②测试结果

2.调试分析

在对程序进行编写的过程中,对与符号优先级的部分产生了一定的问题,主要集中在括号的判断条件上,如果将括号置为最低优先级,那么在进行操作符入栈的过程中括号无法入栈的情况,如果置为最高优先级,那么在入栈后对于其他符号的判断则会产生问题,市区括号原有的功能和界定范围。解决方案是一直将括号的优先级置为最低,在入栈时进

行单独判断,如果是括号则无视优先级顺序直接入栈。

四、总结与体会

    通过本次实验,深入了解了逆波兰式的产生和计算原理,掌握了中缀表达式转换为逆波兰式的方法和逆波兰式的计算方法。此外还学习了如何处理错误和支持更多的运算符和函数,这对我今后的编程工作也有很大的帮助。在实验过程中,也遇到了一些困难,设计的程序无法正确识别输出正确的结果,需要不断地调试,在解决bug的过程中,更加深入地了解了编译原理的相关知识,提高了我的编程能力和解决问题的能力。而如何处理错误和如何支持变量赋值和使用等也始终困扰着我,最终通过查阅资料和与同学讨论的方式解决了这些问题。这让我更加深入地理解了逆波兰式的原理和实现方法。

    本次实验的结果与预期相符,成功地完成了实验任务,并且实现了一些额外的功能。这次实验对我的课程理论学习和编程能力的提高都有很大的帮助。更加深了我对逆波兰式的相关知识的理解和掌握。

  • 60
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
逆波兰式也称为后缀表达式,是一种不含括号的数学表达式。其计算顺序与中缀表达式相同,但是可以通过栈来实现计算。 下面是用 C++ 实现逆波兰式生成计算的示例代码: ```c++ #include <iostream> #include <stack> #include <string> #include <vector> using namespace std; int main() { // 输入逆波兰式 string rpn; cout << "请输入逆波兰式:" << endl; getline(cin, rpn); // 将逆波兰式拆分为操作数和操作符 vector<string> tokens; string token = ""; for (int i = 0; i < rpn.length(); i++) { if (rpn[i] == ' ') { tokens.push_back(token); token = ""; } else { token += rpn[i]; } } tokens.push_back(token); // 计算逆波兰式 stack<int> numStack; for (int i = 0; i < tokens.size(); i++) { string token = tokens[i]; if (token == "+" || token == "-" || token == "*" || token == "/") { int num2 = numStack.top(); numStack.pop(); int num1 = numStack.top(); numStack.pop(); int result; if (token == "+") { result = num1 + num2; } else if (token == "-") { result = num1 - num2; } else if (token == "*") { result = num1 * num2; } else if (token == "/") { result = num1 / num2; } numStack.push(result); } else { int num = stoi(token); numStack.push(num); } } // 输出结果 cout << "计算结果:" << numStack.top() << endl; return 0; } ``` 这个程序首先要求用户输入一个逆波兰式,然后将其拆分为操作数和操作符。接着,程序使用一个栈来计算逆波兰式的值。对于每个操作符,程序将栈顶的两个数弹出,计算后将结果压回栈中。对于每个操作数,程序将其转换为整数并压入栈中。最后,程序输出计算结果。 注意,这个程序没有对输入的逆波兰式进行任何错误检查,如果输入的逆波兰式不符合规范,程序可能会出错。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值