小言_互联网的博客

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

903人阅读  评论(0)

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

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

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

wybing最后编辑于20190510

截图:

运行截图:

界面控制代码:


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. namespace 计算器
  11. {
  12. public partial class FrmMain : Form
  13. {
  14. public static List<char> inputStr= new List< char>( 1000); //用户的输入
  15. public FrmMain()
  16. {
  17. InitializeComponent();
  18. }
  19. private void Btn0_Click(object sender, EventArgs e)
  20. {
  21. inputStr.Add( '0');
  22. textBox1.AppendText( "0");
  23. }
  24. private void BtnDot_Click(object sender, EventArgs e)
  25. {
  26. inputStr.Add( '.');
  27. textBox1.AppendText( ".");
  28. }
  29. private void Btn1_Click(object sender, EventArgs e)
  30. {
  31. inputStr.Add( '1');
  32. textBox1.AppendText( "1");
  33. }
  34. private void Btn2_Click(object sender, EventArgs e)
  35. {
  36. inputStr.Add( '2');
  37. textBox1.AppendText( "2");
  38. }
  39. private void Btn3_Click(object sender, EventArgs e)
  40. {
  41. inputStr.Add( '3');
  42. textBox1.AppendText( "3");
  43. }
  44. private void Btn4_Click(object sender, EventArgs e)
  45. {
  46. inputStr.Add( '4');
  47. textBox1.AppendText( "4");
  48. }
  49. private void Btn5_Click(object sender, EventArgs e)
  50. {
  51. inputStr.Add( '5');
  52. textBox1.AppendText( "5");
  53. }
  54. private void Btn6_Click(object sender, EventArgs e)
  55. {
  56. inputStr.Add( '6');
  57. textBox1.AppendText( "6");
  58. }
  59. private void Btn7_Click(object sender, EventArgs e)
  60. {
  61. inputStr.Add( '7');
  62. textBox1.AppendText( "7");
  63. }
  64. private void Btn8_Click(object sender, EventArgs e)
  65. {
  66. inputStr.Add( '8');
  67. textBox1.AppendText( "8");
  68. }
  69. private void Btn9_Click(object sender, EventArgs e)
  70. {
  71. inputStr.Add( '9');
  72. textBox1.AppendText( "9");
  73. }
  74. private void BtnLeft_Click(object sender, EventArgs e)
  75. {
  76. inputStr.Add( '(');
  77. textBox1.AppendText( "(");
  78. }
  79. private void BtnRig_Click(object sender, EventArgs e)
  80. {
  81. inputStr.Add( ')');
  82. textBox1.AppendText( ")");
  83. }
  84. private void BtnEqual_Click(object sender, EventArgs e)
  85. {
  86. //等号代码
  87. textBox1.AppendText( "=");
  88. textBox2.Text = textBox1.Text;
  89. textBox1.Text = DataOp.DataMain();
  90. string temp= DataOp.DataMain();
  91. inputStr.Clear();
  92. for( int i = 0; i < temp.Length; i++)
  93. {
  94. inputStr.Add(temp[i]);
  95. }
  96. }
  97. private void BtnAdd_Click(object sender, EventArgs e)
  98. {
  99. inputStr.Add( '+');
  100. textBox1.AppendText( "+");
  101. }
  102. private void BtnSubt_Click(object sender, EventArgs e)
  103. {
  104. inputStr.Add( '-');
  105. textBox1.AppendText( "-");
  106. }
  107. private void BtnMul_Click(object sender, EventArgs e)
  108. {
  109. inputStr.Add( '*');
  110. textBox1.AppendText( "*");
  111. }
  112. private void BtnDivi_Click(object sender, EventArgs e)
  113. {
  114. inputStr.Add( '/');
  115. textBox1.AppendText( "/");
  116. }
  117. private void BtnCe_Click(object sender, EventArgs e)
  118. {
  119. textBox1.Text = "";
  120. inputStr.Clear(); //清空链表的所有元素
  121. }
  122. private void BtnC_Click(object sender, EventArgs e)
  123. {
  124. //界面撤销
  125. inputStr.RemoveAt(inputStr.Count -1);
  126. textBox1.Text = "";
  127. for ( int i= 0;i<inputStr.Count;i++)
  128. {
  129. textBox1.Text += inputStr[i];
  130. }
  131. }
  132. }
  133. }

数据操作代码:


  
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. namespace 计算器
  7. {
  8. //表达式存在inputStr中
  9. class DataOp : FrmMain
  10. {
  11. static Stack<double> m = new Stack< double>(); //数字栈
  12. static Stack<char> s = new Stack< char>(); //符号栈
  13. public static void Read() //Read()从inputStr输入流中读值
  14. {
  15. for ( int i = 0; i < inputStr.Count; i++)
  16. {
  17. if (!IsOperator(inputStr[i])) //数字和小数点
  18. {
  19. string s = null;
  20. while (i < inputStr.Count && !IsOperator(inputStr[i]))
  21. {
  22. s += inputStr[i];
  23. i++;
  24. }
  25. i--;
  26. double mm = Convert.ToDouble(s);
  27. m.Push(mm);
  28. }
  29. else if (IsOper(inputStr[i])) //+ - * /
  30. {
  31. if (s.Count.Equals( 0) || s.Peek().Equals( '('))
  32. {
  33. s.Push(inputStr[i]);
  34. }
  35. else if (OperatorPrecedence(inputStr[i]) > OperatorPrecedence(s.Peek()))
  36. {
  37. s.Push(inputStr[i]);
  38. }
  39. else
  40. {
  41. double n1, n2;
  42. char s1;
  43. n2 = m.Pop();
  44. n1 = m.Pop();
  45. s1 = s.Pop();
  46. double sum = Operat(n1, n2, s1);
  47. m.Push(sum);
  48. s.Push(inputStr[i]);
  49. }
  50. }
  51. else //(和)
  52. {
  53. if (inputStr[i].Equals( '('))
  54. {
  55. s.Push(inputStr[i]);
  56. }
  57. else if (inputStr[i].Equals( ')'))
  58. {
  59. while (!s.Peek().Equals( '('))
  60. {
  61. double n1, n2;
  62. char s1;
  63. n2 = m.Pop();
  64. n1 = m.Pop();
  65. s1 = s.Pop();
  66. double sum = Operat(n1, n2, s1);
  67. m.Push(sum);
  68. }
  69. s.Pop();
  70. }
  71. }
  72. }
  73. }
  74. public static double PopStack()
  75. {
  76. double sum = 0;
  77. while (s.Count != 0)
  78. {
  79. double n1, n2;
  80. char s1;
  81. n2 = m.Pop();
  82. n1 = m.Pop();
  83. s1 = s.Pop();
  84. sum = Operat(n1, n2, s1);
  85. m.Push(sum);
  86. }
  87. return sum;
  88. }
  89. public static bool IsOperator(char c) //是否是操作符
  90. {
  91. if (c.Equals( '+') || c.Equals( '-') || c.Equals( '*') || c.Equals( '/') || c.Equals( '(') || c.Equals( ')'))
  92. return true;
  93. return false;
  94. }
  95. public static bool IsOper(char c) //是否是运算符符
  96. {
  97. if (c.Equals( '+') || c.Equals( '-') || c.Equals( '*') || c.Equals( '/'))
  98. return true;
  99. return false;
  100. }
  101. public static int OperatorPrecedence(char a) //操作符优先级
  102. {
  103. int i = 0;
  104. switch (a)
  105. {
  106. case '+': i = 3; break;
  107. case '-': i = 3; break;
  108. case '*': i = 4; break;
  109. case '/': i = 4; break;
  110. }
  111. return i;
  112. }
  113. public static double Operat(double n1, double n2, char s1)
  114. {
  115. double sum = 0;
  116. switch (s1)
  117. {
  118. case '+': sum = n1 + n2; break;
  119. case '-': sum = n1 - n2; break;
  120. case '*': sum = n1 * n2; break;
  121. case '/': sum = n1 / n2; break;
  122. }
  123. return sum;
  124. }
  125. public static string DataMain()
  126. {
  127. Read();
  128. return PopStack().ToString();
  129. }
  130. }
  131. }

程序源代码下载地址:https://wybing.lanzoui.com/is107ijyrha

【Bug修复】

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

20201119修改如下:


  
  1. public static double PopStack()
  2. {
  3. /*
  4. * 修复Bug 3*2-2*2+1结果为1
  5. * 将两个栈逆序后再运算
  6. */
  7. Stack< double> tepM = new Stack< double>(); //数字栈
  8. Stack< char> tepS = new Stack< char>(); //符号栈
  9. while (s.Count!= 0)
  10. {
  11. char temp;
  12. temp = s.Pop();
  13. tepS.Push(temp);
  14. }
  15. while (m.Count != 0)
  16. {
  17. double temp;
  18. temp = m.Pop();
  19. tepM.Push(temp);
  20. }
  21. double sum = 0;
  22. while (tepS.Count != 0)
  23. {
  24. double n1, n2;
  25. char s1;
  26. n2 = tepM.Pop();
  27. n1 = tepM.Pop();
  28. s1 = tepS.Pop();
  29. sum = Operat(n2, n1, s1);
  30. tepM.Push(sum);
  31. }
  32. return sum;
  33. }

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

 


转载:https://blog.csdn.net/qq_41138935/article/details/82750974
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场