计算器修正代码

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    public class CharExt
    {
        public int index;
        public char value;
    }
    public class LinkChar
    {
        public string expstr;
        /// <summary>
        /// 索引链表元素
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public LinkChar find(int index)
        {
            LinkChar tmp = this.header;
            while (tmp != null)
            {
                if (tmp.ch.index == index)
                {
                    return tmp;
                }
                tmp = tmp.next;
            }
            return null;
        }
        //获取链表两个节点之间的内容
        public static string GetContent(LinkChar start, LinkChar end)
        {
            string content = string.Empty;
            LinkChar tmp = start;
            while (tmp != end)
            {
                content += tmp.ch.value.ToString();
                tmp = tmp.next;
            }
            content += end.ch.value;
            return content;

        }
        public void show()
        {
            LinkChar tmp = this.header;
            while (tmp != null)
            {
                Debug.WriteLine(tmp.ch.index + ":" + tmp.ch.value);
                tmp = tmp.next;
            }
        }
        /// <summary>
        /// 将链表内容还原成字符串
        /// </summary>
        /// <returns></returns>
        /// <summary>
        /// 将链表内容还原成字符串
        /// </summary>
        /// <returns></returns>
        public string GetExpStr()
        {
            string str = string.Empty;
            LinkChar tmp = this.header;
            while (tmp != null)
            {
                str += tmp.ch.value;
                tmp = tmp.next;
            }
            return str;
        }
        public LinkChar GetPatialLink(int start, int end)
        {
            return null;
        }
        public LinkChar()
        {

        }
        public void Push(string expstr)
        {
            var cs = expstr.ToCharArray();
            for (int i = 0; i < cs.Length; i++)
            {
                char item = cs[i];
                if (i == 0)
                {

                    this.current = new LinkChar() { ch = new CharExt() { value = cs[i], index = i } };
                    this.header = this.current;
                }
                else
                {
                    var tmpNext = new LinkChar() { ch = new CharExt() { value = cs[i], index = i } };
                    if (i == cs.Length - 1)
                    {
                        laster = tmpNext;
                    }
                    this.current.next = tmpNext;
                    this.current.next.prior = this.current;
                    this.current = this.current.next;
                }


            }
        }
        public LinkChar laster;
        public LinkChar header;
        public CharExt ch;
        public LinkChar current;
        public LinkChar prior;
        public LinkChar next;

    }
    public class kuohaodui
    {
        //左括号
        public int index1;
        //右括号
        public int index2;
    }
    //括号栈
    public class KuoHaoStack
    {
        //用于匹配括号对
        public Stack<kuohaodui> dui { get; set; }

        public static bool jiaoyan(string expstr)
        {
            int count1 = 0;
            int count2 = 0;
            char[] chs = expstr.ToCharArray();
            for (int i = 0; i < chs.Length; i++)
            {
                char ch = chs[i];
                if (ch == '(')
                {
                    count1++;

                }
                else if (ch == ')')
                {
                    count2++;
                }

            }
            bool p = count1 == count2;
            return p;
        }
    }
    public class DbContext
    {
        public Dictionary<string, double> dic = new Dictionary<string, double>();

        internal double getValue(string key)
        {
            return dic[key];
        }
        public Dictionary<string, double> Map(string exprStr)
        {
            exprStr = exprStr.Replace("(", "").Replace(")", "");

            //定义非终结符
            string[] sb = { "+", "-", "*", "/", "^" };

            string copyExpStr = exprStr.Clone().ToString();
            foreach (char ch in exprStr.ToCharArray())
            {
                if (sb.Contains(ch.ToString()))
                {
                    copyExpStr = copyExpStr.Replace(ch.ToString(), ",");
                }

            }
            var items = copyExpStr.Split(',');

            //解析有几个参数要传递

            foreach (string ch in items)
            {

                if (!sb.Contains(ch.ToString()) && !Regex.IsMatch(ch, @"[0-9]+(.d+)?") && ch != "(" && ch != ")")
                {

                    //解决重复参数的问题

                    if (!dic.ContainsKey(ch.ToString()))
                    {
                        Console.WriteLine("请输入" + ch + "的值:");

                        string in1 = Console.ReadLine();

                        dic.Add(ch.ToString(), double.Parse(in1));

                    }

                }

            }

            return dic;

        }


    }
    public abstract class Expression
    {
        public abstract double jieshi(DbContext context);


    }
    public class AddExpression : Expression
    {
        public Expression Left;
        public Expression Right;
        public AddExpression(Expression left, Expression right)
        {
            this.Left = left;
            this.Right = right;
        }

        public override double jieshi(DbContext context)
        {
            return Left.jieshi(context) + Right.jieshi(context);
        }
    }
    public class SubExpression : Expression
    {
        public Expression Left;
        public Expression Right;
        public SubExpression(Expression left, Expression right)
        {
            this.Left = left;
            this.Right = right;
        }

        public override double jieshi(DbContext context)
        {
            return Left.jieshi(context) - Right.jieshi(context);
        }

    }

    public class MultExpression : Expression
    {
        public Expression Left;
        public Expression Right;
        public MultExpression(Expression left, Expression right)
        {
            this.Left = left;
            this.Right = right;
        }

        public override double jieshi(DbContext context)
        {
            return Left.jieshi(context) * Right.jieshi(context);
        }

    }
    public class DivedeExpression : Expression
    {
        public Expression Left;
        public Expression Right;
        public DivedeExpression(Expression left, Expression right)
        {
            this.Left = left;
            this.Right = right;
        }
        public override double jieshi(DbContext context)
        {
            return Left.jieshi(context) / Right.jieshi(context);
        }

    }
    public static class StringEXT
    {
        public static bool IsNum(this string str)
        {
            return Regex.IsMatch(str, @"(\d+)(.(\d+))?");
        }
    }
    public class VarExpression : Expression
    {
        private string key;
        public VarExpression(string key)
        {
            this.key = key;
        }
        public override double jieshi(DbContext context)
        {
            return context.getValue(this.key);
        }
    }
    public class Calculator
    {
        /// <summary>
        /// 定义优先级 索引出来的值越小 优先级越高
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, int> youxianji()
        {
            Dictionary<string, int> youxian = new Dictionary<string, int>();
            youxian.Add("(", 3);
            youxian.Add("*", 2);
            youxian.Add("/", 2);
            youxian.Add("+", 1);
            youxian.Add("-", 1);
            return youxian;
        }
        /// <summary>
        /// 终结符字典
        /// </summary>
        /// <returns></returns>
        public Dictionary<string, double> dic()
        {
            DbContext context = new DbContext();
            context.Map(linkList.GetExpStr());
            return context.dic;
        }

        public string findNextElement(LinkChar firtFuHao, LinkChar chs)
        {
            //a+(b+c)*(c/d)
            //a+b*(c+d)
            //a+(b*c*d)+e
            //(((a+b+c))*d+(e+f+g))*h

            LinkChar nextFuHao = null;
            //循环开始元素
            LinkChar linkElementStart = firtFuHao;
            while (true)
            {
                if (linkElementStart.next.ch.value == '(')
                {
                    int index2 = KuohaoduiStack.FirstOrDefault(x => x.index1 == linkElementStart.next.ch.index).index2;
                    nextFuHao = chs.find(index2 + 1);
                    if (nextFuHao == null)
                    {
                        string content = LinkChar.GetContent(firtFuHao.next, chs.find(index2));
                        return content;
                    }
                    char c = nextFuHao.ch.value;
                    if (c != '+' && c != '-' && c != '*' && c != '/')
                    {
                        string content = LinkChar.GetContent(firtFuHao.next, nextFuHao.prior);
                        return content;
                    }
                }
                else
                {
                    if (linkElementStart.next == chs.laster)
                    {
                        nextFuHao = linkElementStart.next;
                    }
                    else
                    {
                        nextFuHao = linkElementStart.next.next;
                    }
                }
                //优先级
                Dictionary<string, int> yxj = youxianji();
                if (nextFuHao == null)
                {
                    string s = string.Empty;
                    LinkChar ch = firtFuHao.next;
                    while (ch != null)
                    {
                        s += ch.ch.value.ToString();
                        ch = ch.next;
                    }
                    return s;
                }
                string key2 = nextFuHao?.ch.value.ToString();
                string key1 = linkElementStart.ch.value.ToString();
                int you2 = key2 != null && !yxj.ContainsKey(key2) ? 1 : yxj[key2 == null ? "+" : key2];
                int you1 = yxj[key1];
                if (you2 <= you1)
                {
                    break;
                }
                linkElementStart = nextFuHao;
            }
            var tmp = firtFuHao;
            string str = string.Empty;
            int count = 0;
            while (true)
            {
                int maxSize = youxianji().ContainsKey(nextFuHao.ch.value.ToString())
                    ? nextFuHao.ch.index - firtFuHao.ch.index - 1
                    : nextFuHao.ch.index - firtFuHao.ch.index;
                if (count < maxSize)
                {
                    tmp = tmp.next;
                    count++;
                    str += tmp.ch.value.ToString();

                }
                else
                {
                    count = 0;
                    break;
                }
            }
            return str;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="chs">输入的表达式链表</param>
        /// <param name="startIndex">符号(+-*/)之后的第一个字符</param>
        /// <returns></returns>
        public string GetRightKey(LinkChar chs, int startIndex)
        {
            //a+b*(c+d)
            //a+(b*c*d)+e
            LinkChar fuhao = chs.find(startIndex - 1);
            //找到下个元素的符号
            return findNextElement(fuhao, chs);
        }
        /// <summary>
        /// 是否是未匹配的右括号
        /// </summary>
        /// <param name="t1"></param>
        /// <param name="startP"></param>
        /// <returns></returns>
        public bool weiPiPeiYouKuoHao(LinkChar youP)
        {
            return _KuohaoduiStack.Count(x => x.index2 == youP.ch.index) <= 0;
        }
        public bool weiPiPeiZuoKuoHao(LinkChar zuoP)
        {
            return _KuohaoduiStack.Count(x => x.index1 == zuoP.ch.index) <= 0;
        }
        public LinkChar linkList;
        private Stack<kuohaodui> _KuohaoduiStack = new Stack<kuohaodui>();
        public Stack<kuohaodui> KuohaoduiStack
        {
            get
            {
                //1.括号匹配
                //()+() 
                //(()+())
                //(())
                LinkChar tmp = linkList.header;
                while (tmp != null)
                {
                    //当匹配左括号的时候,找到匹配的右括号,压入括号栈内
                    if (tmp.ch.value == '(')
                    {
                        //(a+b)+(a*(c+d))/e

                        //开始匹配的链表元素(右括号)
                        var startP = tmp.next;


                        while (startP != null)
                        {
                            if (startP.ch.value == ')' && weiPiPeiYouKuoHao(startP))
                            {
                                var t1 = startP.prior;

                                while (true)
                                {
                                    //找到左括号
                                    if (t1.ch.value != '(')
                                    {
                                        t1 = t1.prior;
                                        continue;
                                    }
                                    else
                                    {
                                        //不仅要是左括号,还必须是未匹配的左括号
                                        if (!weiPiPeiZuoKuoHao(t1))
                                        {
                                            t1 = t1.prior;
                                            continue;
                                        }
                                        if (_KuohaoduiStack.Count(x => x.index1 == t1.ch.index && x.index2 == startP.ch.index) <= 0)
                                        {
                                            _KuohaoduiStack.Push(new kuohaodui { index1 = t1.ch.index, index2 = startP.ch.index });
                                            break;
                                        }


                                    }
                                }

                            }

                            startP = startP.next;
                        }


                    }

                    tmp = tmp.next;
                }
                return _KuohaoduiStack;
            }
        }

        public Dictionary<string, double> zhongjiefuDic { get; set; }
        public Expression cal(LinkChar chs)
        {
            Expression left = null;
            Expression right = null;
            //linkList = chs;
            string rightkey = string.Empty;
            Stack<Expression> stack = new Stack<Expression>();
            LinkChar tmp = chs.header;
            var jieshu = 0;
            Dictionary<string, double> maps = zhongjiefuDic;
            while (tmp != null)
            {
                if (tmp == chs.laster || tmp == null)
                {
                    jieshu = 1;
                }
                char c = tmp.ch.value;
                switch (c)
                {
                    case '+':
                        left = stack.Pop();
                        rightkey = GetRightKey(chs, tmp.ch.index + 1);
                        if (maps.ContainsKey(rightkey))
                        {
                            right = new VarExpression(rightkey);
                        }
                        else
                        {
                            var tmp11 = new LinkChar();
                            tmp11.header = tmp.next;
                            tmp11.laster = tmp11.header;
                            for (int i = 0; i < rightkey.Length - 1; i++)
                            {
                                tmp11.laster = tmp11.laster.next;
                            }
                            right = cal(tmp11);
                        }
                        if (tmp.ch.index + 1 == chs.laster.ch.index)
                        {
                            jieshu = 1;
                        }
                        for (int i = 0; i < rightkey.Length; i++)
                        {
                            tmp = tmp.next;
                        }
                        stack.Push(new AddExpression(left, right));
                        if (tmp == chs.laster || tmp == null)
                        {
                            return stack.Pop();
                        }
                        break;
                    case '-':
                        left = stack.Pop();
                        rightkey = GetRightKey(chs, tmp.ch.index + 1);
                        if (maps.ContainsKey(rightkey))
                        {
                            right = new VarExpression(rightkey);
                        }
                        else
                        {
                            var tmp11 = new LinkChar();
                            tmp11.header = tmp.next;
                            tmp11.laster = tmp11.header;
                            for (int i = 0; i < rightkey.Length - 1; i++)
                            {
                                tmp11.laster = tmp11.laster.next;
                            }
                            right = cal(tmp11);
                        }
                        if (tmp.ch.index + 1 == chs.laster.ch.index)
                        {
                            jieshu = 1;
                        }
                        for (int i = 0; i < rightkey.Length; i++)
                        {
                            tmp = tmp.next;
                        }
                        stack.Push(new SubExpression(left, right));
                        if (tmp == chs.laster || tmp == null)
                        {
                            return stack.Pop();
                        }
                        break;
                    case '*':
                        left = stack.Pop();
                        rightkey = GetRightKey(chs, tmp.ch.index + 1);
                        if (maps.ContainsKey(rightkey))
                        {
                            right = new VarExpression(rightkey);
                        }
                        else
                        {
                            var tmp11 = new LinkChar();
                            tmp11.header = tmp.next;
                            tmp11.laster = tmp11.header;
                            for (int i = 0; i < rightkey.Length - 1; i++)
                            {
                                tmp11.laster = tmp11.laster.next;
                            }
                            right = cal(tmp11);
                        }
                        if (tmp.ch.index + 1 == chs.laster.ch.index)
                        {
                            jieshu = 1;
                        }
                        for (int i = 0; i < rightkey.Length; i++)
                        {
                            tmp = tmp.next;
                        }
                        stack.Push(new MultExpression(left, right));
                        if (tmp == chs.laster || tmp == null)
                        {
                            return stack.Pop();
                        }
                        break;
                    case '/':
                        left = stack.Pop();
                        rightkey = GetRightKey(chs, tmp.ch.index + 1);
                        if (maps.ContainsKey(rightkey))
                        {
                            right = new VarExpression(rightkey);
                        }
                        else
                        {
                            var tmp11 = new LinkChar();
                            tmp11.header = tmp.next;
                            tmp11.laster = tmp11.header;
                            for (int i = 0; i < rightkey.Length - 1; i++)
                            {
                                tmp11.laster = tmp11.laster.next;
                            }
                            right = cal(tmp11);
                        }
                        if (tmp.ch.index + 1 == chs.laster.ch.index)
                        {
                            jieshu = 1;
                        }
                        for (int i = 0; i < rightkey.Length; i++)
                        {
                            tmp = tmp.next;
                        }
                        stack.Push(new DivedeExpression(left, right));
                        if (tmp == chs.laster || tmp == null)
                        {
                            return stack.Pop();
                        }
                        break;
                    case '(':
                        int lIndex = tmp.ch.index;
                        int start = tmp.ch.index + 1;
                        int end = KuohaoduiStack.FirstOrDefault(x => x.index1 == lIndex).index2 - 1;
                        var tmp1 = new LinkChar();
                        tmp1.header = chs.find(start);
                        tmp1.laster = chs.find(end);
                        for (int i = 0; i < (end - start + 1) + 1; i++)
                        {
                            tmp = tmp.next;
                        }
                        //tmp = tmp1.laster;
                        stack.Push(cal(tmp1));
                        if (tmp == chs.laster || tmp == null)
                        {
                            return stack.Pop();
                        }
                        break;
                    default:
                        Expression varExpression = new VarExpression(c.ToString());
                        stack.Push(varExpression);
                        break;
                }
                tmp = tmp.next;
                if (tmp != null && tmp.ch.value == ')')
                {
                    tmp = tmp.next;
                }
                if (jieshu == 1 || tmp == null)
                {
                    break;

                }
            }
            return stack.Pop();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {

            while (true)
            {
                string str = Console.ReadLine(); //"a+(b*c+d)+e";
                char[] chs1 = str.ToCharArray();
                //1.括号校验 start
                bool p = KuoHaoStack.jiaoyan(str);
                if (p == false)
                {
                    Console.WriteLine("请重新输入!!");
                    break;
                }
                //1. 括号校验end


                //2. 字符放到LinkChar里 strat
                List<CharExt> chs = new List<CharExt>();
                LinkChar linklist = new LinkChar();
                linklist.Push(str.Replace(" ", ""));
                //字符放到LinkChar里 end


                //3. 产生上下文
                DbContext context = new DbContext();
                context.Map(str);

                //4.设计计算器产生表达式
                Calculator calulator = new Calculator();
                calulator.zhongjiefuDic = context.dic;
                calulator.linkList = linklist;
                Expression expression = calulator.cal(linklist);

                //5.进行表达式的解释出结果
                double result = expression.jieshi(context);

                //6.输出结果
                Console.WriteLine(str + "=" + result);


            }
            Console.ReadKey();
        }
    }
}

 

posted on 2017-01-18 18:03  听哥哥的话  阅读(337)  评论(0编辑  收藏  举报

导航