c#实战 计算器(支持加减乘除括号的混合计算) 您所在的位置:网站首页 计算器的连加连减怎么用 c#实战 计算器(支持加减乘除括号的混合计算)

c#实战 计算器(支持加减乘除括号的混合计算)

2023-09-23 12:34| 来源: 网络整理| 查看: 265

c#计算器,支持+-*/()的混合运算,对负号不支持.

原理:将点击的按钮赋给inputStr,然后对inputStr分析、计算。看懂代码的重要前提是你有一定的算法基础(前缀、中缀、后缀表达式)和数据结构基础(链表、栈)。

当初写这份代码的时候还是小白,随着对C#的深入学习,个人觉得本文代码还有很多可以优化的地方。

wybing最后编辑于20190510

截图:

运行截图:

界面控制代码:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace 计算器 { public partial class FrmMain : Form { public static List inputStr=new List(1000); //用户的输入 public FrmMain() { InitializeComponent(); } private void Btn0_Click(object sender, EventArgs e) { inputStr.Add('0'); textBox1.AppendText("0"); } private void BtnDot_Click(object sender, EventArgs e) { inputStr.Add('.'); textBox1.AppendText("."); } private void Btn1_Click(object sender, EventArgs e) { inputStr.Add('1'); textBox1.AppendText("1"); } private void Btn2_Click(object sender, EventArgs e) { inputStr.Add('2'); textBox1.AppendText("2"); } private void Btn3_Click(object sender, EventArgs e) { inputStr.Add('3'); textBox1.AppendText("3"); } private void Btn4_Click(object sender, EventArgs e) { inputStr.Add('4'); textBox1.AppendText("4"); } private void Btn5_Click(object sender, EventArgs e) { inputStr.Add('5'); textBox1.AppendText("5"); } private void Btn6_Click(object sender, EventArgs e) { inputStr.Add('6'); textBox1.AppendText("6"); } private void Btn7_Click(object sender, EventArgs e) { inputStr.Add('7'); textBox1.AppendText("7"); } private void Btn8_Click(object sender, EventArgs e) { inputStr.Add('8'); textBox1.AppendText("8"); } private void Btn9_Click(object sender, EventArgs e) { inputStr.Add('9'); textBox1.AppendText("9"); } private void BtnLeft_Click(object sender, EventArgs e) { inputStr.Add('('); textBox1.AppendText("("); } private void BtnRig_Click(object sender, EventArgs e) { inputStr.Add(')'); textBox1.AppendText(")"); } private void BtnEqual_Click(object sender, EventArgs e) { //等号代码 textBox1.AppendText("="); textBox2.Text = textBox1.Text; textBox1.Text = DataOp.DataMain(); string temp= DataOp.DataMain(); inputStr.Clear(); for(int i = 0; i < temp.Length; i++) { inputStr.Add(temp[i]); } } private void BtnAdd_Click(object sender, EventArgs e) { inputStr.Add('+'); textBox1.AppendText("+"); } private void BtnSubt_Click(object sender, EventArgs e) { inputStr.Add('-'); textBox1.AppendText("-"); } private void BtnMul_Click(object sender, EventArgs e) { inputStr.Add('*'); textBox1.AppendText("*"); } private void BtnDivi_Click(object sender, EventArgs e) { inputStr.Add('/'); textBox1.AppendText("/"); } private void BtnCe_Click(object sender, EventArgs e) { textBox1.Text = ""; inputStr.Clear(); //清空链表的所有元素 } private void BtnC_Click(object sender, EventArgs e) { //界面撤销 inputStr.RemoveAt(inputStr.Count-1); textBox1.Text = ""; for (int i=0;i OperatorPrecedence(s.Peek())) { s.Push(inputStr[i]); } else { double n1, n2; char s1; n2 = m.Pop(); n1 = m.Pop(); s1 = s.Pop(); double sum = Operat(n1, n2, s1); m.Push(sum); s.Push(inputStr[i]); } } else //(和) { if (inputStr[i].Equals('(')) { s.Push(inputStr[i]); } else if (inputStr[i].Equals(')')) { while (!s.Peek().Equals('(')) { double n1, n2; char s1; n2 = m.Pop(); n1 = m.Pop(); s1 = s.Pop(); double sum = Operat(n1, n2, s1); m.Push(sum); } s.Pop(); } } } } public static double PopStack() { /* * 修复Bug 1+3-6*5结果为-10 * 逆序前,先将算式后的 * / 计算,剩下 + - 按照从前往后运算 */ while (OperatorPrecedence(s.Peek()) == 4) { double n1, n2; char s1; n2 = m.Pop(); n1 = m.Pop(); s1 = s.Pop(); double res = Operat(n1, n2, s1); m.Push(res); } /* * 修复Bug 3*2-2*2+1结果为1 * 将两个栈逆序后再运算 */ Stack tepM = new Stack();//数字栈 Stack tepS = new Stack();//符号栈 while (s.Count!=0) { char temp; temp = s.Pop(); tepS.Push(temp); } while (m.Count != 0) { double temp; temp = m.Pop(); tepM.Push(temp); } double sum = 0; while (tepS.Count != 0) { double n1, n2; char s1; n2 = tepM.Pop(); n1 = tepM.Pop(); s1 = tepS.Pop(); sum = Operat(n2, n1, s1); tepM.Push(sum); } return sum; } public static bool IsOperator(char c) //是否是操作符 { if (c.Equals('+') || c.Equals('-') || c.Equals('*') || c.Equals('/') || c.Equals('(') || c.Equals(')')) return true; return false; } public static bool IsOper(char c) //是否是运算符符 { if (c.Equals('+') || c.Equals('-') || c.Equals('*') || c.Equals('/')) return true; return false; } public static int OperatorPrecedence(char a) //操作符优先级 { int i = 0; switch (a) { case '+': i = 3; break; case '-': i = 3; break; case '*': i = 4; break; case '/': i = 4; break; } return i; } public static double Operat(double n1, double n2, char s1) { double sum = 0; switch (s1) { case '+': sum = n1 + n2; break; case '-': sum = n1 - n2; break; case '*': sum = n1 * n2; break; case '/': sum = n1 / n2; break; } return sum; } public static string DataMain() { Read(); return PopStack().ToString(); } } }

程序源代码下载地址:计算器.zip - 蓝奏云

【Bug修复】

感谢Xuuuton反馈的Bug,3*2-2*2+1出来的答案是1 。

20201119修改如下:

public static double PopStack() { /* * 修复Bug 3*2-2*2+1结果为1 * 将两个栈逆序后再运算 */ Stack tepM = new Stack();//数字栈 Stack tepS = new Stack();//符号栈 while (s.Count!=0) { char temp; temp = s.Pop(); tepS.Push(temp); } while (m.Count != 0) { double temp; temp = m.Pop(); tepM.Push(temp); } double sum = 0; while (tepS.Count != 0) { double n1, n2; char s1; n2 = tepM.Pop(); n1 = tepM.Pop(); s1 = tepS.Pop(); sum = Operat(n2, n1, s1); tepM.Push(sum); } return sum; }

【Bug修复】

感谢杏子小姐很忙反馈的Bug,1+3-6*5结果为-10。

修改代码如下:

逆序前,先将算式后的  * /  计算,剩下 + - 按照从前往后运算

while (OperatorPrecedence(s.Peek()) == 4) { double n1, n2; char s1; n2 = m.Pop(); n1 = m.Pop(); s1 = s.Pop(); double res = Operat(n1, n2, s1); m.Push(res); }

关于非法表达式导致的程序异常,可以做异常处理,也可以简单判断数字栈和符号栈的Count,很显然,数字栈至少要两位以上数字,符号栈至少要一位以上,但前提要确保栈内操作数和操作符合法。

发现一个计算器的封装类,来自System.IO.Ports的博客。

此类不涉及数据结构,采用分治和递归的思想,将表达式的处理分为 处理括号[CalcBrackets()]、处理数字[GetANumber()]、处理运算[StrCalc()] 三步,把一个表达式计算问题分为若干个计算子项,通过递归完成子项问题的计算也就完成了整个问题的计算。代码如下:  

public class CalcHelper { public double CalcBrackets(ref string str) { char[] array = str.ToArray(); string tex = str; int count = 1; int endIndex = 0; for (int i = 1; i < array.Length; i++) { if (array[i] == '(') count++; if (array[i] == ')') count--; if (count == 0) { endIndex = i; break; } } tex = tex.Substring(1, endIndex - 1); str = str.Substring(endIndex + 1); var result = StrCalc(0, ref tex); return result; } public double GetANumber(ref string str) { char first = str.First(); if (first == '(') { double result = 0; result = CalcBrackets(ref str); return result; } char[] array = str.ToArray(); int end = 0; int point = -1; for (int i = 0; i < array.Length; i++) { if ((array[i] < 0x30 || array[i] > 0x39) && array[i] != 0x2E) { end = i; break; } if (array[i] == 0x2E) { point = i; } end++; } double Value = 0; Value += array[0] - 0x30; if (point >= 0) { for (int i = 1; i < point; i++) Value = Value * 10 + (array[i] - 0x30); double except = 10.0; for (int i = point + 1; i < end; i++) { Value += (array[i] - 0x30) / except; except *= 10; } } else { for (int i = 1; i < end; i++) Value = Value * 10 + (array[i] - 0x30); } str = str.Substring(end); return Value; } public double StrCalc(double A, ref string str) { if (str.Length == 0) return A; char first = str.First(); double result = 0; if (first >= 0x30 && first


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有