贯彻懒狗哲学
Brief Intro
:::info
- 项目地址:Address
- 项目简介:
- 基础需求:这一部分的内容中
**Ver1.0**
已经实现 (About 2 hours)- 利用逆波兰表达式、栈等实现一个简单的计算器
- 对带有
+
-
*
/
(
)
的算术表达式求值
- 附加需求:
sin
cos
pow
等简单函数
- 自己做的需求调整:根据自己的想法优化代码框架,设计了
**Ver2.0**
(About 1 hour)
- 特色介绍
- 合理封装
- 仓库版本管理
- 使用命令行参数实现无需重复编译更改运行模式
- 日志打印工具
- 设置了 panic 出口
- Warn | Fatal
- Version 3.0 使用 qt
- 自己写简洁
(低技术力)的 makefile - 提供相对方便的自定义函数
- 文件结构介绍
Frame Intro
- 首先简单对需求进行一下任务分解和结构设计
此处简单说明一下本项目对“运算符”和“函数”的定义:
- 首先,因为我比较懒,所以只做了双目运算符,单参函数。其他目等可以同理类推;
- “运算符”:
- 参与运算的两个参数在中缀表达式中位于关键字的两侧,如:
1+2
中的+
、1a2
中的a
、1xor2
中的xor
等; - 参与该运算符的 最简 完整 表达式最终计算结果等效于一个数字量,如:
1+2
等效于3
,1xor3
等效于2
等;
- 参与运算的两个参数在中缀表达式中位于关键字的两侧,如:
- “函数”:
- 参与运算的参数在中缀表达式中全部位于关键字之后(如果是多个参数,则用逗号分割),如
sin(3.1415)
中的sin()
、QWQ(3)
中的QWQ
等; - 参与该运算符的 最简 完整 表达式最终计算结果等效于一个数字量,如:
sin(3.1415)
等效于0
,reciprocal(2)
等效于0.5
等;
- 参与运算的参数在中缀表达式中全部位于关键字之后(如果是多个参数,则用逗号分割),如
- 也就是我主要把所有的双目运算设计成了“运算符”,把单目运算设计成了“函数”,但是他们本质上都是抽象的函数,只是如何处理数据格式的问题。你当然可以把所有的双目运算都设计成函数,但是这样一来,一个算式会变得比较复杂:
1+2+3+4
&add(add(add(1,2),3),4)
(顺序取决于如何入栈)- 然而,使用函数来代替运算符的好处就是不需要判断优先级,毕竟有括号。
- 实际上设计思路是类似的,所以我没有继续做下去。
那么接下来就是如何处理这么多东西了。
- 递归思想
- 我们假设一个表达式不存在括号,只有双目运算符和数字
- 那实际上没必要为操作开一个栈
- 设计一个函数用来获取表达式的值
- 设计若干函数处理若干“运算符”和“函数”
- 任何运算符或函数只处理数值,不处理表达式
- 那其实思路非常简单了~
我最终使用的思路是:
-
Code Intro
哲学目标:
高内聚 | 低耦合 | 强封装 | 逻辑精简 | 不写忍者代码 | 可追踪 | 清晰的注释 | 良好的缩进 ……
(1+2*(sin(0.5*cos(3.1415)*3.1415)*2)^2)
YourFuncName((1+2*(sin(0.5*cos(3.1415)*3.1415)*2)^2))
我的代码中不好的地方:
- 负数
- 少部分内容的封装还是不够到位
- 因为懒得在 C 里做内存管理所以没有使用动态申请内存的方法
- 压行
- 自定义函数其实可以热添加的做法,即不需要更改源代码的做法,但是我懒得做了
- 具体实现可以一定程度上复用计算的方法,只需要处理特定的指定未知量的语法就好了
- 再下去就是编译原理的哲学世界了x