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