Click here to Skip to main content
Licence CPOL
First Posted 25 Aug 2008
Views 26,293
Downloads 456
Bookmarked 25 times

how to program a windows standard calculator

By | 25 Aug 2008 | Article
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;
    
            /// <summary>
            /// the first operator
             /// </summary>
            private decimal opt1 = 0;
            /// <summary>
            /// the second operator
             /// </summary>
            private decimal opt2 = 0;
            /// <summary>
            /// whether the first operator is ready
            /// </summary>
            private bool opt1IsReady = false;
            /// <summary>
            /// whether the second operator is ready
            /// </summary>
            private bool opt2IsReady = false;
    
            /// <summary>
            /// to store current operartor
             /// </summary>
            private Operator currentOperator = Operator.NO_OP;
    
            /// <summary>
            /// whether click operator buttons
            /// </summary>
            private bool isClickOperatingButton = false;
            /// <summary>
            /// whether click digital number
            /// </summary>
            private bool isClickDigitalButton = false;
    
            private bool isCalculating = false;
    
            private Change onChange = null;
    
            #endregion
                            
            #region public attribute
             /// <summary>
            /// get or set   mDisplay
             /// </summary>
            public string Display
            {
                get
                {
                    return this.mDisplay;
                }
                set
                {
                    this.mDisplay = value;
                }
            }
            /// <summary>
            /// get or set  onChange
             /// </summary>
            public Change OnChange
            {
                get
                {
                    return this.onChange;
                }
                set
                {
                    onChange = value;
                }
    
            }
            #endregion
    
            #region private method
    
             /// <summary>
            /// to do mathematic expression
            /// </summary>
            /// <param name="curOpt">operator</param>
            /// <returns>whether success</returns>
            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
             /// <summary>
            /// deal with "C" button
             /// </summary>
            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;
            }
    
            /// <summary>
            /// deal with "MC"、"MR"、"MS"、"M+"
             /// </summary>
            /// <param name="sSub">current function</param>
            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;
                }
            }
    
            /// <summary>
            /// deal with "backspace"
             /// </summary>
            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";
                    }
                }
            }
    
            /// <summary>
            /// deal with number buttons
             /// </summary>
            /// <param name="sSub">current number</param>
            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;
                }
            }
    
            /// <summary>
            /// deal with operator
             /// </summary>
            /// <param name="sSub">current operator</param>
            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;
                }
            }
    
            /// <summary>
            /// to calculate expression
             /// </summary>
            /// <param name="expression">expression</param>
            /// <param name="change">result</param>
            /// <returns>whether success</returns>
            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;
            }
    
            /// <summary>
            /// other operator
             /// </summary>
            /// <param name="opt">operator</param>
            /// <returns>result</returns>
            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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    About the Author

    vivounicorn

    Software Developer
    acca
    China China

    Member

    I love to communicate with eachother.

    Sign Up to vote   Poor Excellent
    Add a reason or comment to your vote: x
    Votes of 3 or less require a comment

    Comments and Discussions

     
    You must Sign In to use this message board. (secure sign-in)
     
    Search this forum  
     FAQ
        Noise  Layout  Per page   
      Refresh
    QuestionWhy not put the delegates in the Dictionary? PinmemberPIEBALDconsult5:16 16 Nov '09  
    Generalm_CE_Click problem Pinmemberedwardxu88812:01 3 Sep '09  
    GeneralRe: m_CE_Click problem Pinmemberedwardxu88812:10 3 Sep '09  
    QuestionCan you add... PinmemberEthnica20:20 5 Jan '09  
    GeneralNot Like Standard Calculator PinmemberArman Z. Sahakyan3:02 27 Aug '08  
    GeneralRe: Not Like Standard Calculator Pinmembervivounicorn4:04 27 Aug '08  
    Generalnot coded properly.. PinmemberAbhishek sur11:08 26 Aug '08  
    GeneralRe: not coded properly.. Pinmemberpwasser17:41 26 Aug '08  
    GeneralRe: not coded properly.. PinmemberAbhishek sur22:29 26 Aug '08  
    GeneralRe: not coded properly.. Pinmembervivounicorn23:39 26 Aug '08  
    Generalnot 4 if Pinmembermehmet_cinci2:40 26 Aug '08  
    GeneralNice coding style Pinmemberokoji Cyril3:45 26 Aug '08  
    GeneralRe: Nice coding style Pinmembervivounicorn23:40 26 Aug '08  
    GeneralRe: not 4 if Pinmembervivounicorn23:47 26 Aug '08  
    GeneralRe: not 4 if Pinmembernicholas_pei22:45 25 Feb '09  
    GeneralRe: not 4 if Pinmembershofb18:02 3 Sep '09  

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    Permalink | Advertise | Privacy | Mobile
    Web02 | 2.5.120517.1 | Last Updated 25 Aug 2008
    Article Copyright 2008 by vivounicorn
    Everything else Copyright © CodeProject, 1999-2012
    Terms of Use
    Layout: fixed | fluid