簡體   English   中英

使用帶有表達式樹的 c#.NET 創建 RPN 計算器

[英]Creating RPN calculator using c#.NET with expression trees

我是表達式樹的新手,有一段時間沒有使用 c# 了。 我需要使用表達式樹創建反向波蘭符號計算器。

到目前為止,我已經創建了 2 個堆棧,一個用於操作,另一個用於數字。 我想知道如何拆分用戶輸入並在以下表達式中調用它

Expression<Func<double, double, double, double>> calc = (x, y, z) => x + y - z;
 //sample input 11 6 5 4 + - / 7 * 2 2 2 + - 

    //my expression class
 class Expression : ExpressionVisitor
{
    Stack<int> nums = new Stack<int>();
    Stack<char> ops = new Stack<char>();



    public override Expression Visit(Expression node)
    {
        if (node == null)
        {
            return null;
        }
        switch (node.NodeType)
        {

            case ExpressionType.Add:
                return this.VisitBinary((BinaryExpression)node); 
            case ExpressionType.Subtract:
                return this.VisitBinary((BinaryExpression)node);
            case ExpressionType.Multiply:
                return this.VisitBinary((BinaryExpression)node);
            case ExpressionType.Divide:
                return this.VisitBinary((BinaryExpression)node);
            case ExpressionType.Power:
                return this.VisitBinary((BinaryExpression)node);
            default:
                return base.Visit(node);

        }
    }


    protected override Expression VisitBinary(BinaryExpression node)
    {

        var rightSide = this.Visit(node.rightSide);


        var leftSide = this.Visit(node.leftSide);
        switch (node.NodeType)
        {
            case ExpressionType.Add:
                return Expression.MakeBinary(ExpressionType.Add, leftSide, rightSide);
            case ExpressionType.Subtract:
                return Expression.MakeBinary(ExpressionType.Subtract, leftSide, rightSide);
            case ExpressionType.Multiply:
              return  Expression.MakeBinary(ExpressionType.Multiply, leftSide, rightSide);
            case ExpressionType.Divide:
              return  Expression.MakeBinary(ExpressionType.Divide, leftSide, rightSide);
            case ExpressionType.Power:
                return Expression.MakeBinary(ExpressionType.Power, leftSide, rightSide);

            default:
                return base.VisitBinary(node);
        }

//main class    
static void Main(string[] args)
    {


        var visitor = new Expression();
        string input = Console.ReadLine();
        string[] rpnTokens = input.Split(' ');
        Expression<Func<double, double, double, double>> calc = (x, y, z) => x + y - z;

        Console.WriteLine("result: " + calc);


    }

使用反向波蘭表示法,用戶輸入按輸入順序執行。

  • 將用戶輸入拆分為一系列操作數和運算符(稱為標記)。
  • 創建一個空堆棧來保存操作數和中間結果。
  • 按順序對用戶輸入(即'call it' )進行操作(對於您的示例輸入,序列將是 11,然后是 6,然后是 5 等)
    • 對於操作數,將操作數壓入堆棧。
    • 對於操作員
      • 從堆棧中彈出操作數 2
      • 從堆棧中彈出操作數 1
      • 將應用於操作數 1 和操作數 2 的運算符的結果壓入堆棧
  • 作用於最后一個令牌后,堆棧中應該剩下一個值; 表達式的結果。

這是使用表達式樹來創建 RPN 計算器嗎? 輸入字符串等效於表達式樹(請參閱示例表達式樹)。 它編碼相同的信息; 即一系列操作。 '5' 和 '4' 必須添加,然后才能從 '6' 中減去結果,等等。所以,也許更好的說法是將表達式樹的等價物用作 RPN 計算器的輸入.


使用代碼片段中的示例輸入的示例。

Empty stack              {}
Push 11                  {11}
Push 6                   {11, 6}
Push 5                   {11, 6, 5}
Push 4                   {11, 6, 5, 4}

Pop operand 2, = 4       {11, 6, 5}
Pop operand 1, = 5       {11, 6}
Push + operator result   {11, 6, 9}

Pop operand 2 = 9        {11, 6}
Pop operand 1 = 6        {11}
Push - operator result   {11, -3}

Pop operand 2 = -3       {11}
Pop operand 1 = 11       {}
Push / operator result   {-11/3}

Push 7                   {-11/3, 7}

Pop operand 2 = 7        {-11/3}
Pop operand 1 = -11/3    {}
Push * operator result   {-77/3}

Push 2                   {-77/3, 2}
Push 2                   {-77/3, 2, 2}
Push 2                   {-77/3, 2, 2, 2}

Pop operand 2 = 2        {-77/3, 2, 2}
Pop operand 1 = 2        {-77/3, 2}
Push + operator result   {-77/3, 2, 4}

Pop operand 2 = 4        {-77/3, 2}
Pop operand 1 = 2        {-77/3}
Push - operator result   {-77/3, -2}

NOTE:  There are two values left on the stack, so the expression is incomplete.
Let's add a '+' operator to complete it.

Pop operand 2 = -2       {-77/3}
Pop operand 1 = -77/3    {}
Push + operator result   {-83/3}

So, there are no more tokens *and* there is one value on the stack.  Success!

Pop final result = -83/3 {}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM