先吐槽一下自己这么久没码代码,连''和'/'都已然有些分不清了,记不清是'\\'还是‘//’,很尴尬,基础开学以后要从头开始打了。
百科正解实现思路:
遍历中缀表达式的每个节点,如果:
1、 该节点为操作数:
直接拷贝进入后缀表达式
2、 该节点是运算符,分以下几种情况:
A、 为“(”运算符:
压入临时堆栈中
B、 为“)”运算符:
不断地弹出临时堆栈顶部运算符直到顶部的运算符是“(”为止,从栈中删除'('。并把弹出的运算符都添加到后缀表达式中。
C、 为其他运算符,有以下步骤进行:
比较该运算符与临时栈栈顶指针的运算符的优先级,如果临时栈栈顶指针的优先级大于等于该运算符的优先级,弹出并添加到后缀表达式中,反复执行前面的比较工作,直到遇到一个栈顶指针的优先级低于该运算符的优先级,停止弹出添加并把该运算符压入栈中。
此时的比较过程如果出现栈顶的指针为‘(’,则停止循环并把该运算符压入栈中,注意:‘(’不要弹出来。
遍历完中缀表达式之后,检查临时栈,如果还有运算符,则全部弹出,并添加到后缀表达式中。
表达式计算器的正解是前缀表达式或者后缀表达式。因为我的运算只有加减乘除两个优先级,所以我的解法与正解有些许的不同,更为简单一些,但也与正解相似。由于在C/C++方面,我是C with STL
的选手,所以做不来C++异常处理。如果输入的数据不是“正常的”数据,程序就会崩溃。所以这个项目目前来说还不算完结,还有许多坑需要填补。
以下列出需要填补的坑:
说了好久要做的UI还不会做(UWP的原生UI还不错,能做,但是UWP对C++实在太不友好(对C#友好),况且跨平台性也就那样吧;而GTK+和QT的原生UI和UWP比起来丑的一笔,学的不深入又不会自定义UI控件;WinAPI做的UI又丑又烦,如果以后学了什么C上可用的好看的我又会做的UI,再把这个坑补齐)
由于C语言原生的char为8bit,只支持ASCII的表示,Unicode需要两个char来表示,所以在处理上,中文符号‘(’和‘)’显得不太友好。Windows开发中提供了
wchar_t
和wprintf
供给使用,虽然我会用,但是我想在对编码的学习深入之后,用char来做宽字节的处理,这样可以加深对编码的理解,也可以提高跨平台性(Win/Linux)。
异常处理的坑实在是大,尚且不会,会了再填。
Ps:这算是高中毕业之后的第一个C语言项目吧,继续加油balabalabala……
文件如下:calculator.cpp
Date:2018/7/20
另外,附上中缀表达式转后缀表达式的算法(数字均由字母表示,大小写无碍):
中缀表达式看成一个字符串,从左到右开始扫描中缀表达式;
1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
6.最终将栈中的元素依次出栈,输出。
中缀表达式即我们平时所写的表达式,例如:(A+B*C)/D
,而该表达式的后缀表达式表示为:ABC*+D/
。
后缀表达式(逆波兰表达式)的运算方法如下,
从左往右,遇到数字则加入栈中,遇到符号则弹出两个数字进行运算,再将运算结果压入栈中。最后会只剩下栈顶一个数值即为答案。
Ps:中缀表达式转前缀表达式只需要将以上算法方向全部反转即可,即从右往左扫描,从右往左运算。为避免不必要的麻烦,后缀表达式显得更为常用,前缀表达式不太常用。
文件如下:expression.cpp
Date:2018/7/20