zoukankan      html  css  js  c++  java
  • 计算器修正代码

    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();
            }
        }
    }
  • 相关阅读:
    快速排序(详解)
    14.linux-platform机制实现驱动层分离(详解)
    13.Linux键盘按键驱动 (详解)
    Linux-hexdump命令调试event驱动—详解(13)
    Android开发final的用法
    Android控件RecyclerView的基本用法
    搜索关键词分析——以个人博客网站为例
    java.net.SocketException: Software caused connection abort: socket write error
    Android layout属性大全
    java中 label 配合 break continue 使用方法
  • 原文地址:https://www.cnblogs.com/kexb/p/6297714.html
Copyright © 2011-2022 走看看