前记
女朋友说:“高数好难,看我最近挺辛苦的,你送我一个礼物给我,让我开心一下吧。你猜猜我想要什么。”
我想了半天,从书到鞋子到电子产品最后到生活用品,感觉什么都不缺,然后和她说:“你说要送啥,我就送啥吧”
她坚持要我猜:“不行,你一定要说一个礼物,并且这个礼物要你亲手做的”
于是,我认真了起来,拿起手机,上淘宝逛了几分钟,但还是没能想出来缺点什么,最后实在没办法了:“这样吧,如果你实在想让我送东西,那我帮你写一个计算器吧”
文章的标题只是噱头,作为热爱交流技术的学习者,我们应该脚踏实地,所以我会保证文章的内容都是干货!
设计原理
根据输入中缀算术表达式,利用栈帧结构,实现转换成后缀表达式输出,再对该后缀表达式求值计算输出结果。最终设计出一个计算器。
适用范围:+ - * / % 整数 小数 负数
设计思想
逻辑设计
- 建立两个栈,栈stack和栈Node
- stack栈用于储存字符数组,以字符形式存储中缀表达式的元素。
- Node栈用于储存双精度浮点型的数组,用于存储中缀表达式的元素值和各元素运算操作后的值。
- 设计以下两个函数和相应的入栈出栈操作。
函数名 | 参数 | 作用 |
---|---|---|
Mtf_function() | char *p1,char *mid,char *final | 用于中缀转后缀 |
Caculate() | stack *M,char *final | 计算后缀表达式值 |
Mtf_function()函数设计
(栈为stack)
(1)如果遇到操作数,直接将其输出。
(2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时将其放入栈中。
(3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
(4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( "。
(5)如果读到了输入的末尾,则将栈中所有元素依次弹出。
Caculate()函数设计
(栈为Node栈)
1)遍历表达式,遇到的数字首先放入栈中
2)接着读到运算操作符如“+”,则弹出栈顶元素和下一个元素,执行相应的运算操作,并将计算结果压入到栈中。
3)读到下一个元素,将其直接放入栈中。
4)读到下一个元素如“”,弹出栈顶元素和下一个元素,执行85,执行相应的运算操作,并将计算结果压入到栈中……以此类推。最后求的值存在栈顶上。
对于小数点的处理算法
- 原理:先将小数化为整数,然后除以10的相应权重。建立一个循环,令小数的值sum初始化0,10的相应权重j=0,判断小数点后的字符数组元素是否属于0-9,若是,将小数点后移,sum = sum * 10 + 元素所对应的值,10的相应权重j加一,直到下一个元素不属于0-9。
- 具体算法如下
对于负号的处理
负号的出现位置是字符数组的第一个元素或左括号后面的元素。为避免与减号“-”混淆,通过判断字符数组的第一个元素或左括号后面的元素是否为“-”找出负号,并替换成“M”。中缀转后缀时若元素为“M”则输出“-”。计算后缀的值时若元素为“M”,则之后的元素值(包括小数)转换为相反数后进行操作。
主程序流程图和各模块调用关系
物理设计
-
基于在内存开辟连续存储空间数组实现,C声明定义字符栈帧结构,包含字符数组,用于中缀转后缀表达式
-
相应的节点的含义
-
进出栈操作
-
C声明定义整型栈帧结构,包含整型数组,用于计算后缀表达式求值。
-
相应的节点的含义
-
进出栈操作
测试
- 测试用例
- 测试结果
源代码(带注释)
代码写的是C语言版,后续有时间会补上java版
github代码链接