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