zoukankan      html  css  js  c++  java
  • 【栈】控制台计算器实现四则运算

    这篇文章主要介绍实现一个控制台界面的计算器,计算用户输入一个完整的、有效的、四则运算式。

    一下是具体步骤:

    1. 定义一个操作的基类,用来实现类似于 "A+B“ 的运算

    View Code
        public class Operation
    {
    public Operation()
    { }

    public Operation(int a, int b)
    {
    _numA = a;
    _numB = b;
    }

    protected int _numA, _numB;

    public int NumA {
    get { return _numA; }
    set { _numA = value; }
    }
    public int NumB {
    get { return this._numB; }
    set { this._numB = value; }
    }

    public virtual int Calculate()
    {
    return _numA + _numB;
    }
    }

    2. 定义对应的四则运算类

    加法运算,直接使用父类默认的方法
        class AddOperation:Operation
    {
    public AddOperation():base()
    { }

    public AddOperation(int a, int b):base(a, b)
    {

    }
    }
    减法运算
        public class MinusOperation:Operation
    {
    public MinusOperation()
    : base()
    { }

    public MinusOperation(int a, int b)
    : base(a, b)
    { }

    public override int Calculate()
    {
    return _numA - _numB;
    }
    }
    乘法运算
        public class MultipleOperation:Operation
    {
    public MultipleOperation()
    { }

    public MultipleOperation(int a, int b)
    : base(a, b)
    { }

    public override int Calculate()
    {
    return _numA * _numB;
    }
    }
    除法运算
        public class DivideOperation:Operation
    {
    public DivideOperation()
    { }

    public DivideOperation(int a, int b)
    : base(a, b)
    { }

    public override int Calculate()
    {
    int result = 0;
    int.TryParse(( _numA / _numB).ToString(),out result);
    return result;
    }
    }

    3. 定义辅助方法

    将栈里面的元素反转,同时将反转后的栈作为结果返回
            static Stack ReverseStack(Stack stack)
    {
    Stack temp = new Stack();
    while (stack.Count > 0)
    {
    temp.Push(stack.Pop());
    }
    return temp;
    }
    从栈里面按栈的顺序获取表达式
            static string GetEquationFromStack(Stack stack)
    {
    StringBuilder equationBuilder = new StringBuilder();
    while (stack.Count > 0)
    {
    equationBuilder.Append(stack.Pop().ToString());
    }
    return equationBuilder.ToString();
    }
    计算表达式并重置参与运算的符号和式子中的两个数值
            private static void BeginCalculate(StringBuilder builderA, StringBuilder builderB, ref string sign)
    {
    //使用反射获取对应的四则运算类
    Operation operation = (Operation)Assembly.Load("Calculator").CreateInstance(string.Format("Calculator.{0}", GetMappedString(sign)));
    operation.NumA = int.Parse(builderA.ToString());
    operation.NumB = int.Parse(builderB.ToString());
    string result = operation.Calculate().ToString();

    //计算完成后需要进行如下操作
    // 1.用计算的结果替换第一个数字,用来参加下一次的运算
    // 2.将符号重置为空
    // 3.将第二个数字重置
    builderA.Clear();
    builderA.Append(result);
    sign = string.Empty;
    builderB.Clear();
    }
    通过传入的符号返回对应的操作类的名称,返回值会用于反射得到对应的类。返回值和类的名称一致,便于操作
            static string GetMappedString(string c)
    {
    switch (c)
    {
    case "+":
    return "AddOperation";
    case "-":
    return "MinusOperation";
    case "*":
    return "MultipleOperation";
    case "/":
    return "DivideOperation";
    default:
    return string.Empty;
    }
    }

    4. 定义对于简单算式(不包含括号的算式)的运算

    View Code
            private static string StackCalculate(string equation)
    {
    string sign = string.Empty; //操作符,“+”、“-”、“*”、“/”
    string result = string.Empty;
    StringBuilder builderA = new StringBuilder(); //参与运算的第一个数字
    StringBuilder builderB = new StringBuilder(); //参与运算的第二个数字
    Stack stack = new Stack(); //这里的栈用来存放低优先级(+、-)的运算

    char[] chars = equation.ToCharArray();

    //不论算式的第一个字符是什么都传给第一个数字,这样可以避免第一个字符是“-”对操作的影响
    builderA.Append(chars[0]);

    //遍历剩下的字符串,把所有乘除法用其对应的结果代替,并把结果压到栈里
    for (int i = 1; i < chars.Length; i++)
    {
    switch (chars[i])
    {
    case '+':
    case '-':
    if (sign == string.Empty)
    {
    //如果是加减号,运算符值为空,则给运算符赋值为加号或者减号
    sign = chars[i].ToString();
    }
    else
    {
    //如果运算符不为空,则表示builderA,sign 和 builderB可以组成一个完成的算式
    //开始计算
    BeginCalculate(builderA, builderB, ref sign);

    //给运算符赋值为加号或者减号
    sign = chars[i].ToString();
    }
    break;
    case '*':
    case '/':
    if (sign == string.Empty)
    {
    //运算符值为空,则给运算符赋值为乘号或者除号
    sign = chars[i].ToString();
    }
    else if (sign == "+" || sign == "-")
    {
    //如果之前的运算符是加减号,则重置存储在builderA, sign 和builderB组成的式子
    //并把之前的builderA 和运算符压到栈里
    stack.Push(builderA.ToString());
    stack.Push(sign);
    builderA.Clear();
    builderA.Append(builderB.ToString());
    builderB.Clear();
    sign = chars[i].ToString();
    }
    else
    {
    //如果运算符不为空,且是乘除号,则进行计算
    BeginCalculate(builderA, builderB, ref sign);

    //给运算符赋值
    sign = chars[i].ToString();
    }
    break;
    default:
    //当前字符不是运算符
    if (sign == string.Empty)
    {
    //如果操作符为空,则表示现在需要给参与运算的第一个数字赋值
    builderA.Append(chars[i]);
    }
    else
    {
    //如果操作符不为空,则表示现在需要给参与运算的第二个数字赋值
    builderB.Append(chars[i]);
    }
    break;
    }
    }

    //处理第一次循环剩余的算式,并把结果压入栈里
    if (sign != string.Empty)
    {
    BeginCalculate(builderA, builderB, ref sign);
    stack.Push(builderA.ToString());
    }

    //对栈里存放的低优先级表达式进行处理
    if (stack.Count < 1)
    {
    return "Error";
    }
    else if (stack.Count == 1)
    {
    return stack.Pop().ToString();
    }
    else
    {
    //从栈里获取低优先级表达式
    string finalEquation = GetEquationFromStack(ReverseStack(stack));
    //对表达式进行计算,并将结果返回
    return StackCalculate(finalEquation);
    }
    }

    5. 定义复杂算式(有括号)的运算,会调用4里面创建的方法

    View Code
            public static string Run(string equation)
    {
    Stack stack = new Stack(); // 1.新建一个栈,用来存放部分表达式

    string result = string.Empty;

    // 2.遍历所有字符,把所有括号里面的算式转换成对应的结果
    // 比如 “1+2+3(9-7/1)+5*4”就会转换成“1+2+3*2+5*4”
    foreach (char c in equation.ToCharArray())
    {
    // 2.1只要遇到的字符不是“)”就压到栈里面
    if (c != ')')
    {
    stack.Push(c);
    }
    else
    {
    // 2.2如果遇到“)”,就把栈顶的值取出来,直到遇到“(”
    // 此时就会得到这个括号里完整的算式
    Stack tempStack = new Stack();
    while (stack.Peek().ToString() != "(")
    {
    tempStack.Push(stack.Pop());
    }
    stack.Pop(); //弹出栈顶元素

    int temp = 0; // 临时变量,用来支持下面判断语句的正常运行

    // 2.3判断栈顶的元素是不是数字,如果是数字,则表示该数字和括号里面的式子是乘法关系
    //这时需要人为的往栈里面压入一个"*"
    if (int.TryParse(stack.Peek().ToString(), out temp))
    {
    stack.Push('*');
    }

    // 2.4把括号里面式子的结果压到栈里
    stack.Push(StackCalculate(GetEquationFromStack(tempStack)));
    }
    }

    //3. 计算栈里面存放的最终表达式,并返回最终结果
    result = StackCalculate(GetEquationFromStack(ReverseStack(stack)));
    return result;
    }

    6. 测试

    View Code
            static void Main(string[] args)
    {
    Console.WriteLine("Please input the equation you want to calculate:");
    string equation = Console.ReadLine();

    Console.WriteLine("The result is {0}", Run(equation));

    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
    }


    运行结果如下图:












  • 相关阅读:
    createjs 利用createjs 写拼图功能
    canvas 利用canvas中的globalCompositeOperation 绘制刮奖 效果
    git 命令
    cmd 打开gitshell
    Grunt完成对LESS实时编译
    nodejs gulp less编辑
    canvas 绘制 矩形 圆形
    canvas绘制时钟
    juqery easyui
    vue-router(第2节课,妙味课堂)
  • 原文地址:https://www.cnblogs.com/silverbullet11/p/2372444.html
Copyright © 2011-2022 走看看