贯彻懒狗哲学

Brief Intro

:::info

  • 项目地址:Address
  • 项目简介:
  1. 基础需求:这一部分的内容中**Ver1.0**已经实现 (About 2 hours)
    1. 利用逆波兰表达式、栈等实现一个简单的计算器
    2. 对带有+ - * / ( ) 的算术表达式求值
  2. 附加需求:
    1. sin cos pow 等简单函数
  3. 自己做的需求调整:根据自己的想法优化代码框架,设计了**Ver2.0** (About 1 hour)
    1. pow 函数用 ^ 算符替代
    2. 实现动态压缩括号
    3. 实现对所有简单一元函数的功能基础,设计了快速添加新的简单一元函数方法(详细查看Readme.md) :::

      Project Intro

  • 特色介绍
    • 合理封装
    • 仓库版本管理
    • 使用命令行参数实现无需重复编译更改运行模式
      • 日志打印工具
      • 设置了 panic 出口
        • Warn | Fatal
    • Version 3.0 使用 qt
    • 自己写简洁(低技术力)的 makefile
    • 提供相对方便的自定义函数
  • 文件结构介绍

    Frame Intro

    • 首先简单对需求进行一下任务分解和结构设计

[项目报告] 2022/5/18 逆波兰表达式计算器 - 图1
此处简单说明一下本项目对“运算符”和“函数”的定义:

  • 首先,因为我比较懒,所以只做了双目运算符,单参函数。其他目等可以同理类推;
  • “运算符”:
    • 参与运算的两个参数在中缀表达式中位于关键字的两侧,如:1+2中的+1a2中的a1xor2中的xor等;
    • 参与该运算符的 最简 完整 表达式最终计算结果等效于一个数字量,如:1+2等效于31xor3等效于2等;
  • “函数”:
    • 参与运算的参数在中缀表达式中全部位于关键字之后(如果是多个参数,则用逗号分割),如sin(3.1415)中的sin()QWQ(3)中的QWQ等;
    • 参与该运算符的 最简 完整 表达式最终计算结果等效于一个数字量,如:sin(3.1415)等效于0reciprocal(2)等效于0.5等;
  • 也就是我主要把所有的双目运算设计成了“运算符”,把单目运算设计成了“函数”,但是他们本质上都是抽象的函数,只是如何处理数据格式的问题。你当然可以把所有的双目运算都设计成函数,但是这样一来,一个算式会变得比较复杂:
  • 1+2+3+4 & add(add(add(1,2),3),4)(顺序取决于如何入栈)
  • 然而,使用函数来代替运算符的好处就是不需要判断优先级,毕竟有括号。
  • 实际上设计思路是类似的,所以我没有继续做下去。

那么接下来就是如何处理这么多东西了。

  • 递归思想
    • 我们假设一个表达式不存在括号,只有双目运算符和数字
    • 那实际上没必要为操作开一个栈
  • 设计一个函数用来获取表达式的值
  • 设计若干函数处理若干“运算符”和“函数”
  • 任何运算符或函数只处理数值,不处理表达式
  • 那其实思路非常简单了~

我最终使用的思路是:

  • 动态处理单参函数、逆波兰处理双目运算符

    Code Intro

    哲学目标:

  • 高内聚 | 低耦合 | 强封装 | 逻辑精简 | 不写忍者代码 | 可追踪 | 清晰的注释 | 良好的缩进 ……

    1. (1+2*(sin(0.5*cos(3.1415)*3.1415)*2)^2)
    1. YourFuncName((1+2*(sin(0.5*cos(3.1415)*3.1415)*2)^2))

我的代码中不好的地方:

  • 负数
  • 少部分内容的封装还是不够到位
  • 因为懒得在 C 里做内存管理所以没有使用动态申请内存的方法
  • 压行
  • 自定义函数其实可以热添加的做法,即不需要更改源代码的做法,但是我懒得做了
    • 具体实现可以一定程度上复用计算的方法,只需要处理特定的指定未知量的语法就好了
    • 再下去就是编译原理的哲学世界了x