为了进行研究,有必要编写一个算术运算器解析器,该解析器不仅可以计算最简单的运算,而且可以使用方括号和函数进行运算。
我在Internet上找不到适合我的现成解决方案(有些太复杂了,有些还不能完全满足我的任务条件)。 经过一番悲伤之后,我开始自己解决问题,现在我想与世界各地
的原始解决方案共享我的原始
****代码 。
我遇到的第一个问题是方括号。 不仅应该首先执行它们,所以括号也可以放在其中。 依此类推。
与函数完全相同的故事-在函数的参数中,可能还有其他函数,甚至整个表达式。
但是稍后会更多。 首先,您需要解析整个表达式。 请注意,我们可能会遇到方括号,数字,操作数(+,-,*,/,^),函数或常量。
创建整个列表:
public static List<string> digits = new List<string>() { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "," }; public static List<string> operands = new List<string>() {"^", "/", "*", "+", "-"}; public static List<string> functions = new List<string>() { "sqrt", "sin", "cos", "log", "abs"}; public static List<string> brackets = new List<string>() { "(", ")" }; public static List<string> constants = new List<string>() { "pi" }; public static Dictionary<string, string> constantsValues = new Dictionary<string, string>() { ["pi"] = "3,14159265359" };
我们将依次检查每个字符。 自然地,如果我们在数字后没有遇到符号“ +”或“-”,则该符号分别表示正数或负数。
for (int i = 0; i < expression.Length; i++) { if (brackets.Contains(expression[i].ToString())){ if (lastSymbol != ""){ symbols.Add(lastSymbol); lastSymbol = ""; }
在示例中,GetParametrs函数被跳过。 函数具有2个参数的情况下需要它。 事实是您无法进行简单的拆分。 我们可以这样表达:
public static List<string> GetParametrs(string functionParametrs){ int bracketsSum = 0; int functionEnd = 0; for (int j = 0; j < functionParametrs.Length; j++){ if (functionParametrs[j].ToString() == "(") bracketsSum++; if (functionParametrs[j].ToString() == ")") bracketsSum--; if (functionParametrs[j].ToString() == ";" && bracketsSum == 0){ functionEnd = j; break; } } var buffer = new char[functionEnd]; functionParametrs.CopyTo(0, buffer, 0, functionEnd); string firstParametr = new string(buffer); buffer = new char[functionParametrs.Length - functionEnd - 1]; functionParametrs.CopyTo(functionEnd + 1, buffer, 0, functionParametrs.Length - functionEnd - 1); string secondParametr = new string(buffer); return ( new List<string>() { firstParametr, secondParametr } ); }
因此,将表达式分为较小的表达式,此外,已经计算了函数的值并将其替换为数字的主表达式。
支架可以按照相同的原理进行处理-立即计算它们并将其替换为数字:
while (symbols.Contains("(")) { int bracketsStart = 0; int bracketsEnd = 0; int bracketsSum = 0; for (int i = 0; i < symbols.Count; i++) { if (symbols[i] == "(") { bracketsStart = i; bracketsSum = 1; break; } } for (int i = bracketsStart + 1; i < symbols.Count; i++) { if (symbols[i] == "(") bracketsSum++; if (symbols[i] == ")") bracketsSum--; if (bracketsSum == 0) { bracketsEnd = i; break; } } string bracketsExpression = ""; for (int i = bracketsStart + 1; i < bracketsEnd; i++) bracketsExpression += symbols[i]; symbols[bracketsStart] = CalculateExpression(bracketsExpression).ToString(); symbols.RemoveRange(bracketsStart + 1, bracketsEnd - bracketsStart); }
再次找到右方括号的索引要复杂一些。 您不能只选择下一个括号。 这不适用于嵌套括号。
该程序的主要部分已编写。 它仍然可以实现普通算术表达式的计算。 为了不担心操作的顺序,我决定用波兰语表示形式写下该表达式:
foreach(var j in operands){
最后,通过堆栈,我们计算表达式的值:
List<string> result = new List<string>(); string[] temp = symbols[0].Split(' '); for (int i = 0; i < temp.Length; i++) { if (operands.Contains(temp[i])) { if (temp[i] == "^") { result[result.Count - 2] = Math.Pow(double.Parse(result[result.Count - 2]), double.Parse(result[result.Count - 1])).ToString(); result.RemoveRange(result.Count - 1, 1); } if (temp[i] == "+") { result[result.Count - 2] = (double.Parse(result[result.Count - 2]) + double.Parse(result[result.Count - 1])).ToString(); result.RemoveRange(result.Count - 1, 1); } if (temp[i] == "-") { result[result.Count - 2] = (double.Parse(result[result.Count - 2]) - double.Parse(result[result.Count - 1])).ToString(); result.RemoveRange(result.Count - 1, 1); } if (temp[i] == "*") { result[result.Count - 2] = (double.Parse(result[result.Count - 2]) * double.Parse(result[result.Count - 1])).ToString(); result.RemoveRange(result.Count - 1, 1); } if (temp[i] == "/") { result[result.Count - 2] = (double.Parse(result[result.Count - 2]) / double.Parse(result[result.Count - 1])).ToString(); result.RemoveRange(result.Count - 1, 1); } } else result.Add(temp[i]); }
如果一切顺利,结果将是结果[0]。
→使用完整代码
链接到GitHub