• 2017-2018-2 20172323 『Java程序设计』课程 结对编程练习_四则运算 2


    相关过程截图







    关键代码解释

    • 将运算式分开的代码
      String[] result = num.split("\s");
      将输入的num以空格为间隔符号分开,将每一个间隔开的字符存入一个名为result的数组里。

    • if ("+".equals(a) || "-".equals(a)) { if ("+".equals(b) || "-".equals(b) || ")".equals(b) || "#".equals(b)) { c = OPTR.pop(); z = OPND.pop(); y = OPND.pop(); //str += " "; str += y; str += " "; str += z; str += " "; str += c; str += " "; OPND.push(str); str = ""; if ("(".equals(OPTR.peek()) && ")".equals(result[x])){ OPTR.pop(); }
      这里给出了一个当a(栈顶元素)的优先级大于b(输入运算符)的情况,将运算符栈的栈顶和操作数栈头两个数提出,重新拼接成一个新的整体的字符存入操作数栈,再将式子的值清空(防止新的式子加在曾经的式子后面),将当前运算符压入运算符栈,但当a匹配b时就直接将栈顶元素a剔除掉(防止转为后缀后依然带有“(”“)”号)。(这里基本实现了当a > b时,a出栈,从OPND依次弹出两个操作数y,x,z = x y a,并将a压入栈OPND,c压进OPTR的操作)

    • if ("=".equals(result[x])) { while (OPND.size() != 0) { number.push(OPND.pop()); } suf += " "; suf += number.pop(); while (number.size() != 0){ suf += " "; suf += number.pop(); } while (OPTR.peek() != "#"){ suf += " "; suf += OPTR.pop(); } suf += " "; suf += "="; } }
      这里我将“=”设为了一个终止的标志,当程序识别到“=”号时,程序将两个栈里的元素进行清理,最终拼接成后缀式。在该程序里,我将操作数栈里的元素重新压入进一个新的栈里,这样就颠倒了栈里元素的顺序,方便之后的拼接。

    遇到的困难及解决方法

    • 1:最开始的思路不是特别清晰,没有把老师上课提供的方法领悟,几乎是在凭自己的思路在编写。一开始的思路是,逐步编辑,先编写出只能转换纯加减号或纯乘除号的式子,再在此基础之上拓展为加减乘除混合运算的式子并实现转换,最后再加上括号,我想实现三步走的计划。

    • Q:如何将输入的式子的每一项分开成为一个单独的字符,尤其是x/y型的分数,如何能使程序将包含三个元素的分数归为一个又不影响其他只含一个元素的字符?

    • A:String下有一个split方法,它可以将指定字符作为分隔标记,且将分隔开的字符存入一个数组里面,在这里我就可以使用空格作为分隔标记,而真分数的数与运算符之间不用空格进行间隔,这样就可以实现了。

    • Q:进行纯的加减或是纯的乘除的运算的思路比较简单,就相当于将原式子的操作数和运算符分别抽离,再进行重新拼接的过程,这也算是给后面挖了一个很大的坑吧,也就是说升级进行加减乘除混合运算的代码实现时,因为运算符的相对位置的不同,转后缀的过程如果单纯有编码者自己去预料到所有情况显然是有些困难的,所以我在这里编写了极其极其冗杂的if-else语句来判断情况进行拼接。附一张只能进行纯加减运算的转后缀

    • A:当时我想到的解决方案是,如果是这样的一串运算式1 + 2 * 3 - 4/5 ,那就先通过一个方法,将用乘除号连接的式子用一个新的字符b来表示,那之后的运算式就转换为1 + b - 4/5这样再调用第一步的纯加减运算,就可以解决了。

    • Q:但如上给出的解决方案看似可行实际上依然难以实现,因为依然要考虑运算符的前一个和后一个运算符的情况,比如我想当遇到第一个乘号或者除号时,用substring方法将一整串式子提出,但是遇到后一个乘号或是除号时,进行大量的判断,所以整个代码依然是特别浩繁的。

    • A:经过组员的提醒,我才重新看了一遍老师的讲课,发现其在PPT中给出了清晰的思路,所以之前算是给自己交的学费吧。

    • 2

    • Q:如何建立运算符的优先级?

    • A:最开始我想编写一个Compare类,在类中定义好所有运算符的优先级关系,在转后缀时,判断栈顶元素和当前输入运算符的关系,输出“<”,“>”,“=”(因为题目生成时不会有错误,所以就没有再考虑错误的情况)。而大于小于等于的关系我想用封装器将栈顶元素和输入运算符赋为int值0和1,这样比较起来就比较容易,但是最后实行起来貌似比较困难,然后我又想到第五章的编程项目PP5—7“剪刀石头布”的编写似乎和这个的比较有相似之处,然后翻阅之前的代码,明确了一个思路,不再单独编写一个类来实现,直接使用if-else语句把所有情况罗列(没错,感觉又一步一步地朝着最开始的思路在行进了。)其他关于这部分的问题在关键代码的解释中有了解释。

    写出项目中自己负责的部分

    实现中缀表达式转为后缀表达式

    个人贡献度划分(按百分比给小组各成员划分贡献度,各成员贡献之和为100%)

    方艺雯 谭鑫 王禹涵
    贡献度 33.4% 33.3%

    对结对的小伙伴做出评价给出小伙伴博客链接(重点指出需要改进的地方)

    • 20172305代码编写认真且有开阔的视野,能够不拘泥于固定的思维。
    • 20172314代码编写非常的认真,遇到问题也很努力的在想办法解决。

    给出项目的码云链接

    给出小组结对编程照片

  • 相关阅读:
    CUDA教程三、cuda的随机数生成
    python 使用element tree 解析 xml
    [转载] Shell正则表达式大全
    git 更新项目中子模块的版本
    git 切换到本地不存在但远端存在的分支
    vue.js3:在css中使用变量(vue@3.2.6)
    mybatis做update:动态传入要更新的字段名和字段值(mybatis 3.5.7)
    npm全局安装和非全局安装的区别(node v16.13.1 / npm 8.4.1)
    vue.js3:用mitt发送接收事件消息(vue@3.2.6 / mitt@3.0.0)
    vue3: 动态修改favicon(网站的ico 图标)(vue@3.2.26)
  • 原文地址:https://www.cnblogs.com/Lewandodoski/p/9011575.html
Copyright © 2020-2023  润新知