知识点:
1.System.Math.Pow() 实现乘方
2.实现计算器的运算优先级,依次调用的流程
问题:
还未实现“()”功能
解决方案
UI:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms; namespace CaculationTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button_Click(object sender, EventArgs e)
{
var text=((Button)sender).Text;
if (text == "=")
{
Evaluate();
}
else
{
txtExpression.Text = txtExpression.Text + text;
}
} private void Evaluate()
{
txtExpression.Text = new Caculator().Evaluate(txtExpression.Text).ToString();
} private void button16_Click(object sender, EventArgs e)
{
txtExpression.Clear();
} }
}
Form1.cs
using System;
using System.Collections.Generic;
using System.Text; namespace CaculationTest
{
enum TokenType
{
Add,Sub,
Mul,Div,
Int,
Expo,
Start,End
} class Token
{
public TokenType Type;
public object Value; public Token(TokenType type , object value = null)
{
Type = type;
Value = value;
}
}
}
Token.cs
using System;
using System.Collections.Generic;
using System.Text; namespace CaculationTest
{
/// <summary> </summary>
abstract class Expression
{
public abstract int GetValue();
} class UnaryExpress : Expression
{
int _value; public UnaryExpress(int value)
{
_value = value;
} public override int GetValue()
{
return _value;
}
} class BinaryExpression : Expression
{
TokenType _tokenType;
int _left;
int _right; public BinaryExpression(TokenType tokenType, Expression left, Expression right)
{
_tokenType = tokenType;
_left = left.GetValue();
_right = right.GetValue();
} public override int GetValue()
{
switch (_tokenType)
{
case TokenType.Add:
return _left + _right;
case TokenType.Sub:
return _left - _right;
case TokenType.Mul:
return _left * _right;
case TokenType.Div:
return _left / _right;
case TokenType.Expo:
return Convert.ToInt32(Math.Pow(_left,_right));
default:
throw new Exception("unexceptional token!");
}
}
}
}
Expression.cs
using System;
using System.Collections.Generic;
using System.Text; namespace CaculationTest
{
/// <summary> </summary>
class Caculator
{
string _exp; int _pos;
Token _token;
int _len; public int Evaluate(string expression)
{
_exp = expression;
_len = expression.Length;
var exp = ParseExpression();
return exp.GetValue();
} Expression ParseExpression()
{
//先解析一次,解析内容存在_token中
ParseToken();
return ParseAddSub();
} //解析加减
Expression ParseAddSub()
{
//左操作数为优先级理高的运算符
var l = ParseMulDiv();
while (_token.Type == TokenType.Add || _token.Type == TokenType.Sub)
{
var t = _token.Type;
ParseToken();
var r = ParseMulDiv();//解析右操作数
l = new BinaryExpression(t, l, r);
}
return l;
} #region 老逻辑
////解析乘除
//Expression ParseMulDiv()
//{
// var l = ParseUnary();
// while (_token.Type == TokenType.Mul || _token.Type == TokenType.Div)
// {
// var t = _token.Type;
// ParseToken();
// var r=ParseUnary();
// l = new BinaryExpression(t, l, r);
// }
// return l;
//}
#endregion //解析乘除
Expression ParseMulDiv()
{
var l = ParseExpo();
while (_token.Type == TokenType.Mul || _token.Type == TokenType.Div)
{
var t = _token.Type;
ParseToken();
var r = ParseExpo();
l = new BinaryExpression(t, l, r);
}
return l;
} //解析乘方
Expression ParseExpo()
{
var l = ParseUnary();
while (_token.Type==TokenType.Expo)
{
var t = _token.Type;
ParseToken();
var r = ParseUnary();
l = new BinaryExpression(t, l, r);
}
return l;
} //解析一元表达式(目前只有单个整数)
Expression ParseUnary()
{
Expression ret = null;
if (_token.Type == TokenType.Int)
{
ret= new UnaryExpress((int)_token.Value);
} //解析完int后,移到下一个token处,即+-*/
ParseToken();
return ret;
} void ParseToken()
{
//已结束
if (_pos >= _len)
{
_token= new Token(TokenType.End);
return;
} //跳过空格
while (_exp[_pos] == ' ')
{
_pos++;
} //如果以数字开头,解析整数
if (_exp[_pos] >= '' && _exp[_pos] <= '')
{
for (int i = ; i + _pos <= _len; i++)
{
//如果以数字结尾,或者到达了数字的边界
if( i+_pos==_len||(_exp[_pos + i] < '' || _exp[_pos + i] > ''))
{
var intStr = _exp.Substring(_pos, i);
var value = int.Parse(intStr);
_token= new Token(TokenType.Int, value);
_pos += i; //解析成功后,更新当前位置
break;
}
}
}
else
{
switch (_exp[_pos])
{
case '+':
_token=new Token(TokenType.Add);
break;
case '-':
_token = new Token(TokenType.Sub);
break;
case '*':
_token=new Token(TokenType.Mul);
break;
case '/':
_token = new Token(TokenType.Div);
break;
case '^':
_token=new Token(TokenType.Expo);
break;
default:
throw new Exception("unexpected token: " + _exp[_pos]);
}
_pos++;//解析成功后,更新当前位置
}
} }
}
Calculator.cs