C# 将字符串转换为允许更改运算符前导的公式

C# 将字符串转换为允许更改运算符前导的公式,c#,operator-overloading,string-parsing,C#,Operator Overloading,String Parsing,假设我有一个公式字符串(例如stringformula=“(2+3*3)+7”),但我希望乘法运算符的顺序优先级不高于其他运算符。因此,在上面的例子中,除了仍然具有优先权的括号外,它们只需从左到右求解 我在网上到处找,找不到解决办法。我发现了非常古老的StackOverflow线程,但是评论中的人提到这些方法已经过时了,我不确定他们是否允许改变操作符的先例,他们只会按面值处理字符串 我也找到了但没有关于如何使用它的教程,而且我也没有找到需要添加到引用中的dll,以将框架实现到我的项目中 我在这里

假设我有一个公式字符串(例如
stringformula=“(2+3*3)+7”
),但我希望乘法运算符的顺序优先级不高于其他运算符。因此,在上面的例子中,除了仍然具有优先权的括号外,它们只需从左到右求解

我在网上到处找,找不到解决办法。我发现了非常古老的StackOverflow线程,但是评论中的人提到这些方法已经过时了,我不确定他们是否允许改变操作符的先例,他们只会按面值处理字符串

我也找到了但没有关于如何使用它的教程,而且我也没有找到需要添加到引用中的dll,以将框架实现到我的项目中

我在这里画空白。你们能帮忙吗


谢谢

将字符串转换为公式的类是:

public class StringToFormula
{
    private string[] _operators = { "-", "+", "/", "*", "^" };
    private Func<double, double, double>[] _operations = {
    (a1, a2) => a1 - a2,
    (a1, a2) => a1 + a2,
    (a1, a2) => a1 / a2,
    (a1, a2) => a1 * a2,
    (a1, a2) => Math.Pow(a1, a2)
    };

    public double Eval(string expression)
    {
        List<string> tokens = getTokens(expression);
        Stack<double> operandStack = new Stack<double>();
        Stack<string> operatorStack = new Stack<string>();
        int tokenIndex = 0;

        while (tokenIndex < tokens.Count)
        {
            string token = tokens[tokenIndex];
            if (token == "(")
            {
                string subExpr = getSubExpression(tokens, ref tokenIndex);
                operandStack.Push(Eval(subExpr));
                continue;
            }
            if (token == ")")
            {
                throw new ArgumentException("Mis-matched parentheses in expression");
            }
            //If this is an operator  
            if (Array.IndexOf(_operators, token) >= 0)
            {
                while (operatorStack.Count > 0 && Array.IndexOf(_operators, token) < Array.IndexOf(_operators, operatorStack.Peek()))
                {
                    string op = operatorStack.Pop();
                    double arg2 = operandStack.Pop();
                    double arg1 = operandStack.Pop();
                    operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
                }
                operatorStack.Push(token);
            }
            else
            {
                operandStack.Push(double.Parse(token));
            }
            tokenIndex += 1;
        }

        while (operatorStack.Count > 0)
        {
            string op = operatorStack.Pop();
            double arg2 = operandStack.Pop();
            double arg1 = operandStack.Pop();
            operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
        }
        return operandStack.Pop();
    }

    private string getSubExpression(List<string> tokens, ref int index)
    {
        StringBuilder subExpr = new StringBuilder();
        int parenlevels = 1;
        index += 1;
        while (index < tokens.Count && parenlevels > 0)
        {
            string token = tokens[index];
            if (tokens[index] == "(")
            {
                parenlevels += 1;
            }

            if (tokens[index] == ")")
            {
                parenlevels -= 1;
            }

            if (parenlevels > 0)
            {
                subExpr.Append(token);
            }

            index += 1;
        }

        if ((parenlevels > 0))
        {
            throw new ArgumentException("Mis-matched parentheses in expression");
        }
        return subExpr.ToString();
    }

    private List<string> getTokens(string expression)
    {
        string operators = "()^*/+-";
        List<string> tokens = new List<string>();
        StringBuilder sb = new StringBuilder();

        foreach (char c in expression.Replace(" ", string.Empty))
        {
            if (operators.IndexOf(c) >= 0)
            {
                if ((sb.Length > 0))
                {
                    tokens.Add(sb.ToString());
                    sb.Length = 0;
                }
                tokens.Add(c.ToString());
            }
            else
            {
                sb.Append(c);
            }
        }

        if ((sb.Length > 0))
        {
            tokens.Add(sb.ToString());
        }
        return tokens;
    }
}
结果是

18

将字符串转换为公式的类是:

public class StringToFormula
{
    private string[] _operators = { "-", "+", "/", "*", "^" };
    private Func<double, double, double>[] _operations = {
    (a1, a2) => a1 - a2,
    (a1, a2) => a1 + a2,
    (a1, a2) => a1 / a2,
    (a1, a2) => a1 * a2,
    (a1, a2) => Math.Pow(a1, a2)
    };

    public double Eval(string expression)
    {
        List<string> tokens = getTokens(expression);
        Stack<double> operandStack = new Stack<double>();
        Stack<string> operatorStack = new Stack<string>();
        int tokenIndex = 0;

        while (tokenIndex < tokens.Count)
        {
            string token = tokens[tokenIndex];
            if (token == "(")
            {
                string subExpr = getSubExpression(tokens, ref tokenIndex);
                operandStack.Push(Eval(subExpr));
                continue;
            }
            if (token == ")")
            {
                throw new ArgumentException("Mis-matched parentheses in expression");
            }
            //If this is an operator  
            if (Array.IndexOf(_operators, token) >= 0)
            {
                while (operatorStack.Count > 0 && Array.IndexOf(_operators, token) < Array.IndexOf(_operators, operatorStack.Peek()))
                {
                    string op = operatorStack.Pop();
                    double arg2 = operandStack.Pop();
                    double arg1 = operandStack.Pop();
                    operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
                }
                operatorStack.Push(token);
            }
            else
            {
                operandStack.Push(double.Parse(token));
            }
            tokenIndex += 1;
        }

        while (operatorStack.Count > 0)
        {
            string op = operatorStack.Pop();
            double arg2 = operandStack.Pop();
            double arg1 = operandStack.Pop();
            operandStack.Push(_operations[Array.IndexOf(_operators, op)](arg1, arg2));
        }
        return operandStack.Pop();
    }

    private string getSubExpression(List<string> tokens, ref int index)
    {
        StringBuilder subExpr = new StringBuilder();
        int parenlevels = 1;
        index += 1;
        while (index < tokens.Count && parenlevels > 0)
        {
            string token = tokens[index];
            if (tokens[index] == "(")
            {
                parenlevels += 1;
            }

            if (tokens[index] == ")")
            {
                parenlevels -= 1;
            }

            if (parenlevels > 0)
            {
                subExpr.Append(token);
            }

            index += 1;
        }

        if ((parenlevels > 0))
        {
            throw new ArgumentException("Mis-matched parentheses in expression");
        }
        return subExpr.ToString();
    }

    private List<string> getTokens(string expression)
    {
        string operators = "()^*/+-";
        List<string> tokens = new List<string>();
        StringBuilder sb = new StringBuilder();

        foreach (char c in expression.Replace(" ", string.Empty))
        {
            if (operators.IndexOf(c) >= 0)
            {
                if ((sb.Length > 0))
                {
                    tokens.Add(sb.ToString());
                    sb.Length = 0;
                }
                tokens.Add(c.ToString());
            }
            else
            {
                sb.Append(c);
            }
        }

        if ((sb.Length > 0))
        {
            tokens.Add(sb.ToString());
        }
        return tokens;
    }
}
结果是

18

谢谢你的帮助!该类接受运算符重载吗?我不认为它接受运算符重载。很遗憾:(在这种情况下,还有另一种方法可以达到我的目标,这段代码决定运算符的优先级吗?如果是,有没有办法改变代码,使乘法运算符不优先于加法和减法?谢谢你的帮助!该类接受运算符重载吗?我想它不接受运算符重载不幸的是:(在这种情况下,有另一种方法可以达到我的目标,这段代码决定运算符的优先级吗?如果是的话,有没有办法改变代码,使乘法运算符不优先于加法和减法?