简体   繁体   中英

Convert Java to C# (Unity)

I'm trying to convert this Java code (Evaluates arithmetic expressions using Dijkstra's two-stack algorithm) to 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();
    }
}

But Unity stop working when I'm try to test it. What have I done wrong?

Your code is behaving as expected. You did not translate the Java code to C# well. I can spot one problem for now but I don't know if there is more of them when you fix this one.

The Java original code exits the while loop if input is empty . Below is what the Java code looks like:

while (!StdIn.isEmpty()) {
String s = StdIn.readString();  
......
......
}

It uses the input to break out of the while loop. Exits if input is empty.

Your C# code:

while (!s.Equals(""))
{
......
......
}

It uses s to break out of the while loop but s is not being changed any where in the loop. So the loop keeps going.This leads to infinite loop and infinite loop in Unity = Lock/Freeze with few Exceptions.

Fix #1 . Call Eval in another Thread. Not recommended for a beginner.

Fix #2 . Use Coroutine .

My solution is with Coroutine.

Change your function return type from double to Coroutine then put yield return null; inside the while loop. To call the function, use StartCoroutine(Eval("Your Expression")); . The use of yield return null; will prevent Unity from crashing.

Even when you do this, you code still won't exit when you pass in a value that is not empty but it wont Lock / Freeze anymore.

To fix this and replicate the code from Java, you should find a way to exit the program with an input.

Go to GameObject -> UI -> Input Field and Rename that GameObject to EvalInput ;

Now use the Input field and the code below to make the C# code look and function more like the Java Code. The final result is stored in the global evalResult variable.

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM