【问题标题】:Computing a simple statement with 4 arithmetic operators doesn't work用 4 个算术运算符计算一个简单的语句不起作用
【发布时间】:2019-11-17 15:58:47
【问题描述】:

我正在尝试学习 c#,目前我正在尝试制作一个计算器,您可以在其中输入任意数量的字符,它会显示最终结果...

对于我的示例,我将使用 List<string> Statement = {"12", "/", "4", "*", "3"}

string numbers = "0123456789";

for (int i = 0; i < Statement.Count; i++)
            {
                if (!numbers.Contains(Statement[i][0]))
                {
                    Statement[i] = Convert.ToString(Operations.Compute(Convert.ToInt32(Statement[i - 1]), Convert.ToInt32(Statement[i + 1]), Statement[i]));
                    Statement.RemoveAt(i - 1);
                    Statement.RemoveAt(i + 1);
                    i--;
                }
            }

运算计算:

class Operations
    {
        public static float Compute(float num1, float num2, string OpType)
        {
            if(OpType == "+") { return num1 + num2; }
            if(OpType == "-") { return num1 - num2; }
            if(OpType == "*") { return num1 * num2; }
            if(OpType == "/") { return num1 / num2; }

            return 0;
        }
    }

当我运行程序并使用简单的 foreach 循环列出来自 Statement 的所有元素时,我希望它返回 9(因为 12/4*3 = 9)。

相反,它列出了以下三个数字:3、4、3

它似乎总是计算前两个数字,然后列出其余的数字。

【问题讨论】:

  • 如果您调用RemoveAt,那么您的i 不再是之前值的索引。这意味着您的第二个 RemoveAt 删除了其他内容
  • 您以非常复杂的方式进行操作。也许Stack&lt;&gt;Queue&lt;&gt; 可以帮助您。那么你就不需要for-loop。
  • @Neijwiert 我知道 RemoveAt 会以某种方式影响我,没想到那个。谢谢!
  • 第一次执行Statement.RemoveAt(i + 1);,i 是1,所以你删除了item[2],当时"*"
  • @oerkelens 是的,我刚刚将 RemoveAt 中的 i + 1 更改为 i 并且它可以工作。谢谢!

标签: c# list for-loop


【解决方案1】:

为了计算公式,我建议使用堆栈机。在一般情况中,您必须在Shunting-yard algorithm 的帮助下将初始公式转换为RPN(反向波兰表示法)。 但是,如果您只有4 中缀二进制算术运算,则可以将计算视为

  // Let's extract the model: all possible infix binary operations
  Dictionary<string, Func<double, double, double>> operations = 
    new Dictionary<string, Func<double, double, double>>() {
      { "+", (x, y) => x + y },
      { "-", (x, y) => x - y },
      { "*", (x, y) => x * y },
      { "/", (x, y) => x / y },
  };

  List<string> data = new List<string>() {
    "12", "/", "4", "*", "3"
  };

  // Stack for data
  Stack<double> items = new Stack<double>();
  // Stack for operations
  Stack<Func<double, double, double>> ops = new Stack<Func<double, double, double>>();

  foreach (string item in data)
    if (double.TryParse(item, out double v)) // do we have number? 
      if (ops.Any()) // do we have an operation? 
        // if yes, execute it; put the outcome on the stack 
        items.Push(ops.Pop()(items.Pop(), v)); 
      else
        // if no operation, just put item on the stack
        items.Push(v);
    else // operation should be put on its stack
      ops.Push(operations[item]);

  double result = items.Pop();

【讨论】:

  • 非常感谢您的深入回答。我将研究所有这些的含义。并在我的代码中一一查看它如何影响一切。
【解决方案2】:

我刚刚从 Statement.RemoveAt(i + 1); 切换到 Statement.RemoveAt(i); 并且它工作正常。

那是因为当您执行Statement.RemoveAt(i - 1); 时,i 的位置发生了变化,因此Statement.RemoveAt(i + 1); 在您实际要删除的元素之后删除了该元素。感谢您的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    相关资源
    最近更新 更多