1208: 计算整数四则运算表达式的结果

参考资料

数据结构(C语言版)严蔚敏 吴伟民 编著————表达式求值

题目

  简单四则运算。更多内容点击标题。

  1. 保证表达式合法。
  2. 运算符只包含:加(+),减(-),乘(*),除(/)。
  3. 以等号(=)结束。

提示

  1. 表达式只包含:数字字符,加,减,乘,除,等号这六种符号。
  2. 测试数据不存在分母为0的情况,代码中不用考虑。
  3. 全部为int型,不存在浮点型,也就是说:3/2=15/2=2
  4. 切记,虽然题目没说多组输入,但是测试数据有很多(我被被坑了)。
  5. 操作数可能不止一位,例如:10+8=

测试数据(不像OJ的Simple Input跟没有一样QAQ)

输入
  1. -5/2+0+1*3+14=
  2. 520=
输出
  1. 15
  2. 520

这两组数据对了,你可以直接提交了,肯定对。

分析

  这道题目很明显是在考察的运用,不知道栈是什么的,自己参考其他资料。这里只讲题目思路。

  有这本书的可以看看书(应该能看懂),没有的话,我就稍微啰嗦一下。



  四则运算规则不需要我说吧。下面是这道题目的运算关系表:


  这里要用到两个栈(Stack),分别是运算数栈(opnd)运算符栈(optr)。分别保存运算符和运算数。代码声明如下:

  1. /**
  2. 1. @Field optr 运算符栈
  3. */
  4. private Stack<Character> optr;
  5. /**
  6. 2. @Field opnd 运算数栈
  7. */
  8. private Stack<Integer> opnd;

  算法思想:

  1. 表达式最后一个字符是’=’,因此将运算符栈栈底置为’=’
  2. 依次读取表达式中的每个字符,如果是数字字符,则将这个操作数进opnd栈,如果是运算符,则和optr栈顶运算符比较优先级后进行操作。
  3. 直到计算结束(optr栈顶和当前字符都为’='说明计算结束)。

  测试数据 1 运算过程如下:

步骤 optr(运算符栈) opnd(运算数栈) 剩余字符 主要操作
1 = -5/2+0+1*3+14= opnd.push(0)
2 = 0 -5/2+0+1*3+14= optr.push(’-’)
3 = - 0 5/2+0+1*3+14= opnd.push(5)
4 = - 0 5 /2+0+1*3+14= optr.push(’/’)
5 = - / 0 5 2+0+1*3+14= opnd.push(2)
6 = - / 0 5 2 +0+1*3+14= opnd.push(calculate(5,’/’,2))
7 = - 0 2 +0+1*3+14= opnd.push(calculate(0,’-’,2))
8 = -2 +0+1*3+14= optr.push(’+’)
9 = + -2 0+1*3+14= opnd.push(0)
10 = + -2 0 +1*3+14= opnd.push(calculate(-2,’+’,0))
11 = -2 +1*3+14= optr.push(’+’)
12 = + -2 1*3+14= opnd.push(1)
13 = + -2 1 *3+14= optr.push(’*’)
14 = + * -2 1 3+14= opnd.push(3)
15 = + * -2 1 3 +14= opnd.push(calculate(1,’*’,3))
16 = + -2 3 +14= opnd.push(calculate(-2,’+’,3))
17 = 1 +14= optr.push(’+’)
18 = + 1 14= opnd.push(14)
19 = + 1 14 = opnd.push(calculate(1,’+’,14))
20 = 15 = Output(opnd.peek())

  【备注】手打不易,且看且珍惜。

  【说明】1、左边是栈底,右边是栈顶。2、剩余字符中的加粗字符(也就是最左边的字符)表示正在读取的字符。3、optr.push()表示进运算符栈;opnd.push()表示进运算数栈;calculate()表示二元运算;opnd.peek()表示获取栈顶元素(Java的Stack类自带方法);Output()表示输出。4、第18步至19步没看懂的阅读代码的getInt()方法。



  下图为课本例题的过程图:

代码

  1. /**
  2. * time 268ms
  3. * @author PengHao
  4. * @version A2.0
  5. * @date 2019-04-23 下午10:48:22
  6. */
  7. import java.util.Scanner;
  8. import java.util.Stack;
  9. public class Main {
  10. private Scanner sc;
  11. /**
  12. * @Field formal 算式
  13. */
  14. private String formal;
  15. /**
  16. * @Field optr 运算符栈
  17. */
  18. private Stack<Character> optr;
  19. /**
  20. * @Field opnd 运算数栈
  21. */
  22. private Stack<Integer> opnd;
  23. /**
  24. * @Field index 正在读取的式子中的字符的下标
  25. */
  26. private int index;
  27. public Main() {
  28. sc = new Scanner(System.in);
  29. char temp; // 临时变量
  30. while (sc.hasNext()) {
  31. formal = sc.next(); // 式子
  32. init(); // 初始化
  33. temp = formal.charAt(index); // 获取当前字符
  34. // 只有当前字符和运算符栈栈顶都是‘=’时,才退出循环,表示计算结束
  35. while ('=' != temp || '=' != optr.peek()) {
  36. if (Character.isDigit(temp)) { // 当前字符是数字
  37. opnd.push(getInt()); // 将当前运算数入栈
  38. } else { // 当前字符是运算符
  39. if (0 == index) { // 这个字符是算式的第0个字符
  40. opnd.push(0); // 将数字0入运算数栈栈顶
  41. }
  42. operate(); // 运算操作
  43. }
  44. temp = formal.charAt(index); // 获取算式的当前的字符
  45. }
  46. System.out.println(opnd.peek()); // 输出运算数栈栈顶(即算式结果)
  47. }
  48. sc.close();
  49. }
  50. /**
  51. * Initializes the properties of the class
  52. */
  53. private void init() {
  54. optr = new Stack<Character>();
  55. opnd = new Stack<Integer>();
  56. optr.push('='); // 初始运算符栈有一个‘=’
  57. index = 0; // 第0个字符
  58. }
  59. /**
  60. * @return 式子中当前需要输入的运算数
  61. */
  62. private int getInt() {
  63. int num = 0, n;
  64. char temp;
  65. do {
  66. // char型转成int型,并且下标向后移动一位
  67. n = formal.charAt(index++) - '0';
  68. num = num * 10 + n; // 转成运算数
  69. temp = formal.charAt(index); // 获取当前字符
  70. } while (Character.isDigit(temp)); // 当前字符是数字,则属于同一个运算数
  71. return num;
  72. }
  73. /**
  74. * Arithmetic operations
  75. */
  76. private void operate() {
  77. int num1, num2; // 需要计算的两个运算数
  78. char op; // 需要计算的运算符
  79. char a = optr.peek(); // 运算符栈的栈顶运算符
  80. char b = formal.charAt(index); // 算式的当前的运算符
  81. if ('>' == priority(a, b)) { // 栈里面的运算符优先级较高
  82. num2 = opnd.pop(); // 先出栈的是第二个运算数
  83. op = optr.pop(); // 运算符
  84. num1 = opnd.pop(); // 后出栈的是第一运算数
  85. opnd.push(calculate(num1, op, num2)); // 运算结果入运算数栈
  86. } else { // 当前运算符优先级较高
  87. optr.push(b); // 当前运算符入运算符栈
  88. index++; // 算式下标后移一位
  89. }
  90. }
  91. /**
  92. * @param a 第一个运算符
  93. * @param b 第二个运算符
  94. * @return > 如果 <b>a</b> 的优先级高于 <b>b</b> 的优先级</br>
  95. * < 如果 <b>a</b> 的优先级低于 <b>b</b> 的优先级
  96. */
  97. private char priority(char a, char b) {
  98. if ('*' == a || '/' == a) { // a运算符优先级最高
  99. return '>';
  100. }
  101. if ('*' == b || '/' == b) { // b运算符优先级最高
  102. return '<';
  103. }
  104. if ('=' == a) { // a是‘=’,优先级肯定是最低的
  105. return '<';
  106. }
  107. return '>'; // 从左到右运算顺序,a优先级高于b(a在b左边)
  108. }
  109. /**
  110. * @param num1 第一个运算数
  111. * @param op 两个运算数之间的运算符
  112. * @param num2 第二个运算数
  113. * @return num1 op num2 的运算结果
  114. */
  115. private int calculate(int num1, char op, int num2) {
  116. switch (op) {
  117. case '+':
  118. return num1 + num2;
  119. case '-':
  120. return num1 - num2;
  121. case '*':
  122. return num1 * num2;
  123. case '/':
  124. return num1 / num2;
  125. default:
  126. return 0;
  127. }
  128. }
  129. public static void main(String[] args) {
  130. new Main();
  131. }
  132. }

写在最后:

  1. 如需转载,请于首页至少注明链接形式的wowpH的博客这几个字;
  2. 代码原创,如需公开引用,不能删除首行注释(作者,版本号,时间等信息)。
  3. 如果有疑问欢迎评论留言,尽量解答。

WUSTOJ 1208: 计算整数四则运算表达式的结果(Java)的更多相关文章

  1. 去空格的四则运算表达式求值-Java

    笔记 package com.daidai.day4.demo1; import java.util.ArrayList; import java.util.Arrays; import java.u ...

  2. sql server编写简洁四则运算表达式脚本实现计算批次功能(C#等其它编程语言也能直接用此通用表达式)

    问题: 在数据库编程开发中,有时会遇到数据量比较大的情况,如果直接大批量进行添加数据.修改数据.删除数据,就会是比较大的事务,事务日志也比较大,耗时久的话会对正常操作造成一定的阻塞.虽不至于达到删库跑 ...

  3. 数据结构课程设计四则运算表达式求值(C语言版)

    本系统为四则运算表达式求值系统,用于带小括号的一定范围内正负数的四则运算标准(中缀)表达式的求值.注意事项:    1.请保证输入的四则表达式的合法性.输入的中缀表达式中只能含有英文符号"+ ...

  4. 大整数四则运算(vector与数组两种版本实现)

    每逢大整数四则运算,都会怯懦,虽是算法竞赛必会的东西,也零散的学过,简单的总结过,但不成体系的东西心里一直没底. 所以今天消耗了大量的卡路里,啃了几套模板之后终于总结成了一套自己的模板 再也不用担心大 ...

  5. PAT IO-02 整数四则运算

    /* *PAT IO-02 整数四则运算 *2015-07-30 *作者:flx413 */ #include<stdio.h> int main() { int a, b; scanf( ...

  6. JAVA计算整数的位数

    /** * 计算整数的位数 * @param x * @return */ public static int countIntegerLength(int x){ final int [] size ...

  7. 小学生四则运算出题软件-基于java控制台的实现

    .题目描述: 1. 使用 -n 参数控制生成题目的个数,例如 Myapp.exe -n 10 -o Exercise.txt 将生成10个题目. 2. 使用 -r 参数控制题目中数值(自然数.真分数和 ...

  8. 随机四则运算的出题程序java

    一.设计思想 1.功能较多必须有菜单选择项,将一个大程序分为若干个功能模块的小程序,逐个实现2.针对题目避免重复时先将已生成的算式保存,然后将下一条生成的式子进行判断是否已生成,如果生成则返回循环语句 ...

  9. 结对项目:四则运算题目生成器(Java)

    目录 一.需求分析 二.开发计划 三.实现方案 3.1 项目结构 3.2 代码说明 3.2.1 出题功能代码 3.2.3 批卷功能代码 3.2.3 四则运算功能代码 四.效能分析 4.1 程序效能 4 ...

随机推荐

  1. 使用python2 对服务器监控(监控内存,CPU,网卡流量等)

    #!/usr/bin/env python # -*- coding:utf- -*- #create at -- 'this is a system monitor scripts' __autho ...

  2. mapper @Select()注解开发,使用模板 if 和循环

    if @Select({"<script>", "SELECT " + " mu.id userId, " + " e ...

  3. Logback 输出 JPA SQL日志 到文件

    Logback 输出 JPA SQL日志 到文件 使用Spring Boot 配置 JPA 时可以指定如下配置在控制台查看执行的SQL语句 spring.jpa.show-sql=true Sprin ...

  4. Matlab 图像平移、旋转、缩放、镜像

    今天学习了用Matlab实现对图像的基本操作.在Matlab中,图像是按照二维矩阵的形式表示的.所以对图像的操作就是对矩阵的操作. 对图像进行缩放.平移.旋转,都可以转化为矩阵的运算. 关于变换矩阵的 ...

  5. 基础数据结构 对应 基础api

    <深入理解Redis> mastering redis

  6. 用http请求thrift服务端出现了内存溢出的情况

    记一次内存溢出的分析经历 - Janti - 博客园 https://www.cnblogs.com/superfj/p/8474288.html 说在前面的话 朋友,你经历过部署好的服务突然内存溢出 ...

  7. redis配置文件讲解

    #redis.conf # Redis configuration file example. # ./redis-server /path/to/redis.conf ############### ...

  8. keras启用tensorboard

    在callback函数中添加tensorboard,启用tensorboard. # TensorBoard callback tensorboard_cb = K.callbacks.TensorB ...

  9. Row_Number() and Rank() in SQL

    1. 数据表实例数据 2. 使用Row_Number()方法给每一行数据添加一个唯一编号, 可以按照某一列进行排序. 3. 使用Partition by Column在一个Partition内进行编号 ...

  10. CGI "Internal Server Error"

    在安裝 CGI 程式時如果設定錯誤,便會看到 "500 Internal Server Error" 訊息,一般常見的錯誤可以用以下方法解決: 1. CGI 程式的權限需要設定為 ...