首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >后缀和一元/二元运算符的中缀

后缀和一元/二元运算符的中缀
EN

Stack Overflow用户
提问于 2010-03-12 18:06:15
回答 2查看 8.9K关注 0票数 3

在内存中,我有一段代码可以将中缀表达式转换为表达式树。这个很好用。只有一个小麻烦。我只是连接出如何正确地涉及一元运算符(正确的结合运算符)。

使用以下中缀表达式:

代码语言:javascript
复制
+1 + +2 - -3 - -4

我期望RPN为:

代码语言:javascript
复制
1+2++3-4--

然而,没有一个我能找到的在线中缀-post转换器以我期望的方式处理这个例子。有没有人清楚地解释了如何处理正确的结合运算符,特别是那些可能被误认为一元运算符的二元运算符?

编辑/澄清:我想知道在从中缀到后缀的转换过程中如何处理一元运算符。例如,将相同的'-‘字符识别为一元而不是二元运算符,因此具有不同的优先级。我会考虑使用状态机,也许有两个状态,但是...?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-03-13 22:19:46

那么,您需要在解析阶段确定给定的运算符是否为二进制/一元。这样做之后,在创建RPN时,可以将运算符标记为采用2个或1个参数。

您可以尝试使用Shunting Yard算法进行解析(同时创建RPN ),该算法也设计为使用一元运算符。

在任何情况下,如果你只关心一元的+或-,当你看到一个“意外”出现的+或-时,你可以插入一个带括号的0。

例如

+1 + +2 - -3 - -4

您应该能够通过它并转换为

(0+1) + (0+2) - (0-3) - (0-4)

现在你不需要担心一元的+或者-,并且可以忘记用它们所带参数的数量来标记运算符。

票数 6
EN

Stack Overflow用户

发布于 2016-12-22 01:08:54

也许这个混乱的C#代码会对你有所帮助。一元运算符在算术运算中具有最高优先级,因此它们的优先级将更高。为了识别一元运算符,我采用了一个布尔变量unary,它将在每个运算符令牌之后设置为true,在操作数之后设置为false。您必须对一元加和减运算符使用不同的符号,以便在PFE中区分一元运算符和二元运算符。这里'#‘和'~’用于描述后缀表达式(PFE)中的一元加和一元减。

您可以使用此方法处理所有情况,如1+-1,1+(-1),1-1,1+--1。

代码语言:javascript
复制
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DSA
{
    class Calculator
    {
        string PFE;
        public Calculator()
        {
            Console.WriteLine("Intializing Calculator");
        }

        public double Calculate(string expression)
        {
            ConvertToPost(expression);
            return CalculatePOST();
        }

        public void ConvertToPost(string expression)
        {
            expression = "(" + expression + ")";

            var temp = new DSA.Stack<char>();
            string ch = string.Empty;
            bool unary = true;
            char a;
            foreach (var b in expression)
            {
                a = b;
                if (!a.IsOperator()) {
                    ch += a.ToString();
                    unary = false;
                }
                else
                {
                    if (ch!=string.Empty) 
                    PFE += ch+",";
                    ch = string.Empty;
                    if(a!='(' && a!=')')
                    {
                        if (unary == true)
                        {
                            if (a == '-') a = '~'; else if (a == '+') a = '#'; else throw new InvalidOperationException("invalid input string");
                        }
                        try
                        {
                            if (a.Precedence() <= temp.Peek().Precedence())
                            {
                                PFE += temp.Pop().ToString() + ",";
                            }
                          }
                        catch(InvalidOperationException e)
                        {

                        }

                            temp.Push(a);
                            unary = true;
                    }
                    if (a == '(') { temp.Push(a);}
                    if(a==')')
                    {
                       for(char t=temp.Pop();t!='(';t=temp.Pop())
                        {
                            PFE += t.ToString() + ","; 
                        }
                    }
                }

            }

        }

        public double CalculatePOST()
        {
            var eval = new Stack<double>();
            string ch = string.Empty;
            bool skip = false;
            foreach(char c in PFE)
            {
                if(!c.IsOperator())
                {
                    if (c == ',')
                    {
                        if (skip == true)

                        {
                            skip = false;
                            continue;
                        }
                        eval.Push(Double.Parse(ch));
                        ch = string.Empty;
                    }
                    else ch += c;
                }
                else
                {
                    if (c == '~')
                    {
                        var op1 = eval.Pop();
                        eval.Push(-op1);
                    }
                    else if (c == '#') ;
                    else
                    {
                        var op2 = eval.Pop();
                        var op1 = eval.Pop();
                        eval.Push(Calc(op1, op2, c));
                    }
                    skip = true;
                }
              }
            return eval.Pop();
        }

        private double Calc(double op1, double op2, char c)
        {   
           switch(c)
            {

                case '+':
                    return op1 + op2;
                case '-':
                    return op1 - op2;
                case '*':
                    return op1 * op2;
                case '%':
                    return op1 % op2;
                case '/':
                    return op1 / op2;
                case '^':
                    return float.Parse(Math.Pow(op1,op2).ToString());
                default:
                    throw new InvalidOperationException();
            }
        }
    }


    public static class extension
    {
        public static bool IsOperator(this char a)
        {
            char[] op = {'+','-','/','*','(',')','^','!','%','~','#'};
             return op.Contains(a);
        }

        public static int Precedence(this char a)
        {
            if (a == '~' || a== '#')
                return 1;
            if (a == '^')
                return 0;
            if (a == '*' || a == '/' || a=='%')
                return -1;
            if (a == '+' || a == '-')
                return -2;
            return -3;       
        }       
    }
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2431863

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档