黑马程序员-控制台下的连续四则计算器
来源:互联网 发布:sd卡格式化后数据还在 编辑:程序博客网 时间:2024/06/03 02:21
------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------
效果:输入一个四则运算式回车,计算这个算式的结果:
连续运算看似简单,且方法多样,但要做到有通用性和扩展性却很不容易,而且优先级的调整也让人头疼。
要点1:
后缀表达式:
假设用户输入了一个算式是这样的:
4+5-7*2
类似的长算式,怎么让程序连续计算呢,首先第一步是要把这个串调整成后缀表达式的形式,就是所有数字在前而运算符在后面倒序排列的形式,拿刚才那个算式来说,就是变成这样:
4,5,7,2,*,-,+
后缀表达式又称之为逆波兰算式,调整成后缀表达式的好处是操作数和操作符分开提取,当要增加运算种类和调整优先级的时候比较容易
下面是C#版的后缀表达式调整算法:
myStack stack1; myStack NumStack; initStack(out stack1); initStack(out NumStack); string str = Console.ReadLine(); //接受用户输入的一个串 string[] str2; //声明一个储存数字的字符串数组 char[] op = new char[4] { '+', '-', '*', '/' }; //声明一个包含四种运算符的字符数组 //char[] opArray = new char[64]; //声明一个储存算式中出现的运算符(有顺序)的字符数组 str2 = str.Split(op); //将输入串按照运算符的间隔分割成各个数字(需要转换成int) for (int i = 0; i < str.Length; i++) {//检索字符串中出现的运算符,倒序存入运算符数组中 switch (str.Substring(i, 1)) { case "+": pushStack(ref stack1, '+'); break; case "-": pushStack(ref stack1, '-'); break; case "*": pushStack(ref stack1, '*'); break; case "/": pushStack(ref stack1, '/'); break; default: break; } } foreach (string s in str2) { pushStack(ref NumStack, s); }
这里我们用到了栈结构,栈结构是FILO也就是先进后出了,当然你也可以使用泛型集合,把眼光从令人头疼的拆箱和装箱操作上移开,只关注程序的算法逻辑,贴一个笔者自己写的栈操作函数(很菜的水平):
如此,为了确保通用性而使用拆装箱操作而大大牺牲了效率,实在是得不偿失
如此,进行到这里我们已经把操作数和操作符分别压到了两个栈中,下面就是具体计算的过程:
运算的过程是这样的:
数字栈中弹出一个数
操作数栈弹出一个运算符
数字栈再弹出一个数
运算,将结果压回数字栈中
重复 弹出数字,弹出运算符 再弹出数字,运算,结果压入栈 这个操作
static int calc(ref myStack st, ref myStack NumStack) {//接受两个栈的引用作为参数 int result=0; int i=0; while (NumStack.top > 0 && st.top>0) { result = Convert.ToInt32((string)popStack(ref NumStack));//从栈中弹出一个操作数(两次转换,object类型拆箱时只能拆成原来装进去的数据类型,也就是string,所以还要转换一次) switch ((char)popStack(ref st)) {//弹出一个操作符并判断操作符类型 case '+': result += Convert.ToInt32((string)popStack(ref NumStack)); pushStack(ref NumStack, result.ToString());//弹出操作数进行加法运算,将运算结果压回栈里面(想当初如果直接转换成int再压栈就不会这么转换来转换去了) break; case '-': result = Convert.ToInt32((string)popStack(ref NumStack))-result; pushStack(ref NumStack, result.ToString());//其余运算同加法 break; case '*': result *= Convert.ToInt32((string)popStack(ref NumStack)); pushStack(ref NumStack, result.ToString()); break; case '/': try { result = Convert.ToInt32((string)popStack(ref NumStack))/result; pushStack(ref NumStack, result.ToString()); } catch { Console.WriteLine("0不能做除数"); } break; default: break; } } return result; }
最后要解决的是优先级的问题,这个问题留给你们,因为操作符和操作数都在堆栈中,如果需要调整的运算符在栈底,那么全部弹出显然很不经济,这个时候就可以把栈看成数组或者队列来操作,我也没有什么太好的办法,而且同一优先级的运算符在一起还有结合性的问题,比如:
2-3+1=?
应该先算减法还是加法?同一级别的运算符的结合性应该是从左到右的,但是遇到括号就不行了
2-(3+1)=?
如果遇到++和--之类的单目运算符也很麻烦:
2+++3=?
究竟是2+(++3),还是2++(+3)(事实上,这是C语言语法中的一个陷阱)?
假设你要开发一个编译器的前端,那么确定运算符的优先级和结合性绝对是要首先考虑的问题,或许你也可以不用栈而用树来储存操作符合操作数,树结构中的元素比较容易调整位置。
------- Windows Phone 7手机开发、.Net培训、期待与您交流! -------
- 黑马程序员-控制台下的连续四则计算器
- c++实现的一个控制台下的计算器
- 简单的四则计算器
- 控制台下的计算器——C++实现
- 控制台下的unicode
- 控制台下的万年历
- 控制台下的多线程
- 控制台下的定时器
- 控制台下的扫雷
- 四则计算器
- Linux控制台下的快捷键
- 控制台下菱形的代码
- win32控制台下的main
- Linux控制台下的快捷键
- windows 控制台下的时钟
- 控制台下的超级玛丽
- 设计一个简单的四则计算器
- mysql之控制台下的事务控制
- ERwin Data Modeler 建模实践
- stat函数遇到的错误
- (数组的应用二:高精度运算4.2.1)POJ 1504 Adding Reversed Numbers(将一个数取反)
- 屏幕增强的实现方法
- 矢量图不会让你忘记你是在他们
- 黑马程序员-控制台下的连续四则计算器
- WC bug
- Pro Android学习笔记(四三):Fragment(8):再谈Transaction和管理器
- 关于C#发送邮件模块
- POJ P1182 食物链
- APIsocket,VS2010,windows非阻塞模式异步套接字编程(看孙鑫视频有感)
- 并发 并行
- 拍好宝贝照片后,PS三秒抠出宝贝图片
- HTML 存储自定义对象