一、前言
Hello,又见面了,今天分享如何使用Unity制作计算器,难度中等,可以用来学习,或者当成其他项目的小组件导入。
当然,也可以导出来,发布到网页端,来做一个嵌入式工具也可以。
二、效果图及源工程
效果图:
源工程: https://wwr.lanzoui.com/iHOuzpo4lti
三、实现
3-1 界面搭建
所有的按钮摆放到Background下面。
3-2 代码实现
首先找到所有的按钮,添加到事件:
代码语言:javascript
复制
//结果显示 TextComputeProcess = GameObject.Find("Canvas/Background/Image/TextComputeProcess").GetComponent<Text>(); TextComputeResult = GameObject.Find("Canvas/Background/Image/TextComputeResult").GetComponent<Text>(); TextComputeResult.text = "0"; RUNSTATE = 0;
//操作 BtnReset = GameObject.Find("Canvas/Background/重置").GetComponent<Button>(); BtnReset.onClick.AddListener(() => OperationDispose("CE")); BtnDelete = GameObject.Find("Canvas/Background/删除").GetComponent<Button>(); BtnDelete.onClick.AddListener(() => OperationDispose("Del")); //加减乘除 BtnAdd = GameObject.Find("Canvas/Background/加").GetComponent<Button>(); BtnAdd.onClick.AddListener(() => OperationDispose("+")); BtnSub = GameObject.Find("Canvas/Background/减").GetComponent<Button>(); BtnSub.onClick.AddListener(() => OperationDispose("-")); BtnMul = GameObject.Find("Canvas/Background/乘").GetComponent<Button>(); BtnMul.onClick.AddListener(() => OperationDispose("*")); BtnDiv = GameObject.Find("Canvas/Background/除").GetComponent<Button>(); BtnDiv.onClick.AddListener(() => OperationDispose("/")); BtnEqual = GameObject.Find("Canvas/Background/等于").GetComponent<Button>(); BtnEqual.onClick.AddListener(() => OperationDispose("=")); //数字 Btn0 = GameObject.Find("Canvas/Background/0").GetComponent<Button>(); Btn0.onClick.AddListener(() => NumDispose("0")); Btn1 = GameObject.Find("Canvas/Background/1").GetComponent<Button>(); Btn1.onClick.AddListener(() => NumDispose("1")); Btn2 = GameObject.Find("Canvas/Background/2").GetComponent<Button>(); Btn2.onClick.AddListener(() => NumDispose("2")); Btn3 = GameObject.Find("Canvas/Background/3").GetComponent<Button>(); Btn3.onClick.AddListener(() => NumDispose("3")); Btn4 = GameObject.Find("Canvas/Background/4").GetComponent<Button>(); Btn4.onClick.AddListener(() => NumDispose("4")); Btn5 = GameObject.Find("Canvas/Background/5").GetComponent<Button>(); Btn5.onClick.AddListener(() => NumDispose("5")); Btn6 = GameObject.Find("Canvas/Background/6").GetComponent<Button>(); Btn6.onClick.AddListener(() => NumDispose("6")); Btn7 = GameObject.Find("Canvas/Background/7").GetComponent<Button>(); Btn7.onClick.AddListener(() => NumDispose("7")); Btn8 = GameObject.Find("Canvas/Background/8").GetComponent<Button>(); Btn8.onClick.AddListener(() => NumDispose("8")); Btn9 = GameObject.Find("Canvas/Background/9").GetComponent<Button>(); Btn9.onClick.AddListener(() => NumDispose("9")); BtnPoint = GameObject.Find("Canvas/Background/点").GetComponent<Button>(); BtnPoint.onClick.AddListener(() => NumDispose(".")); BtnPm = GameObject.Find("Canvas/Background/正负").GetComponent<Button>(); BtnPm.onClick.AddListener(() => NumDispose("-"));</code></pre></div></div><p>按钮操作:</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"> //操作点击处理 private void OperationDispose(string operation) { switch (operation) { case "+": if (RUNSTATE == 0) TextComputeProcess.text = "0 + "; else { TextComputeProcess.text = TextComputeResult.text + " + "; m_operation = "+"; RUNSTATE = 2; } break; case "-": if (RUNSTATE == 0) TextComputeProcess.text = "0 - "; else { TextComputeProcess.text = TextComputeResult.text + " - "; m_operation = "-"; RUNSTATE = 2; } break; case "*": if (RUNSTATE == 0) TextComputeProcess.text = "0 * "; else { TextComputeProcess.text = TextComputeResult.text + " * "; m_operation = "*"; RUNSTATE = 2; } break; case "/": if (RUNSTATE == 0) TextComputeProcess.text = "0 / "; else { TextComputeProcess.text = TextComputeResult.text + " / "; m_operation = "/"; RUNSTATE = 2; } break; case "=": if (RUNSTATE == 0) TextComputeProcess.text = "0 = "; else { if (RUNSTATE == 3) { double result; switch (m_operation) { case "+": result = double.Parse(calculateString) + double.Parse(TextComputeResult.text); TextComputeProcess.text = calculateString + " + " + TextComputeResult.text + " = "; TextComputeResult.text = result.ToString(); RUNSTATE = 4; break; case "-": result = double.Parse(calculateString) - double.Parse(TextComputeResult.text); TextComputeProcess.text = calculateString + " - " + TextComputeResult.text + " = "; TextComputeResult.text = result.ToString(); RUNSTATE = 4; break; case "*": result = double.Parse(calculateString) * double.Parse(TextComputeResult.text); TextComputeProcess.text = calculateString + " * " + TextComputeResult.text + " = "; TextComputeResult.text = result.ToString(); RUNSTATE = 4; break; case "/": result = double.Parse(calculateString) / double.Parse(TextComputeResult.text); TextComputeProcess.text = calculateString + " / " + TextComputeResult.text + " = "; TextComputeResult.text = result.ToString(); RUNSTATE = 4; break; default: break; } } else { TextComputeProcess.text = TextComputeResult.text + " = "; } } break; case "CE": TextComputeProcess.text = ""; TextComputeResult.text = "0"; RUNSTATE = 0; break; case "Del": if (RUNSTATE == 0) return; else { if (TextComputeResult.text.Length == 1) { TextComputeResult.text = "0"; } else { TextComputeResult.text = TextComputeResult.text.Remove(TextComputeResult.text.Length - 1, 1); } } break; default: break; } }</code></pre></div></div><p>数字点击处理:</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"> //数字点击处理 private void NumDispose(string num) { switch (num) { case ".": if (RUNSTATE == 0) TextComputeResult.text = "0"; else TextComputeResult.text += num; break; case "-": if (RUNSTATE == 0) TextComputeResult.text = "0"; else { if (RUNSTATE == 1) { if (pmState) { TextComputeResult.text = TextComputeResult.text.Remove(0, 1); pmState = false; } else { TextComputeResult.text = num + TextComputeResult.text; pmState = true; } } else if (RUNSTATE == 2) { pmState = false; } else if (RUNSTATE == 3) { if (pmState) { TextComputeResult.text = TextComputeResult.text.Remove(0, 1); pmState = false; } else { TextComputeResult.text = num + TextComputeResult.text; pmState = true; } } else if (RUNSTATE == 4) { pmState = false; OperationDispose("CE"); } } break; default: if (RUNSTATE == 0) { TextComputeResult.text = num; RUNSTATE = 1; } else if (RUNSTATE == 1) { pmState = false; TextComputeResult.text += num; } else if (RUNSTATE == 2) { calculateString = TextComputeResult.text; TextComputeResult.text = ""; TextComputeResult.text += num; RUNSTATE = 3; } else if (RUNSTATE == 3) { TextComputeResult.text += num; } else if (RUNSTATE == 4) { OperationDispose("CE"); TextComputeResult.text = num; RUNSTATE = 1; } break; } }</code></pre></div></div><p>完整代码:</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class CalculatorControl : MonoBehaviour
{
private Text TextComputeProcess;//计算过程
private Text TextComputeResult;//计算结果private Button BtnReset; private Button BtnDelete; private Button BtnAdd; private Button BtnSub; private Button BtnMul; private Button BtnDiv; private Button BtnEqual; private Button Btn0, Btn1, Btn2, Btn3, Btn4, Btn5, Btn6, Btn7, Btn8, Btn9; private Button BtnPoint, BtnPm; private string calculateString = "";//计算数 private string m_operation = "";//操作数 private bool pmState = false;//正负状态 private int RUNSTATE = 0;//0 默认 1 输入数字 2 输入操作符 3 输入操作符再输入数字 4 计算结果后 void Start() { //结果显示 TextComputeProcess = GameObject.Find("Canvas/Background/Image/TextComputeProcess").GetComponent<Text>(); TextComputeResult = GameObject.Find("Canvas/Background/Image/TextComputeResult").GetComponent<Text>(); TextComputeResult.text = "0"; RUNSTATE = 0; //操作 BtnReset = GameObject.Find("Canvas/Background/重置").GetComponent<Button>(); BtnReset.onClick.AddListener(() => OperationDispose("CE")); BtnDelete = GameObject.Find("Canvas/Background/删除").GetComponent<Button>(); BtnDelete.onClick.AddListener(() => OperationDispose("Del")); //加减乘除 BtnAdd = GameObject.Find("Canvas/Background/加").GetComponent<Button>(); BtnAdd.onClick.AddListener(() => OperationDispose("+")); BtnSub = GameObject.Find("Canvas/Background/减").GetComponent<Button>(); BtnSub.onClick.AddListener(() => OperationDispose("-")); BtnMul = GameObject.Find("Canvas/Background/乘").GetComponent<Button>(); BtnMul.onClick.AddListener(() => OperationDispose("*")); BtnDiv = GameObject.Find("Canvas/Background/除").GetComponent<Button>(); BtnDiv.onClick.AddListener(() => OperationDispose("/")); BtnEqual = GameObject.Find("Canvas/Background/等于").GetComponent<Button>(); BtnEqual.onClick.AddListener(() => OperationDispose("=")); //数字 Btn0 = GameObject.Find("Canvas/Background/0").GetComponent<Button>(); Btn0.onClick.AddListener(() => NumDispose("0")); Btn1 = GameObject.Find("Canvas/Background/1").GetComponent<Button>(); Btn1.onClick.AddListener(() => NumDispose("1")); Btn2 = GameObject.Find("Canvas/Background/2").GetComponent<Button>(); Btn2.onClick.AddListener(() => NumDispose("2")); Btn3 = GameObject.Find("Canvas/Background/3").GetComponent<Button>(); Btn3.onClick.AddListener(() => NumDispose("3")); Btn4 = GameObject.Find("Canvas/Background/4").GetComponent<Button>(); Btn4.onClick.AddListener(() => NumDispose("4")); Btn5 = GameObject.Find("Canvas/Background/5").GetComponent<Button>(); Btn5.onClick.AddListener(() => NumDispose("5")); Btn6 = GameObject.Find("Canvas/Background/6").GetComponent<Button>(); Btn6.onClick.AddListener(() => NumDispose("6")); Btn7 = GameObject.Find("Canvas/Background/7").GetComponent<Button>(); Btn7.onClick.AddListener(() => NumDispose("7")); Btn8 = GameObject.Find("Canvas/Background/8").GetComponent<Button>(); Btn8.onClick.AddListener(() => NumDispose("8")); Btn9 = GameObject.Find("Canvas/Background/9").GetComponent<Button>(); Btn9.onClick.AddListener(() => NumDispose("9")); BtnPoint = GameObject.Find("Canvas/Background/点").GetComponent<Button>(); BtnPoint.onClick.AddListener(() => NumDispose(".")); BtnPm = GameObject.Find("Canvas/Background/正负").GetComponent<Button>(); BtnPm.onClick.AddListener(() => NumDispose("-")); } //操作点击处理 private void OperationDispose(string operation) { switch (operation) { case "+": if (RUNSTATE == 0) TextComputeProcess.text = "0 + "; else { TextComputeProcess.text = TextComputeResult.text + " + "; m_operation = "+"; RUNSTATE = 2; } break; case "-": if (RUNSTATE == 0) TextComputeProcess.text = "0 - "; else { TextComputeProcess.text = TextComputeResult.text + " - "; m_operation = "-"; RUNSTATE = 2; } break; case "*": if (RUNSTATE == 0) TextComputeProcess.text = "0 * "; else { TextComputeProcess.text = TextComputeResult.text + " * "; m_operation = "*"; RUNSTATE = 2; } break; case "/": if (RUNSTATE == 0) TextComputeProcess.text = "0 / "; else { TextComputeProcess.text = TextComputeResult.text + " / "; m_operation = "/"; RUNSTATE = 2; } break; case "=": if (RUNSTATE == 0) TextComputeProcess.text = "0 = "; else { if (RUNSTATE == 3) { double result; switch (m_operation) { case "+": result = double.Parse(calculateString) + double.Parse(TextComputeResult.text); TextComputeProcess.text = calculateString + " + " + TextComputeResult.text + " = "; TextComputeResult.text = result.ToString(); RUNSTATE = 4; break; case "-": result = double.Parse(calculateString) - double.Parse(TextComputeResult.text); TextComputeProcess.text = calculateString + " - " + TextComputeResult.text + " = "; TextComputeResult.text = result.ToString(); RUNSTATE = 4; break; case "*": result = double.Parse(calculateString) * double.Parse(TextComputeResult.text); TextComputeProcess.text = calculateString + " * " + TextComputeResult.text + " = "; TextComputeResult.text = result.ToString(); RUNSTATE = 4; break; case "/": result = double.Parse(calculateString) / double.Parse(TextComputeResult.text); TextComputeProcess.text = calculateString + " / " + TextComputeResult.text + " = "; TextComputeResult.text = result.ToString(); RUNSTATE = 4; break; default: break; } } else { TextComputeProcess.text = TextComputeResult.text + " = "; } } break; case "CE": TextComputeProcess.text = ""; TextComputeResult.text = "0"; RUNSTATE = 0; break; case "Del": if (RUNSTATE == 0) return; else { if (TextComputeResult.text.Length == 1) { TextComputeResult.text = "0"; } else { TextComputeResult.text = TextComputeResult.text.Remove(TextComputeResult.text.Length - 1, 1); } } break; default: break; } } //数字点击处理 private void NumDispose(string num) { switch (num) { case ".": if (RUNSTATE == 0) TextComputeResult.text = "0"; else TextComputeResult.text += num; break; case "-": if (RUNSTATE == 0) TextComputeResult.text = "0"; else { if (RUNSTATE == 1) { if (pmState) { TextComputeResult.text = TextComputeResult.text.Remove(0, 1); pmState = false; } else { TextComputeResult.text = num + TextComputeResult.text; pmState = true; } } else if (RUNSTATE == 2) { pmState = false; } else if (RUNSTATE == 3) { if (pmState) { TextComputeResult.text = TextComputeResult.text.Remove(0, 1); pmState = false; } else { TextComputeResult.text = num + TextComputeResult.text; pmState = true; } } else if (RUNSTATE == 4) { pmState = false; OperationDispose("CE"); } } break; default: if (RUNSTATE == 0) { TextComputeResult.text = num; RUNSTATE = 1; } else if (RUNSTATE == 1) { pmState = false; TextComputeResult.text += num; } else if (RUNSTATE == 2) { calculateString = TextComputeResult.text; TextComputeResult.text = ""; TextComputeResult.text += num; RUNSTATE = 3; } else if (RUNSTATE == 3) { TextComputeResult.text += num; } else if (RUNSTATE == 4) { OperationDispose("CE"); TextComputeResult.text = num; RUNSTATE = 1; } break; } }
}
效果图如下:
四、后记
完整代码278行,还是依旧那么简练,整体代码难度不大,主要是状态之间的切换: 1、输入数字的状态 2、输入操作符状态 3、输入操作符后再输入数字状态 4、计算结果后状态
理解这些状态后,代码就容易理解了。
最后,拓展一下,将其他大佬写的代码给大家看一下,大家如果觉得上面的代码太简单,可以看一下:
代码使用OnGUI搭建界面,直接拖到任意对象上就可以看到效果了:
代码语言:javascript
复制
using UnityEngine;
using System.Text.RegularExpressions;
using System;public class Calculator2 : MonoBehaviour
{
public static bool IsNumeric(string value)
{
return Regex.IsMatch(value, @"^[+-]?\d*[.]?\d*$");
}public string result = "";//用来显示结果 public static string str1 = "";//第一个操作数 public static bool haveDot = false;//第二个操作数 public static bool isCaclutate = false; void OnGUI() { //对数字进行处理 if (GUI.Button(new Rect(100, 100, 100, 60), "CE")) { result = ""; str1 = ""; haveDot = false; } if (GUI.Button(new Rect(210, 100, 100, 60), "×") &amp;&amp; str1.Substring(str1.Length - 1, 1) != "-" &amp;&amp; str1.Substring(str1.Length - 1, 1) != "+" &amp;&amp; str1.Substring(str1.Length - 1, 1) != ".") { if (IsNumeric(str1.Substring(str1.Length - 1, 1))) { Debug.Log(str1.Substring(str1.Length - 1, 1)); str1 += "*"; haveDot = false; isCaclutate = false; } result = str1; } if (GUI.Button(new Rect(320, 100, 100, 60), "÷") &amp;&amp; str1.Substring(str1.Length - 1, 1) != "-" &amp;&amp; str1.Substring(str1.Length - 1, 1) != "+" &amp;&amp; str1.Substring(str1.Length - 1, 1) != ".") { if (IsNumeric(str1.Substring(str1.Length - 1, 1))) { str1 += "/"; haveDot = false; isCaclutate = false; } result = str1; } if (GUI.Button(new Rect(430, 100, 100, 60), "←")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; } else if (result.Length != 0) { str1 = str1.Substring(0, str1.Length - 1); } result = str1; } if (GUI.Button(new Rect(100, 170, 100, 60), "1")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "1"; result = str1; } if (GUI.Button(new Rect(210, 170, 100, 60), "2")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "2"; result = str1; } if (GUI.Button(new Rect(320, 170, 100, 60), "3")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "3"; result = str1; } if (GUI.Button(new Rect(430, 170, 100, 60), "-")) { if (IsNumeric(str1.Substring(str1.Length - 1, 1)) &amp;&amp; str1.Substring(str1.Length - 1, 1) != "-" &amp;&amp; str1.Substring(str1.Length - 1, 1) != "+" &amp;&amp; str1.Substring(str1.Length - 1, 1) != ".") { str1 += "-"; haveDot = false; isCaclutate = false; } result = str1; } if (GUI.Button(new Rect(100, 240, 100, 60), "4")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "4"; result = str1; } if (GUI.Button(new Rect(210, 240, 100, 60), "5")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "5"; result = str1; } if (GUI.Button(new Rect(320, 240, 100, 60), "6")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "6"; result = str1; } if (GUI.Button(new Rect(430, 240, 100, 60), "+") &amp;&amp; str1.Substring(str1.Length - 1, 1) != "+" &amp;&amp; str1.Substring(str1.Length - 1, 1) != "-" &amp;&amp; str1.Substring(str1.Length - 1, 1) != ".") { if (IsNumeric(str1.Substring(str1.Length - 1, 1))) { str1 += "+"; haveDot = false; isCaclutate = false; } result = str1; } if (GUI.Button(new Rect(100, 310, 100, 60), "7")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "7"; result = str1; } if (GUI.Button(new Rect(210, 310, 100, 60), "8")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "8"; result = str1; } if (GUI.Button(new Rect(320, 310, 100, 60), "9")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "9"; result = str1; } if (GUI.Button(new Rect(430, 310, 100, 130), "=")) { var tmp = Evaluator.Eval(result); Debug.Log(tmp.ToString()); result = tmp.ToString(); str1 = result; isCaclutate = true; if (result.Contains(".")) { haveDot = true; } } if (GUI.Button(new Rect(100, 380, 210, 60), "0")) { if (isCaclutate == true) { str1 = ""; isCaclutate = false; haveDot = false; } str1 += "0"; result = str1; } if (GUI.Button(new Rect(320, 380, 100, 60), ".")) { if (isCaclutate == true) { str1 = "0."; isCaclutate = false; } if (IsNumeric(str1.Substring(str1.Length - 1, 1)) &amp;&amp; str1.Substring(str1.Length - 1, 1) != "." &amp;&amp; haveDot == false) { Debug.Log(str1.Substring(str1.Length - 1, 1)); str1 += "."; haveDot = true; isCaclutate = false; } result = str1; } GUI.TextArea(new Rect(100, 20, 430, 60), result); } /**/ /// <summary> /// 动态求值 /// </summary> public class Evaluator { /**/ /// <summary> /// 计算结果,如果表达式出错则抛出异常 /// </summary> /// <param name="statement">表达式,如"1+2+3+4"</param> /// <returns>结果</returns> public static object Eval(string statement) { if (statement.Trim() != string.Empty) { Evaluator evaluator = new Evaluator(); return evaluator.GetFormulaResult(statement); } else { return null; } } private object GetFormulaResult(string s) { if (s == "") { return null; } string S = BuildingRPN(s); string tmp = ""; System.Collections.Stack sk = new System.Collections.Stack(); char c = ' '; System.Text.StringBuilder Operand = new System.Text.StringBuilder(); double x, y; for (int i = 0; i < S.Length; i++) { c = S[i]; //added c==',' for germany culture if (char.IsDigit(c) || c == '.' || c == ',') { //数据值收集. Operand.Append(c); } else if (c == ' ' &amp;&amp; Operand.Length > 0) { #region 运算数转换 try { tmp = Operand.ToString(); if (tmp.StartsWith("-"))//负数的转换一定要小心...它不被直接支持. { //现在我的算法里这个分支可能永远不会被执行. sk.Push(-((double)Convert.ToDouble(tmp.Substring(1, tmp.Length - 1)))); } else { sk.Push(Convert.ToDouble(tmp)); } } catch { return null; // } Operand = new System.Text.StringBuilder(); #endregion } else if (c == '+'//运算符处理.双目运算处理. || c == '-' || c == '*' || c == '/' || c == '%' || c == '^') { #region 双目运算 if (sk.Count > 0)/*如果输入的表达式根本没有包含运算符.或是根本就是空串.这里的逻辑就有意义了.*/ { y = (double)sk.Pop(); } else { sk.Push(0); break; } if (sk.Count > 0) x = (double)sk.Pop(); else { sk.Push(y); break; } switch (c) { case '+': sk.Push(x + y); break; case '-': sk.Push(x - y); break; case '*': if (y == 0) { sk.Push(x * 1); } else { sk.Push(x * y); } break; case '/': if (y == 0) { sk.Push(x / 0); } else { sk.Push(x / y); } break; case '%': sk.Push(x % y); break; case '^':// if (x > 0)// { //我原本还想,如果被计算的数是负数,又要开真分数次方时如何处理的问题.后来我想还是算了吧. sk.Push(System.Math.Pow(x, y)); // } // else// { // double t = y; // string ts = ""; // t = 1 / (2 * t); // ts = t.ToString(); // if (ts.ToUpper().LastIndexOf('E') > 0)// { // ; // } // } break; } #endregion } else if (c == '!')//单目取反. ) { sk.Push(-((double)sk.Pop())); } } if (sk.Count > 1) { return null;//; } if (sk.Count == 0) { return null;//; } return sk.Pop(); } /**/ /// <summary> /// /// </summary> private string BuildingRPN(string s) { System.Text.StringBuilder sb = new System.Text.StringBuilder(s); System.Collections.Stack sk = new System.Collections.Stack(); System.Text.StringBuilder re = new System.Text.StringBuilder(); char c = ' '; //sb.Replace( " ","" ); //一开始,我只去掉了空格.后来我不想不支持函数和常量能滤掉的全OUT掉. for (int i = 0; i < sb.Length; i++) { c = sb[i]; //added c==',' for german culture if (char.IsDigit(c) || c == ',')//数字当然要了. re.Append(c); //if( char.IsWhiteSpace( c )|| char.IsLetter(c);//如果是空白,那么不要.现在字母也不要. //continue; switch (c)//如果是其它字符...列出的要,没有列出的不要. { case '+': case '-': case '*': case '/': case '%': case '^': case '!': case '(': case ')': case '.': re.Append(c); break; default: continue; } } sb = new System.Text.StringBuilder(re.ToString()); #region 对负号进行预转义处理.负号变单目运算符求反. for (int i = 0; i < sb.Length - 1; i++) if (sb[i] == '-' &amp;&amp; (i == 0 || sb[i - 1] == '(')) sb[i] = '!'; //字符转义. #endregion #region 将中缀表达式变为后缀表达式. re = new System.Text.StringBuilder(); for (int i = 0; i < sb.Length; i++) { if (char.IsDigit(sb[i]) || sb[i] == '.')//如果是数值. { re.Append(sb[i]); //加入后缀式 } else if (sb[i] == '+' || sb[i] == '-' || sb[i] == '*' || sb[i] == '/' || sb[i] == '%' || sb[i] == '^' || sb[i] == '!')//. { #region 运算符处理 while (sk.Count > 0) //栈不为空时 { c = (char)sk.Pop(); //将栈中的操作符弹出. if (c == '(') //如果发现左括号.停. { sk.Push(c); //将弹出的左括号压回.因为还有右括号要和它匹配. break; //中断. } else { if (Power(c) < Power(sb[i]))//如果优先级比上次的高,则压栈. { sk.Push(c); break; } else { re.Append(' '); re.Append(c); } //如果不是左括号,那么将操作符加入后缀式中. } } sk.Push(sb[i]); //把新操作符入栈. re.Append(' '); #endregion } else if (sb[i] == '(')//基本优先级提升 { sk.Push('('); re.Append(' '); } else if (sb[i] == ')')//基本优先级下调 { while (sk.Count > 0) //栈不为空时 { c = (char)sk.Pop(); //pop Operator if (c != '(') { re.Append(' '); re.Append(c); //加入空格主要是为了防止不相干的数据相临产生解析错误. re.Append(' '); } else break; } } else re.Append(sb[i]); } while (sk.Count > 0)//这是最后一个弹栈啦. { re.Append(' '); re.Append(sk.Pop()); } #endregion re.Append(' '); return FormatSpace(re.ToString()); //在这里进行一次表达式格式化.这里就是后缀式了. } /// <summary> /// 优先级别测试函数. /// </summary> /// <param name="opr"></param> /// <returns></returns> private static int Power(char opr) { switch (opr) { case '+': case '-': return 1; case '*': case '/': return 2; case '%': case '^': case '!': return 3; default: return 0; } } /// <summary> /// 规范化逆波兰表达式. /// </summary> /// <param name="s"></param> /// <returns></returns> private static string FormatSpace(string s) { System.Text.StringBuilder ret = new System.Text.StringBuilder(); for (int i = 0; i < s.Length; i++) { if (!(s.Length > i + 1 &amp;&amp; s[i] == ' ' &amp;&amp; s[i + 1] == ' ')) ret.Append(s[i]); else ret.Append(s[i]); } return ret.ToString(); //.Replace( '!','-' ); } }
}