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(); } } }