| using System; |
| using System.Collections.Generic; |
| using System.ComponentModel; |
| using System.Data; |
| using System.Drawing; |
| using System.Linq; |
| using System.Text; |
| using System.Windows.Forms; |
| |
| namespace NickGeorge.Cis300.Calculator |
| { |
| /// <summary> |
| /// Main class for calculator |
| /// </summary> |
| public partial class Calculator : Form |
| { |
| /// <summary> |
| /// Stores total of calculator input. |
| /// </summary> |
| private Double _total = 0.0; |
| |
| /// <summary> |
| /// Boolean to tell if calculator is in display or input modes. |
| /// </summary> |
| private Boolean _input = false; |
| |
| /// <summary> |
| /// Stack of all used operators. |
| /// </summary> |
| private Stack<char> _operators = new Stack<char>(); |
| |
| /// <summary> |
| /// Stack of all used operands. |
| /// </summary> |
| private Stack<double> _operands = new Stack<double>(); |
| |
| /// <summary> |
| /// Method which intializes GUI |
| /// </summary> |
| public Calculator() |
| { |
| InitializeComponent(); |
| } |
| |
| /// <summary> |
| /// Method which appends given text/integer to display and stores the current value if necessary |
| /// </summary> |
| /// <param name="str">Input string to append to the display</param> |
| private void AppendTo(String str) |
| { |
| if(this._input) |
| this.uxSum.Text = this.uxSum.Text + str; |
| else |
| { |
| this._input = true; |
| this.uxSum.Text = str; |
| } |
| } |
| |
| /// <summary> |
| /// Returns the precedence of given operator |
| /// </summary> |
| /// <param name="c">Operator</param> |
| /// <returns>Int value of precedence 0-2</returns> |
| private int GetPrecedence(char c) |
| { |
| switch(c) |
| { |
| case '*': |
| case '/': |
| return 2; |
| |
| case '+': |
| case '-': |
| return 1; |
| |
| default: |
| return 0; |
| } |
| } |
| |
| /// <summary> |
| /// Will record an arithmatic sequence. |
| /// </summary> |
| /// <param name="Operator">Operator of the sequence</param> |
| /// <param name="Operand">First value of the sequence</param> |
| private void StartSequence(char Operator, double Operand) |
| { |
| this._input = false; |
| this._operands.Push(Operand); |
| this._operators.Push(Operator); |
| this.uxSum.Text = Operand.ToString(); |
| } |
| |
| /// <summary> |
| /// Performs all of the pending operations up to, but not including, the most recent pending operation having precedence less than or equal to a given precedence |
| /// </summary> |
| /// <param name="precedence">value of precedence at which to stop calculating</param> |
| /// <param name="operand">Last pending operand to use in calculation</param> |
| /// <returns>Value of calcuation</returns> |
| private double Calculate(int precedence, double operand) |
| { |
| double total = operand; |
| |
| while(this._operators.Count > 0 && this.GetPrecedence(this._operators.Peek()) > (precedence - 1)) |
| { |
| switch (this._operators.Pop()) |
| { |
| case '+': |
| total += this._operands.Pop(); |
| break; |
| |
| case '-': |
| total = this._operands.Pop() - total; |
| break; |
| |
| case '*': |
| total *= this._operands.Pop(); |
| break; |
| |
| case '/': |
| total = this._operands.Pop() / total; |
| break; |
| } |
| } |
| |
| return total; |
| } |
| |
| /// <summary> |
| /// Clears totals and sets display to "0" |
| /// </summary> |
| private void uxClear_Click(object sender, EventArgs e) |
| { |
| this._total = 0.0; |
| this.uxSum.Text = "0"; |
| this._operands.Clear(); |
| this._operators.Clear(); |
| this._input = false; |
| } |
| |
| /// <summary> |
| /// Adds 0 to display |
| /// </summary> |
| private void uxZero_Click(object sender, EventArgs e) |
| { |
| AppendTo("0"); |
| } |
| |
| /// <summary> |
| /// Adds 1 to display |
| /// </summary> |
| private void uxOne_Click(object sender, EventArgs e) |
| { |
| AppendTo("1"); |
| } |
| |
| /// <summary> |
| /// Adds 2 to display |
| /// </summary> |
| private void uxTwo_Click(object sender, EventArgs e) |
| { |
| AppendTo("2"); |
| } |
| |
| /// <summary> |
| /// Adds 3 to display |
| /// </summary> |
| private void uxThree_Click(object sender, EventArgs e) |
| { |
| AppendTo("3"); |
| } |
| |
| /// <summary> |
| /// Adds 4 to display |
| /// </summary> |
| private void uxFour_Click(object sender, EventArgs e) |
| { |
| AppendTo("4"); |
| } |
| |
| /// <summary> |
| /// Adds 5 to display |
| /// </summary> |
| private void uxFive_Click(object sender, EventArgs e) |
| { |
| AppendTo("5"); |
| } |
| |
| /// <summary> |
| /// Adds 6 to display |
| /// </summary> |
| private void uxSix_Click(object sender, EventArgs e) |
| { |
| AppendTo("6"); |
| } |
| |
| /// <summary> |
| /// Adds 7 to display |
| /// </summary> |
| private void uxSeven_Click(object sender, EventArgs e) |
| { |
| AppendTo("7"); |
| } |
| |
| /// <summary> |
| /// Adds 8 to display |
| /// </summary> |
| private void uxEight_Click(object sender, EventArgs e) |
| { |
| AppendTo("8"); |
| } |
| |
| /// <summary> |
| /// Adds 9 to display |
| /// </summary> |
| private void uxNine_Click(object sender, EventArgs e) |
| { |
| AppendTo("9"); |
| } |
| |
| /// <summary> |
| /// If in input mode, will invert the sign associated with the current value |
| /// </summary> |
| private void uxInvert_Click(object sender, EventArgs e) |
| { |
| if(this._input) |
| { |
| if(this.uxSum.Text.CompareTo("0") != 0) |
| { |
| if(this.uxSum.Text.Contains("-")) |
| this.uxSum.Text = this.uxSum.Text.Substring(1); |
| else |
| this.uxSum.Text = "-" + this.uxSum.Text; |
| } |
| } |
| } |
| |
| /// <summary> |
| /// If in input mode, will add a decimal to the current value |
| /// </summary> |
| private void uxDecimal_Click(object sender, EventArgs e) |
| { |
| if (!this._input) |
| { |
| this._input = true; |
| this._total = Double.Parse(this.uxSum.Text); |
| this.uxSum.Text = "0."; |
| } |
| else |
| { |
| if (!this.uxSum.Text.Contains('.')) |
| this.uxSum.Text = this.uxSum.Text + "."; |
| } |
| } |
| |
| /// <summary> |
| /// If two values are given, will operate the two values together to a new value |
| /// </summary> |
| private void uxEqual_Click(object sender, EventArgs e) |
| { |
| this._input = false; |
| double output = Double.Parse(this.uxSum.Text); |
| while(this._operands.Count > 0) |
| output = this.CloseParenth(output); |
| this.uxSum.Text = output.ToString(); |
| } |
| |
| /// <summary> |
| /// Creates an addition sequence |
| /// </summary> |
| private void uxAdd_Click(object sender, EventArgs e) |
| { |
| this.StartSequence('+', this.Calculate(this.GetPrecedence('+'), Double.Parse(this.uxSum.Text))); |
| } |
| |
| /// <summary> |
| /// Creates a subtration sequence |
| /// </summary> |
| private void uxSubtract_Click(object sender, EventArgs e) |
| { |
| this.StartSequence('-', this.Calculate(this.GetPrecedence('-'), Double.Parse(this.uxSum.Text))); |
| } |
| |
| /// <summary> |
| /// Creates a multiplication sequence |
| /// </summary> |
| private void uxMultiply_Click(object sender, EventArgs e) |
| { |
| this.StartSequence('*', this.Calculate(this.GetPrecedence('*'), Double.Parse(this.uxSum.Text))); |
| } |
| |
| /// <summary> |
| /// Creates a division sequence |
| /// </summary> |
| private void uxDivide_Click(object sender, EventArgs e) |
| { |
| this.StartSequence('/', this.Calculate(this.GetPrecedence('/'), Double.Parse(this.uxSum.Text))); |
| } |
| |
| /// <summary> |
| /// Creates a open parenthesis to the order of operations |
| /// </summary> |
| private void uxOpenParenth_Click(object sender, EventArgs e) |
| { |
| this._input = false; |
| this._operators.Push('('); |
| } |
| |
| /// <summary> |
| /// Creates a close parenthesis to the order of operations |
| /// </summary> |
| private void uxCloseParenth_Click(object sender, EventArgs e) |
| { |
| this._input = false; |
| this.uxSum.Text = this.CloseParenth(Double.Parse(this.uxSum.Text)).ToString(); |
| } |
| |
| /// <summary> |
| /// Will close a set of parenthesis |
| /// </summary> |
| /// <param name="op">Current input</param> |
| /// <returns>Calculated number</returns> |
| private double CloseParenth(double op) |
| { |
| double number = this.Calculate(this.GetPrecedence('('), op); |
| if (this._operators.Count > 0) |
| this._operators.Pop(); |
| return number; |
| } |
| } |
| } |