//------------------------------------------------------------------------------------------------------------ public static decimal Evaluate(string postfix) { bool debug = false; if (Toolbelt.HasLetters(postfix)) { return(0M); } Stack <string> expression = new Stack <string>(postfix.Split(' ').Reverse()); Stack <decimal> operands = new Stack <decimal>(); while (expression.Count > 0) { if (debug) { Toolbelt.DisplayStack(expression, "expression"); Toolbelt.DisplayStack(operands, "operands"); } string working = expression.Pop(); decimal value; if (Decimal.TryParse(working, out value)) { operands.Push(value); } else if (working.Length == 1 && Toolbelt.IsOperator(working[0])) { if (operands.Count >= 2) { var x = operands.Pop(); var y = operands.Pop(); operands.Push(calculate(y, working[0], x)); } } } return(operands.Pop()); }
//------------------------------------------------------------------------------------------------------------ public static string Convert(string infix, bool allowLetters = true) { string name = "InfixToPostfix.Convert"; if (infix == null) { throw new ArgumentNullException($"{name} infix value cannot be null"); } if (infix.Trim() == "") { throw new ArgumentException($"{name} infix value must not be empty"); } if (infix.Trim().Length <= 0) { throw new ArgumentException($"{name} infix value must have at least one character"); } Toolbelt.StripWhiteSpace(ref infix); Stack <char> infixStack = new Stack <char>(infix.ToCharArray().Reverse()); StringBuilder postFix = new StringBuilder(); Stack <string> operators = new Stack <string>(); int counter = 0; while (infixStack.Count > 0) { ++counter; if (debug) { Toolbelt.DisplayStack(infixStack, $"{counter}:: infixStack"); Toolbelt.DisplayStack(operators, $"{counter}:: operators"); Console.WriteLine(counter + ":: postfix: " + postFix.ToString() + "\n"); } char ch = infixStack.Peek(); StringBuilder newChars = new StringBuilder(); if (Char.IsNumber(ch)) { StringBuilder number = new StringBuilder(); number.Append(infixStack.Pop()); while (infixStack.Count > 0 && Char.IsNumber(infixStack.Peek())) { number.Append(infixStack.Pop()); } newChars.Append(number + " "); } else if (allowLetters && Char.IsLetter(ch)) { newChars.Append(infixStack.Pop() + " "); if (infixStack.Count > 0 && Char.IsLetter(infixStack.Peek())) { throw new SystemException($"{name} variables in infix value can only be one character"); } } else if (ch == '(') { operators.Push(infixStack.Pop().ToString()); } else if (ch == ')') { string op = operators.Pop(); while (op != "(") { newChars.Append(op + " "); if (operators.Count == 0) { break; } op = operators.Pop(); } infixStack.Pop(); // discard the left parenthesis } else { if (operators.Count > 0 && comparePrecedence(operators.Peek(), ch) >= 0) { string op = operators.Pop(); while (true) { newChars.Append(op + " "); if (operators.Count == 0) { break; } if (comparePrecedence(operators.Peek(), ch) < 0) { break; } op = operators.Pop(); } operators.Push(infixStack.Pop().ToString()); } else { operators.Push(infixStack.Pop().ToString()); } } int oldPFLengh = postFix.Length; int newCharsLength = newChars.Length; postFix.Append(newChars); if (postFix.Length != (oldPFLengh + newCharsLength)) { Console.WriteLine("Error appending to postfix"); Toolbelt.DisplayStack(operators, "operators"); Console.WriteLine($"postfix: {postFix}"); } } while (operators.Count > 0) { postFix.Append(operators.Pop() + " "); } if (infixStack.Count > 0 || operators.Count > 0) { Toolbelt.DisplayStack(infixStack, "infix"); Toolbelt.DisplayStack(operators, "operators"); } return(postFix.ToString().Trim()); }