C#使用链表List,栈Stack实现四则算术运算【小括号、加减乘除】

已知一个 字符串表达式【四则运算】,求出 加减乘除 以及小括号的运算结果。

在控制台应用程序中,新建一个类 ArithmeticUtil.cs。详细代码与逻辑注释如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestLinq
{
    /// <summary>
    /// 四则算术运算【小括号、加减乘除】
    /// </summary>
    public class ArithmeticUtil
    {
        /*
         * 已知一个 字符串表达式,求出 加减乘除 以及小括号的运算结果。
         * string s="(3+5.2)*8-100/20+5.8*((2+3)*4)";
        */

        /// <summary>
        /// 计算含有小括号表达式的结果
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static double CalculateResult(string expression) 
        {
            //先计算出小括号表达式,并去除所有的小括号
            Stack<int> stackLeftBrackets = new Stack<int>();//左括号索引
            while (expression.Contains(")")) //如果存在小括号,就计算出结果后 逐个去除
            {
                stackLeftBrackets.Clear();
                for (int index = 0; index < expression.Length; index++)
                {
                    if (expression[index] == '(')
                    {
                        stackLeftBrackets.Push(index);
                    }
                    else if (expression[index] == ')')
                    {
                        //stackRightBrackets.Push(i);
                        //遇到右括号时,找出最近的左括号
                        if (stackLeftBrackets.Count == 0)
                        {
                            Console.WriteLine("表达式非法,小括号不是成对出现的【存在右括号,没有找到对应的左括号】");
                            return 0;
                        }
                        int leftIndex = stackLeftBrackets.Pop();
                        string subExpression = expression.Substring(leftIndex + 1, index - leftIndex - 1);
                        double innerResult = CalculateWithoutBrackets(subExpression);
                        //字符串计算出结果后,去除一个小括号后,重新赋值
                        expression = expression.Substring(0, leftIndex) + innerResult + expression.Substring(index + 1);
                        //Console.WriteLine(expression);
                        break;
                    }
                }
            }
            if (stackLeftBrackets.Count > 0)
            {
                Console.WriteLine("表达式非法,小括号不是成对出现的【存在左括号,没有找到右括号】");
                return 0;
            }
            //此时,表达式中所有的小括号都已经计算完毕,无小括号。只用运行四则运算即可。
            double result = CalculateWithoutBrackets(expression);
            return result;
        }

        /// <summary>
        /// 没有括号的四则运算 加减乘除 
        /// </summary>
        /// <param name="subExpression"></param>
        /// <returns></returns>
        public static double CalculateWithoutBrackets(string subExpression) 
        {
            //表达式形如:4.5+2*6.9-13.8/5+6
            string str = "";
            List<double> listNumber = new List<double>();
            List<char> listOper = new List<char>();
            for (int index = 0; index < subExpression.Length; index++)
            {
                if (subExpression[index] == '+' || subExpression[index] == '-' || subExpression[index] == '*' || subExpression[index] == '/')
                {
                    listNumber.Add(double.Parse(str));
                    str = "";
                    listOper.Add(subExpression[index]);
                }
                else 
                {
                    str = str + subExpression[index];
                }
            }
            //最后 还要将最后一个数字放入链表
            listNumber.Add(double.Parse(str));
            //收集所有的运算符到集合listOper,收集所有的数字到集合listNumber。其中listNumber的个数比listOper的个数多一个
            //Console.WriteLine(string.Join("||",listNumber));
            //Console.WriteLine(string.Join("||", listOper));
            //先乘除,过滤出乘除符号,计算出最新结果后,删除该乘除符号
            for (int i = 0; i < listOper.Count; i++)
            {
                if (listOper[i] == '*' || listOper[i] == '/') 
                {
                    double first = listNumber[i];
                    double second = listNumber[i+1];
                    double tempResult = 0;
                    if (listOper[i] == '*')
                    {
                        tempResult = first * second;
                    }
                    else 
                    {
                        tempResult = first / second;
                    }
                    //Console.WriteLine("乘除结果:" + tempResult);
                    //计算出 乘(除)号两边的结果,从集合中移除 【乘(除)号右边的数】。同时将算术结果重新赋值给 【乘(除)号左边的数】
                    listNumber[i] = tempResult;
                    listNumber.RemoveAt(i + 1);
                    listOper.RemoveAt(i);
                    i--;
                }
            }
            //Console.WriteLine(string.Join("||", listNumber));
            //Console.WriteLine(string.Join("||", listOper));
            //现在只有加减操作,依次从左到右计算即可
            for (int i = 0; i < listOper.Count; i++)
            {
                double first = listNumber[i];
                double second = listNumber[i + 1];
                double tempResult = 0;
                if (listOper[i] == '+')
                {
                    tempResult = first + second;
                }
                else
                {
                    tempResult = first - second;
                }
                //Console.WriteLine("加减结果:" + tempResult);
                //计算出 乘(除)号两边的结果,从集合中移除 【乘(除)号右边的数】。同时将算术结果重新赋值给 【乘(除)号左边的数】
                listNumber[i] = tempResult;
                listNumber.RemoveAt(i + 1);
                listOper.RemoveAt(i);
                i--;
            }
            //最后的结果 listNumber只留下一个元素,也就是计算结果。listOper元素为空
            //Console.WriteLine(string.Join("||", listNumber));
            //Console.WriteLine(string.Join("||", listOper) == "");
            return listNumber.Count > 0 ? listNumber[0] : 0;
        }
    }
}

在默认的Program.cs的Main函数下 输入测试代码:

            string exp = "4.5+2*6.9-13.8/5+6";
            double calResult = ArithmeticUtil.CalculateResult(exp);
            Console.WriteLine("{0}={1}", exp, calResult);
            exp = "(3+5.2)*8-100/20+5.8*((2+3)*4)";
            calResult = ArithmeticUtil.CalculateResult(exp);
            Console.WriteLine("{0}={1}", exp, calResult);
            Console.ReadLine();

测试运行效果如下图:

猜你喜欢

转载自blog.csdn.net/ylq1045/article/details/86625761