知识点:
1.System.Math.Pow() 实现乘方
2.实现计算器的运算优先级,依次调用的流程
问题:
还未实现“()”功能
解决方案
UI:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 9 namespace CaculationTest 10 { 11 public partial class Form1 : Form 12 { 13 public Form1() 14 { 15 InitializeComponent(); 16 } 17 18 private void button_Click(object sender, EventArgs e) 19 { 20 var text=((Button)sender).Text; 21 if (text == "=") 22 { 23 Evaluate(); 24 } 25 else 26 { 27 txtExpression.Text = txtExpression.Text + text; 28 } 29 } 30 31 private void Evaluate() 32 { 33 txtExpression.Text = new Caculator().Evaluate(txtExpression.Text).ToString(); 34 } 35 36 private void button16_Click(object sender, EventArgs e) 37 { 38 txtExpression.Clear(); 39 } 40 41 42 } 43 }
Form1.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace CaculationTest 6 { 7 enum TokenType 8 { 9 Add,Sub, 10 Mul,Div, 11 Int, 12 Expo, 13 Start,End 14 } 15 16 class Token 17 { 18 public TokenType Type; 19 public object Value; 20 21 22 public Token(TokenType type , object value = null) 23 { 24 Type = type; 25 Value = value; 26 } 27 } 28 }
Token.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace CaculationTest 6 { 7 /// <summary> </summary> 8 abstract class Expression 9 { 10 public abstract int GetValue(); 11 } 12 13 class UnaryExpress : Expression 14 { 15 int _value; 16 17 public UnaryExpress(int value) 18 { 19 _value = value; 20 } 21 22 23 public override int GetValue() 24 { 25 return _value; 26 } 27 } 28 29 30 class BinaryExpression : Expression 31 { 32 TokenType _tokenType; 33 int _left; 34 int _right; 35 36 37 public BinaryExpression(TokenType tokenType, Expression left, Expression right) 38 { 39 _tokenType = tokenType; 40 _left = left.GetValue(); 41 _right = right.GetValue(); 42 } 43 44 public override int GetValue() 45 { 46 switch (_tokenType) 47 { 48 case TokenType.Add: 49 return _left + _right; 50 case TokenType.Sub: 51 return _left - _right; 52 case TokenType.Mul: 53 return _left * _right; 54 case TokenType.Div: 55 return _left / _right; 56 case TokenType.Expo: 57 return Convert.ToInt32(Math.Pow(_left,_right)); 58 default: 59 throw new Exception("unexceptional token!"); 60 } 61 } 62 } 63 }
Expression.cs
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 6 namespace CaculationTest 7 { 8 /// <summary> </summary> 9 class Caculator 10 { 11 string _exp; 12 13 int _pos; 14 Token _token; 15 int _len; 16 17 18 public int Evaluate(string expression) 19 { 20 _exp = expression; 21 _len = expression.Length; 22 var exp = ParseExpression(); 23 return exp.GetValue(); 24 } 25 26 Expression ParseExpression() 27 { 28 //先解析一次,解析内容存在_token中 29 ParseToken(); 30 return ParseAddSub(); 31 } 32 33 //解析加减 34 Expression ParseAddSub() 35 { 36 //左操作数为优先级理高的运算符 37 var l = ParseMulDiv(); 38 while (_token.Type == TokenType.Add || _token.Type == TokenType.Sub) 39 { 40 var t = _token.Type; 41 ParseToken(); 42 var r = ParseMulDiv();//解析右操作数 43 l = new BinaryExpression(t, l, r); 44 } 45 return l; 46 } 47 48 #region 老逻辑 49 ////解析乘除 50 //Expression ParseMulDiv() 51 //{ 52 // var l = ParseUnary(); 53 // while (_token.Type == TokenType.Mul || _token.Type == TokenType.Div) 54 // { 55 // var t = _token.Type; 56 // ParseToken(); 57 // var r=ParseUnary(); 58 // l = new BinaryExpression(t, l, r); 59 // } 60 // return l; 61 //} 62 #endregion 63 64 //解析乘除 65 Expression ParseMulDiv() 66 { 67 var l = ParseExpo(); 68 while (_token.Type == TokenType.Mul || _token.Type == TokenType.Div) 69 { 70 var t = _token.Type; 71 ParseToken(); 72 var r = ParseExpo(); 73 l = new BinaryExpression(t, l, r); 74 } 75 return l; 76 } 77 78 //解析乘方 79 Expression ParseExpo() 80 { 81 var l = ParseUnary(); 82 while (_token.Type==TokenType.Expo) 83 { 84 var t = _token.Type; 85 ParseToken(); 86 var r = ParseUnary(); 87 l = new BinaryExpression(t, l, r); 88 } 89 return l; 90 } 91 92 //解析一元表达式(目前只有单个整数) 93 Expression ParseUnary() 94 { 95 Expression ret = null; 96 if (_token.Type == TokenType.Int) 97 { 98 ret= new UnaryExpress((int)_token.Value); 99 } 100 101 //解析完int后,移到下一个token处,即+-*/ 102 ParseToken(); 103 return ret; 104 } 105 106 107 void ParseToken() 108 { 109 //已结束 110 if (_pos >= _len) 111 { 112 _token= new Token(TokenType.End); 113 return; 114 } 115 116 //跳过空格 117 while (_exp[_pos] == ‘ ‘) 118 { 119 _pos++; 120 } 121 122 //如果以数字开头,解析整数 123 if (_exp[_pos] >= ‘0‘ && _exp[_pos] <= ‘9‘) 124 { 125 for (int i = 0; i + _pos <= _len; i++) 126 { 127 //如果以数字结尾,或者到达了数字的边界 128 if( i+_pos==_len||(_exp[_pos + i] < ‘0‘ || _exp[_pos + i] > ‘9‘)) 129 { 130 var intStr = _exp.Substring(_pos, i); 131 var value = int.Parse(intStr); 132 _token= new Token(TokenType.Int, value); 133 _pos += i; //解析成功后,更新当前位置 134 break; 135 } 136 } 137 } 138 else 139 { 140 switch (_exp[_pos]) 141 { 142 case ‘+‘: 143 _token=new Token(TokenType.Add); 144 break; 145 case ‘-‘: 146 _token = new Token(TokenType.Sub); 147 break; 148 case ‘*‘: 149 _token=new Token(TokenType.Mul); 150 break; 151 case ‘/‘: 152 _token = new Token(TokenType.Div); 153 break; 154 case ‘^‘: 155 _token=new Token(TokenType.Expo); 156 break; 157 default: 158 throw new Exception("unexpected token: " + _exp[_pos]); 159 } 160 _pos++;//解析成功后,更新当前位置 161 } 162 } 163 164 } 165 }
Calculator.cs
验证结果
时间: 2024-11-10 14:34:42