C# 简易计算器
编写如下界面的简易计算器界面代码:
using System; using System.Windows.Forms; using exp; namespace calculator { public partial class Form1 : Form { public Form1() { InitializeComponent(); } enum symbol { plus,dec,mult,div}; private void button1_Click(object sender, EventArgs e) { Button currentButton = sender as Button; if(currentButton!= null) { textBox1.Text += currentButton.Text; } } private void equal_Click(object sender, EventArgs e) { //string text = textBox1.Text; // string[] value = text.Split(new char[4] { '+','-','x','/'}); //foreach (string i in value) MessageBox.Show(i); //com.change(); compute cs = new compute(textBox1.Text); cs.PostFix(); textBox1.Text=cs.scanpost().ToString(); } private void clear_Click(object sender, EventArgs e) { textBox1.Text = ""; } } }
功能实现:(创建computeexp类文件)
思路:数字以及运算符按钮共享一个点击事件,则文本框里的字符串为中缀表达式,将中缀表达式求值返回值到文本框即可。
在computeexp类中初始化操作符栈stack等,然后编写方法转化为后缀表达式,然后对后缀表达式求值
转化为后缀表达式string:
扫描中缀表达式,对于多位数字依次添加到string中,并在每个数字结束后添加空格作为数字的分界,对于操作符按照其优先级判断是否添加到stack或string中,注意括号()不出现在后缀表达式内。
优先级高的要先计算,所以运算符stack栈顶元素的优先级最高,因为要先pop出来先进行计算
后缀求值:
扫描后缀表达式,处理字符型数字为demical类型,进操作数栈,遇到运算符,从操作数栈中弹出两个数运算,计算结果再次push操作数栈,直至扫描结束,同时操作数栈顶即为最后结果
问题:对于dowhile()循环条件的编写不清楚
1.do while 先执行一次在判断循环条件是否成立,成立继续执行,不成立跳出循环
2.注意:在进行按照string位数扫描时,如果是多位数字,如何让下一次遍历的位数正确,不出现没有扫描到操作符的问题,导致后缀表达式多个数字分 界符导致错误
功能实现代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace exp { class compute { private string exp; private string postexp; private Stack<char> oper=new Stack<char>(); private Stack<decimal> opernum=new Stack<decimal>(); public compute() { exp = "((34.51+5x2)+3)/5+6/4x2+3"; exp += '#'; postexp = ""; oper.Push('#'); } public int prority(char c) { if (c == 'x' || c == '/') return 3; if (c == '+' || c == '-') return 2; // if (c == ')') return 0; if (c == '(') return 1;//遇到(直接入栈 if (c == '#') return 0; return -1; } public void PostFix() { int i = 0; while(i<exp.Length) { if (exp[i]=='#') { while(true) { if (oper.Peek() == '#') break; char tem = oper.Peek(); postexp += tem; oper.Pop(); } } else { if (exp[i] >= '0' && exp[i] <= '9') {//若为操作数 postexp += exp[i]; //加上小数点和多位数 while (exp[i + 1] >= '0' && exp[i + 1] <= '9') { i++; postexp += exp[i]; } postexp += ' '; } else {//若为其他符号 switch (exp[i]) { case '(': oper.Push(exp[i]); break; case ')': while (true) { if (oper.Peek() == '(') break; char cur = oper.Peek(); postexp += cur; oper.Pop(); } oper.Pop(); break; case '.': postexp = postexp.Substring(0,postexp.Length-1);//截取字符串 postexp += '.';break; default: if (prority(oper.Peek()) < prority(exp[i])) oper.Push(exp[i]); else { while (true) { if (prority(exp[i]) > prority(oper.Peek())) break; char tem = oper.Peek(); postexp += tem; oper.Pop(); } oper.Push(exp[i]); } break; }//switch }//numelse }//#else i++; }//while }//函数 public void show() { Console.WriteLine(exp); Console.WriteLine(postexp); } public decimal computepost(char c) { decimal first, second,res=0; second = opernum.Pop();//第二操作数 first = opernum.Pop();//第一操作数 if (c == '+') res = first + second; if (c == '-') res = first - second; if (c == 'x') res = first * second; if (c == '/') res = first / second; return res; } public decimal scanpost() { int i = 0; while (i <= postexp.Length - 1) { if(postexp[i]>='0'&&postexp[i]<='9') {//读到操作数 decimal num = 0; string nu =""; nu += postexp[i]; while(postexp[i+1]!=' ') { i++; nu += postexp[i]; } num = Convert.ToDecimal(nu); opernum.Push(num); } else if(postexp[i]!=' ') {//读到操作符或空格 opernum.Push(computepost(postexp[i])); } i++; } Console.WriteLine("result="+opernum.Peek()); return oper.Peek(); } } }