惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News | PayPal Newsroom
P
Proofpoint News Feed
Cyberwarzone
Cyberwarzone
C
Cisco Blogs
SecWiki News
SecWiki News
Know Your Adversary
Know Your Adversary
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Vercel News
Vercel News
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
NISL@THU
NISL@THU
WordPress大学
WordPress大学
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Threat Research - Cisco Blogs
AI
AI
Simon Willison's Weblog
Simon Willison's Weblog
Security Archives - TechRepublic
Security Archives - TechRepublic
有赞技术团队
有赞技术团队
L
LINUX DO - 热门话题
Hacker News: Ask HN
Hacker News: Ask HN
V
V2EX
G
GRAHAM CLULEY
TaoSecurity Blog
TaoSecurity Blog
Hugging Face - Blog
Hugging Face - Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
F
Fortinet All Blogs
博客园 - 叶小钗
博客园 - 三生石上(FineUI控件)
云风的 BLOG
云风的 BLOG
Recorded Future
Recorded Future
Latest news
Latest news
The Hacker News
The Hacker News
aimingoo的专栏
aimingoo的专栏
T
Troy Hunt's Blog
S
Schneier on Security
I
Intezer
Google DeepMind News
Google DeepMind News
A
Arctic Wolf
Apple Machine Learning Research
Apple Machine Learning Research
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Threatpost
爱范儿
爱范儿
The Register - Security
The Register - Security
S
SegmentFault 最新的问题
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
宝玉的分享
宝玉的分享
Recent Commits to openclaw:main
Recent Commits to openclaw:main
美团技术团队
B
Blog RSS Feed

博客园 - sdxd.bgl

将SQL Server中的数据显示到SharePoint中 拓展训练总结 在PowerShell中,如何获取SharePoint的默认数据库服务器 在SharePoint页面中如何显示来自其他网站的List 恢复导出XSLT List View WebPart 实战部署FAST Search Server 2010 for SharePoint Sharepoint开发中代码运行权限级别 在InfoPath中如何获取当前用户的信息(Profile) 晒晒我的家乡 关于模式的思考 小心委托 利用System.Linq.Expressions实现四则运算计算器(二) 利用System.Linq.Expressions实现四则运算计算器(一) 初识System.Linq.Expressions 请拆招:将两个已排序集合分解成两个独立部分的集合和一个共有部分的集合? 如何实现Windows服务 用javascript实现下拉列表的自动筛选功能 - sdxd.bgl - 博客园 我的生活 电脑是个神奇的东西!
利用System.Linq.Expressions实现四则运算计算器(三)
sdxd.bgl · 2007-08-30 · via 博客园 - sdxd.bgl

利用System.Linq.Expressions实现四则运算计算器(三)

将表达式树转换成.NET定义的表达式树

请大家留意上次提供的类图:


抽象类
BWExpression提供了一个抽象方法GetExpression,这个方法就是用于获取表达式类的。

对于常量表达式BWConstantExpressionNode节点,GetExpression只需把数字作为常量表达式返回:

///<summary>

///生成表达式

///</summary>

///<returns>表达式</returns>

public override Expression GetExpression()

{

    return Expression.Constant(this.Operand, typeof(double));

}

对于BWExpressionNodeCollection节点,GetExpression需要对其表达式子节点针对运算符优先级进行组合。

///<summary>

///生成表达式

///</summary>

///<returns>表达式</returns>

public override Expression GetExpression()

{

    // 1 + 5 * 9 - ( 1 + 2 ) * 3 / 4 + 6 * ( -2 )

    // 将加、减放入队列中,乘、除计算后也放入队列中

    List<ExpressionWriper> expressionList = new List<ExpressionWriper>();

    expressionList.Add(new ExpressionWriper(this.expressionNodeList[0].GetExpression(), this.expressionNodeList[0].ExpressionNodeType));

    for (int i = 1; i < this.expressionNodeList.Count; i++)

    {

        BWExpressionNode currentNode = this.expressionNodeList[i];

        switch (currentNode.ExpressionNodeType)

        {

            case BWExpressionNodeType.Addition:

            case BWExpressionNodeType.Subtration:

                expressionList.Add(new ExpressionWriper(currentNode.GetExpression(), currentNode.ExpressionNodeType));

                break;

            case BWExpressionNodeType.Multiplication:

                {

                    ExpressionWriper preNode = expressionList[expressionList.Count - 1];

                    expressionList[expressionList.Count - 1] = new ExpressionWriper(Expression.Multiply(preNode.Expression, currentNode.GetExpression()), preNode.ExpressionNodeType);

                    break;

                }

            case BWExpressionNodeType.Division:

                {

                    ExpressionWriper preNode = expressionList[expressionList.Count - 1];

                    expressionList[expressionList.Count - 1] = new ExpressionWriper(Expression.Divide(preNode.Expression, currentNode.GetExpression()), preNode.ExpressionNodeType);

                    break;

                }

        }

    }

    Expression expression = null;

    // 对队列中的加、减进行计算

    for (int i = 0; i < expressionList.Count; i++)

    {

        ExpressionWriper wriper = expressionList[i];

        switch (wriper.ExpressionNodeType)

        {

            case BWExpressionNodeType.Start:

                expression = wriper.Expression;

                break;

            case BWExpressionNodeType.Addition:

                expression = Expression.Add(expression, wriper.Expression);

                break;

            case BWExpressionNodeType.Subtration:

                expression = Expression.Subtract(expression, wriper.Expression);

                break;

            case BWExpressionNodeType.Multiplication:

                expression = Expression.Multiply(expression, wriper.Expression);

                break;

            case BWExpressionNodeType.Division:

                expression = Expression.Divide(expression, wriper.Expression);

                break;

       }

    }

    return expression;

}

在这个方法中,我引入一个辅助类ExpressionWriper,用于保存临时表达式和其前面的符号。

private class ExpressionWriper

{

    public BWExpressionNodeType ExpressionNodeType { get; set; }

    public Expression Expression { get; set; }

    public ExpressionWriper(Expression expression, BWExpressionNodeType type)

    {

        this.Expression = expression;

        this.ExpressionNodeType = type;

    }

}

这个GetExpression方法中,使用一个列表来临时存储加减表达式。由于乘法和除法需要优先计算,在方法中,先是把第一个表达式放入队列,再判断第二个表达式的符号,如果是加号或者减号,则直接把第二个表达式放入队列,如果遇到的是乘号或除号,则把队列的最后一个拿出来与当前表达式进行计算,结果放回队列的最后一个。这样,就保持了队列中只有加减表达式,没有乘除,因为乘法和除法都计算过了。看下面的流程图。


这个方法最后得到一个包含所有节点和子节点的表达式,返回给调用者。

为了方便使用,我写了一个静态方法,从传入字符串到得到计算结果,一次完成!

public class BWExpression

{

    Func<double> func;

    public Func<double> Func

    {

        get { return func; }

        set { func = value; }

    }

    public void CreateFunc(string input)

    {

        // 1 + 5 * 9 - ( 1 + 2 ) * 3 / 4 + 6 * ( -2 )

        BWExpressionNodeCollection nodes = new BWExpressionNodeCollection(input, BWExpressionNodeType.Start);

        Expression expression = nodes.GetExpression();

        Expression<Func<double>> lamdbaExpression = Expression.Lambda<Func<double>>(expression);

        func = lamdbaExpression.Compile();

    }

    public static double Calculate(string expressionString)

    {

        BWExpression expression = new BWExpression();

        expression.CreateFunc(expressionString);

        return expression.Func();

    }

}

CreateFunc(string input)方法在《初识System.Linq.Expressions》中提到过,大家可以连接过去看看。

最后建一个窗体:

按钮的事件处理如下:

private void btnCalc_Click(object sender, EventArgs e)

{

    try

    {

        txtOutput.Text = BWExpression.Calculate(txtInput.Text).ToString();

    }

    catch

    {

        MessageBox.Show("表达式错误!");

    }

}

好啦!一个完整的四则运算的简单计算器就做好啦!大家大概了解System.Linq.Expressions中表达式的应用了吧?