Exemple #1
0
 public string ToHalfWidth(string str = null)
 {
     return(ResultPipe(StringTool.ToHalfWidth(str)));
 }
        /// <summary>
        /// 算术逆波兰表达式生成(也叫后缀表达式)Reverse Polish Notation
        /// </summary>
        /// 首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则
        /// 如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
        ///
        ///参考 https://bbs.csdn.net/topics/200010856
        private string BuildingRPN(string originExpression)
        {
            originExpression = originExpression.ToLower();//仅支持小写
            #region 先把所有支持的函数名替换为单个字符
            originExpression = StringTool.ToHalfWidth(originExpression);
            if (originExpression.IsMatch("[a-z]"))
            {
                originExpression = originExpression.ReplaceAllFromPairSet(_supportFunction);
            }
            #endregion

            StringBuilder originStr     = new StringBuilder(originExpression); //存入要转成的字符串为stringBuilder
            Stack         operatorStack = new Stack();                         //运算符栈
            StringBuilder parsingStr    = new StringBuilder();                 //存放处理后的结果

            char nowChar = ' ';                                                //遍历用当前字符

            //这一步遍历是挑出有用的字符,去除一些空格或无用字符等干扰因素
            for (int i = 0;
                 i < originStr.Length;
                 i++)
            {
                nowChar = originStr[i];
                //added c==',' for german culture
                if (char.IsDigit(nowChar) || nowChar == ',')//数字当然要了.
                {
                    parsingStr.Append(nowChar);
                }
                else if (char.IsWhiteSpace(nowChar))
                {
                    continue;
                }
                else if (char.IsLetter(nowChar))//注意可能会有用户乱输入的字母 还未处理
                {
                    parsingStr.Append(nowChar);
                }
                else
                {
                    switch (nowChar)//如果是其它字符...列出的要,没有列出的不要.
                    {
                    case '+':
                    case '-':
                    case '*':
                    case '/':
                    case '%':
                    case '^':
                    case '!':
                    case '(':
                    case ')':
                    case '.':
                        parsingStr.Append(nowChar);
                        break;

                    default:
                        continue;
                    }
                }
            }
            originStr = new StringBuilder(parsingStr.ToString());
            #region 对负号进行预转义处理.负号变单目运算符求反.
            for (int i = 0; i < originStr.Length - 1; i++)
            {
                if (originStr[i] == '-' && (i == 0 || originStr[i - 1] == '('))//这里是支持开头为负号的数字,但中间有数字负号必须用括号括起来
                {
                    originStr[i] = '!';
                }
            }
            //字符转义.
            #endregion
            #region 将中缀表达式变为后缀表达式.
            parsingStr = new StringBuilder();
            for (int i = 0; i < originStr.Length; i++)
            {
                if (char.IsDigit(originStr[i]) || originStr[i] == '.')//如果是数值.
                {
                    parsingStr.Append(originStr[i]);
                    //加入后缀式
                }
                else if (originStr[i] == '+' ||
                         originStr[i] == '-' ||
                         originStr[i] == '*' ||
                         originStr[i] == '/' ||
                         originStr[i] == '%' ||
                         originStr[i] == '^' ||
                         originStr[i] == '!' ||
                         isInSupportedArray(originStr[i]))
                {
                    #region 运算符处理 主要按照优先级刷新运算顺序
                    while (operatorStack.Count > 0) //栈不为空时
                    {
                        nowChar = (char)operatorStack.Pop();
                        //将栈中的操作符弹出.
                        if (nowChar == '(') //如果发现左括号.停.
                        {
                            operatorStack.Push(nowChar);
                            //将弹出的左括号压回.因为还有右括号要和它匹配.
                            break;
                            //中断.
                        }
                        else
                        {
                            if (Power(nowChar) < Power(originStr[i]))//如果优先级比上次的高,则压栈.
                            {
                                operatorStack.Push(nowChar);
                                break;
                            }
                            else
                            {
                                parsingStr.Append(' ');
                                parsingStr.Append(nowChar);
                            }
                            //如果不是左括号,那么将操作符加入后缀式中.
                        }
                    }
                    operatorStack.Push(originStr[i]);
                    //把新操作符入栈.
                    parsingStr.Append(' ');
                    #endregion
                }
                else if (originStr[i] == '(')//基本优先级提升
                {
                    operatorStack.Push('(');
                    parsingStr.Append(' ');
                }
                else if (originStr[i] == ')')       //基本优先级下调
                {
                    while (operatorStack.Count > 0) //栈不为空时
                    {
                        nowChar = (char)operatorStack.Pop();
                        //pop Operator
                        if (nowChar != '(')
                        {
                            parsingStr.Append(' ');
                            parsingStr.Append(nowChar);
                            //加入空格主要是为了防止不相干的数据相临产生解析错误.
                            parsingStr.Append(' ');
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else
                {
                    parsingStr.Append(originStr[i]);
                }
            }
            while (operatorStack.Count > 0)//这是最后一个弹栈啦.
            {
                parsingStr.Append(' ');
                parsingStr.Append(operatorStack.Pop());
            }
            #endregion
            parsingStr.Append(' ');
            return(FormatSpace(parsingStr.ToString()));
            //在这里进行一次表达式格式化.这里就是后缀式了.
        }