Click here to Skip to main content
15,895,084 members
Articles / Programming Languages / C#
Article

how to program a windows standard calculator

Rate me:
Please Sign up or sign in to vote.
1.50/5 (11 votes)
25 Aug 2008CPOL 74.4K   1.9K   25   17
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)


    Written By
    Software Developer acca
    China China
    I love to communicate with eachother.

    Comments and Discussions

     
    GeneralThanks Pin
    Member 450722313-Sep-12 16:06
    Member 450722313-Sep-12 16:06 
    QuestionWhy not put the delegates in the Dictionary? Pin
    PIEBALDconsult16-Nov-09 5:16
    mvePIEBALDconsult16-Nov-09 5:16 
    Generalm_CE_Click problem Pin
    edwardxu8883-Sep-09 12:01
    edwardxu8883-Sep-09 12:01 
    GeneralRe: m_CE_Click problem Pin
    edwardxu8883-Sep-09 12:10
    edwardxu8883-Sep-09 12:10 
    QuestionCan you add... Pin
    Ethnica5-Jan-09 20:20
    Ethnica5-Jan-09 20:20 
    GeneralNot Like Standard Calculator Pin
    Arman S.27-Aug-08 3:02
    Arman S.27-Aug-08 3:02 
    GeneralRe: Not Like Standard Calculator Pin
    vivounicorn27-Aug-08 4:04
    vivounicorn27-Aug-08 4:04 
    Generalnot coded properly.. Pin
    Abhishek Sur26-Aug-08 11:08
    professionalAbhishek Sur26-Aug-08 11:08 
    GeneralRe: not coded properly.. Pin
    User 5924126-Aug-08 17:41
    User 5924126-Aug-08 17:41 
    GeneralRe: not coded properly.. Pin
    Abhishek Sur26-Aug-08 22:29
    professionalAbhishek Sur26-Aug-08 22:29 
    GeneralRe: not coded properly.. Pin
    vivounicorn26-Aug-08 23:39
    vivounicorn26-Aug-08 23:39 
    Generalnot 4 if Pin
    Mehmet CINCI26-Aug-08 2:40
    Mehmet CINCI26-Aug-08 2:40 
    GeneralNice coding style Pin
    okoji Cyril26-Aug-08 3:45
    okoji Cyril26-Aug-08 3:45 
    GeneralRe: Nice coding style Pin
    vivounicorn26-Aug-08 23:40
    vivounicorn26-Aug-08 23:40 
    GeneralRe: not 4 if Pin
    vivounicorn26-Aug-08 23:47
    vivounicorn26-Aug-08 23:47 
    GeneralRe: not 4 if Pin
    nicholas_pei25-Feb-09 22:45
    nicholas_pei25-Feb-09 22:45 
    GeneralRe: not 4 if Pin
    shofb3-Sep-09 18:02
    shofb3-Sep-09 18:02 
    "but i maintain that using "switch" is not conducive to coding expansion. "

    This shows a clear lack of programming skills.

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

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