Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

how to program a windows standard calculator

0.00/5 (No votes)
25 Aug 2008 1  
This article is help beginners to program a windows standard calculator

Introduction

C# is an interesting language,in my opinion,beginners always need some samples for learning,I hope my article can help them.As your know,the function of windows calculator is so strong even standard version,it can process expression like this:"2+==*.3-4+5===" or "2.5*3-.6+4.4=+==-=" and so on,I think make a calculator without any bug is hard,so a good design can help you to decrease your bug,so I will try to do this.

Using the code

  • CalculatorOperation - a class to provide basic function of calculator
  • .
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
    
    namespace NewCalculator
    {
        public enum Operator { NO_OP, ADD, SUB, MUL, DIV, EQUAL, SQRT, BACKWARDS,PERCENT }
    
        internal class CalculatorOperation
        {
            public delegate decimal MathematicOperating(decimal opt1, decimal opt2);
    
            public delegate decimal OtherOperating(decimal opt1);
    
            public static Hashtable hashTable;
    
            static CalculatorOperation()
            {
                hashTable = new Hashtable();
                hashTable.Add("+", Operator.ADD);
                hashTable.Add("-", Operator.SUB);
                hashTable.Add("*", Operator.MUL);
                hashTable.Add("/", Operator.DIV);
                hashTable.Add("=", Operator.EQUAL);
            }
    
            private static decimal Add(decimal op1, decimal op2)
            {
                return decimal.Add(op1, op2);
            }
    
            private static decimal Sub(decimal op1, decimal op2)
            {
                return decimal.Subtract(op1, op2);
            }
    
            private static decimal Mul(decimal op1, decimal op2)
            {
                return decimal.Multiply(op1, op2);
            }
    
            private static decimal Div(decimal op1, decimal op2)
            {
               // if (op2 != 0)
                    return decimal.Divide(op1, op2);
                //else
                 //   return decimal.MinValue;
            }
    
            private static decimal Sqrt(decimal op1)
            {
                return (decimal)Math.Sqrt((double)op1);
            }
    
            private static decimal Backwords(decimal op1)
            {
                return 1 / op1;
            }
    
            private static decimal Percent(decimal op1)
            {
                return op1 / 100;
            }
    
    
            public static MathematicOperating Mathematic(Operator opt)
            {
                MathematicOperating MO = null;
    
                if (opt == Operator.ADD)
                {
                    MO = new MathematicOperating(CalculatorOperation.Add);
                    return MO;
                }
    
                if (opt == Operator.SUB)
                {
                    MO = new MathematicOperating(CalculatorOperation.Sub);
                    return MO;
                }
    
                if (opt == Operator.MUL)
                {
                    MO = new MathematicOperating(CalculatorOperation.Mul);
                    return MO;
                }
    
                if (opt == Operator.DIV)
                {
                    MO = new MathematicOperating(CalculatorOperation.Div);
                    return MO;
                }
    
                
                return null;
            }
    
            public static OtherOperating OtherMathematic(Operator opt)
            {
                OtherOperating MO;
    
                if (opt == Operator.SQRT)
                {
                    MO = new OtherOperating(CalculatorOperation.Sqrt);
                    return MO;
                }
                if (opt == Operator.BACKWARDS)
                {
                    MO = new OtherOperating(CalculatorOperation.Backwords);
                    return MO;
                }
    
                if (opt == Operator.PERCENT)
                {
                    MO = new OtherOperating(CalculatorOperation.Percent);
                    return MO;
                }
                return null;
            }
        }
    }
    		

  • CalculatorController - a class to simulate a calculator
  • .

    Blocks of code should be set as style "Formatted" like this:

    			//
    			// Any source code blocks look like this
    			//
    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace NewCalculator
    {
        public delegate void Change(string str);
    
        public class CalculatorController:IController
        {
            #region private field
             private decimal mStore = 0;
            private decimal mResult = 0;
            private string mDisplay = string.Empty;
    
            /// 
            /// the first operator
             /// 
            private decimal opt1 = 0;
            /// 
            /// the second operator
             /// 
            private decimal opt2 = 0;
            /// 
            /// whether the first operator is ready
            /// 
            private bool opt1IsReady = false;
            /// 
            /// whether the second operator is ready
            /// 
            private bool opt2IsReady = false;
    
            /// 
            /// to store current operartor
             /// 
            private Operator currentOperator = Operator.NO_OP;
    
            /// 
            /// whether click operator buttons
            /// 
            private bool isClickOperatingButton = false;
            /// 
            /// whether click digital number
            /// 
            private bool isClickDigitalButton = false;
    
            private bool isCalculating = false;
    
            private Change onChange = null;
    
            #endregion
                            
            #region public attribute
             /// 
            /// get or set   mDisplay
             /// 
            public string Display
            {
                get
                {
                    return this.mDisplay;
                }
                set
                {
                    this.mDisplay = value;
                }
            }
            /// 
            /// get or set  onChange
             /// 
            public Change OnChange
            {
                get
                {
                    return this.onChange;
                }
                set
                {
                    onChange = value;
                }
    
            }
            #endregion
    
            #region private method
    
             /// 
            /// to do mathematic expression
            /// 
            /// operator
            /// whether success
            private bool MathematicProcess(Operator curOpt)
            {
                if (currentOperator == Operator.NO_OP)
                {
                    if (curOpt != Operator.EQUAL)
                        this.currentOperator = curOpt;
                    this.opt1IsReady = true;
                    this.opt2IsReady = false;
                    this.isCalculating = false;
                    return false;
                }
                else
                {
                    if (Operator.EQUAL != curOpt)
                    {
                        if (this.opt1IsReady && this.opt2IsReady && !this.isCalculating)
                        {
                            this.mResult = CalculatorOperation.Mathematic(this.currentOperator)(this.opt1, this.opt2);
                            this.mDisplay = this.mResult.ToString();
                            opt1 = this.mResult;
                            this.opt1IsReady = true;
                            this.opt2IsReady = false;                        
                               this.isCalculating = false;
                        }
                        if (curOpt != this.currentOperator)
                        {
                            this.currentOperator = curOpt;
                        }
                        {
                            this.opt1 = decimal.Parse(this.mDisplay.ToString());
                            this.opt2IsReady = false;
                            this.isCalculating = false;
                        }
    
                    }
                   
                      if (Operator.EQUAL == curOpt)
                    {
                        if (this.opt1IsReady && this.opt2IsReady)
                        {
                            this.mResult = CalculatorOperation.Mathematic(this.currentOperator)(this.opt1, this.opt2);
                            opt1 = this.mResult;
                            this.mDisplay = this.mResult.ToString();
                            this.opt1IsReady = true;
                            this.opt2IsReady = true;
                        }
                        if (this.opt1IsReady && !this.opt2IsReady)
                        {
                            /////////////////////////////////
                            this.mResult = decimal.Parse(this.mDisplay.ToString());
    
                            this.mResult = CalculatorOperation.Mathematic(this.currentOperator)(this.mResult, this.opt1);
                            this.mDisplay = this.mResult.ToString();
                            this.opt1IsReady = true;
                            this.opt2IsReady = false;
                        }
                        
                        this.isCalculating = true;
                    }
                    return true;
                }
            }
    
            #endregion
    
            #region public method
             /// 
            /// deal with "C" button
             /// 
            public void InitializeCalculatorController()
            {
                this.mDisplay = string.Empty;
                this.mResult = 0;
                this.opt1 = 0;
                this.opt2 = 0;
                this.opt1IsReady = false;
                this.opt2IsReady = false;
                currentOperator = Operator.NO_OP;
                isClickOperatingButton = true;
                isCalculating = false;
            }
    
            /// 
            /// deal with "MC"、"MR"、"MS"、"M+"
             /// 
            /// current function
            public void FunctionButtonClick(string sSub)
            {
                if ("MC" == sSub.Trim().ToUpper())
                {
                    this.mStore = 0;
    
                    if (OnChange != null)
                        OnChange("");
                    return;
                }
                if ("MR" == sSub.Trim().ToUpper())
                {
                    /////////////////////////////////////////////
                    this.isCalculating = false;
    
                    this.mDisplay = this.mStore.ToString();
                    return;
                }
                if ("MS" == sSub.Trim().ToUpper())
                {
                    this.mStore = decimal.Parse(this.mDisplay);
    
                    if (OnChange != null)
                        OnChange("M");
                    return;
                }
                if ("M+" == sSub.Trim().ToUpper())
                {
                    this.mStore += decimal.Parse(this.mDisplay);
    
                    if (OnChange != null)
                        OnChange("M");
    
                    return;
                }
            }
    
            /// 
            /// deal with "backspace"
             /// 
            public void BackspaceClick()
            {
                if (!this.isCalculating)
                {
                    if (this.mDisplay.Length > 1)
                    {
                        this.mDisplay = this.mDisplay.Substring(0, this.mDisplay.Length - 1);
                    }
                    else
                    {
                        this.mDisplay = "0";
                    }
                }
            }
    
            /// 
            /// deal with number buttons
             /// 
            /// current number
            public bool DigitalButtonClick(string sSub)
            {
                try
                {
                    isClickDigitalButton = true;
    
                    if ("+/-" != sSub.Trim() && !(sSub.Equals("0") && sSub.Equals(this.mDisplay.Trim())))
                    {
                        if (!sSub.Equals("0") && this.mDisplay.Equals("0") && !sSub.Equals("."))
                        {
                            this.mDisplay = sSub;
                            return true;
                        }
    
                        if (sSub.Equals("."))
                        {
                            if (this.mDisplay.IndexOf(".") >= 0
                            {
                                if (this.isCalculating)
                                {
                                    this.mDisplay = "0";
                                    isClickOperatingButton = false;
                                    return true;
                                }
                                return false;
                            }
    
                            if (this.isClickOperatingButton)
                            {
                                if (this.mDisplay.Equals("0") || this.mDisplay.Equals(""))
                                {
                                    this.mDisplay = "0";
                                    isClickOperatingButton = false;
                                    return true;
                                }
                            }
                        }
    
                        if (!this.isClickOperatingButton)
                        {
                            this.mDisplay += sSub;
                        }
                        else
                        {
                            isClickOperatingButton = false;
                            this.mDisplay = sSub;
                        }
                    }
                    else
                        if ("+/-" == sSub.Trim())
                        {
                            decimal tmp = 0.0m - decimal.Parse(this.mDisplay);
                            if (tmp == 0)
                            {
                                if (this.mDisplay.IndexOf('-') >= 0)
                                    this.mDisplay = this.mDisplay.Substring(1, this.mDisplay.Length-1);
                                else
                                    this.mDisplay = "-" + tmp.ToString();
                            }
                            else
                                this.mDisplay = tmp.ToString();
                        }
                    return true;
                }
                catch
                {
                    return false;
                }
            }
    
            /// 
            /// deal with operator
             /// 
            /// current operator
            public bool OperatingButtonClick(string sSub)
            {
                try
                {
                    if (!this.opt1IsReady)
                    {
                        this.opt1 = decimal.Parse(this.mDisplay);
                        this.opt1IsReady = true;
                    }
                    else
                        if (isClickDigitalButton && !this.opt2IsReady)
                        {
                            this.opt2IsReady = true;
                            this.opt2 = decimal.Parse(this.mDisplay);
                        }
                    isClickOperatingButton = true;
                    isClickDigitalButton = false;
    
                    MathematicProcess((Operator)CalculatorOperation.hashTable[sSub]);
    
                    return true;
                }
                catch
                {
                    return false;
                }
            }
    
            /// 
            /// to calculate expression
             /// 
            /// expression
            /// result
            /// whether success
            public bool ExecuteExpression(string expression, Change change)
            {
                bool flag = true;
    
                foreach (char ch in expression)
                {
                    if (ch >= '0' && ch <= '9' || '.' == ch)
                    {
                        flag = this.DigitalButtonClick(ch.ToString());
                        change(this.mDisplay);
                        continue;
                    }
    
                    if ('+' == ch || '-' == ch || '*' == ch || '/' == ch || '=' == ch)
                    {
                        flag = this.OperatingButtonClick(ch.ToString());
                        change(this.mDisplay);
                        continue;
                    }
                }
    
                return flag;
            }
    
            /// 
            /// other operator
             /// 
            /// operator
            /// result
            public decimal OtherCalculationg(string opt)
            {
                if ("sqrt" == opt.ToLower())
                {
                    this.isClickOperatingButton = true;
                    return CalculatorOperation.OtherMathematic(Operator.SQRT)(decimal.Parse(this.mDisplay));
                }
                if ("1/x" == opt.ToLower())
                {
                    this.isClickOperatingButton = true;
                    return CalculatorOperation.OtherMathematic(Operator.BACKWARDS)(decimal.Parse(this.mDisplay));
                }
                if ("%" == opt.ToLower())
                {
                    this.isClickOperatingButton = true;
                    return CalculatorOperation.OtherMathematic(Operator.PERCENT)(decimal.Parse(this.mDisplay));
                }
                return 0.0m;
            }
            #endregion
        }
    }
    	

    History

  • 08.01.2008 - Initial release
  • License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here