我正在尝试转换 this Java code (使用 Dijkstra 的两栈算法计算算术表达式)到 C#:
using System;
using System.Collections.Generic;
using System.IO;
public class Evaluate
{
public double Eval(string expression)
{
Stack<string> ops = new Stack<string>();
Stack<double> vals = new Stack<double>();
string s = expression;
while (!s.Equals(""))
{
if (s.Equals("(")) ;
if (s.Equals("+")) ops.Push(s);
else if (s.Equals("-")) ops.Push(s);
else if (s.Equals("*")) ops.Push(s);
else if (s.Equals("/")) ops.Push(s);
else if (s.Equals("sqrt")) ops.Push(s);
else if (s.Equals(")"))
{
string op = ops.Pop();
double v = vals.Pop();
if (op.Equals("+")) v = vals.Pop() + v;
else if (op.Equals("-")) v = vals.Pop() - v;
else if (op.Equals("*")) v = vals.Pop() * v;
else if (op.Equals("/")) v = vals.Pop() / v;
else if (op.Equals("sqrt")) v = Math.Sqrt(v);
vals.Push(v);
}
else vals.Push(double.Parse(s));
}
return vals.Pop();
}
}
但是当我尝试测试 Unity 时它停止工作。我做错了什么?
最佳答案
您的代码的行为符合预期。你没有很好地将Java代码翻译成C#。我现在可以发现一个问题,但我不知道当你解决这个问题时是否还会出现更多问题。
如果输入为空,Java 原始代码就会退出 while 循环。下面是 Java 代码的样子:
while (!StdIn.isEmpty()) {
String s = StdIn.readString();
......
......
}
它使用输入来打破 while 循环。如果输入为空则退出。
您的 C# 代码:
while (!s.Equals(""))
{
......
......
}
它使用 s 来打破 while 循环,但 s 在循环中的任何位置都不会被更改。所以循环继续进行。这导致了Unity中的无限循环和无限循环 = 锁定/卡住,几乎没有异常(exception)。
修复#1。在另一个线程中调用 Eval。不建议初学者使用。
修复#2。使用协程。
我的解决方案是使用 Coroutine。
将函数返回类型从 double
更改为 Coroutine
,然后将 yield return null;
放入 while
循环内。要调用该函数,请使用StartCoroutine(Eval("Your Expression"));
。使用 yield return null;
将防止 Unity 崩溃。
即使您这样做,当您传入一个不为空的值时,您的代码仍然不会退出,但它不会锁定/卡住。
要解决此问题并从 Java 复制代码,您应该找到一种通过输入退出程序的方法。
转到GameObject->UI->输入字段并将GameObject重命名为EvalInput;
现在使用输入字段和下面的代码使 C# 代码的外观和功能更像 Java 代码。最终结果存储在全局evalResult
变量中。
InputField evalInput;
void Start()
{
StartCoroutine(Eval("Your Expression"));
evalInput = GameObject.Find("EvalInput").GetComponent<InputField>();
}
double evalResult = 0;
public IEnumerator Eval(string expression)
{
Stack<string> ops = new Stack<string>();
Stack<double> vals = new Stack<double>();
string s = expression;
while (!s.Equals(""))
{
s = evalInput.text; //Modify the string here (Empty string == Exit)
if (s.Equals("(")) ;
if (s.Equals("+")) ops.Push(s);
else if (s.Equals("-")) ops.Push(s);
else if (s.Equals("*")) ops.Push(s);
else if (s.Equals("/")) ops.Push(s);
else if (s.Equals("sqrt")) ops.Push(s);
else if (s.Equals(")"))
{
string op = ops.Pop();
double v = vals.Pop();
if (op.Equals("+")) v = vals.Pop() + v;
else if (op.Equals("-")) v = vals.Pop() - v;
else if (op.Equals("*")) v = vals.Pop() * v;
else if (op.Equals("/")) v = vals.Pop() / v;
else if (op.Equals("sqrt")) v = System.Math.Sqrt(v);
vals.Push(v);
}
else vals.Push(double.Parse(s));
yield return null;
}
evalResult = vals.Pop();
}
关于java - 将 Java 转换为 C# (Unity),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36632465/