Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我计算基本插入表达式的算法的缺陷在哪里?_C#_Algorithm_Parsing_Recursion - Fatal编程技术网

C# 我计算基本插入表达式的算法的缺陷在哪里?

C# 我计算基本插入表达式的算法的缺陷在哪里?,c#,algorithm,parsing,recursion,C#,Algorithm,Parsing,Recursion,我正在尝试实施一个类似于 输入: ~1^(2~&3)|1 69 11111 -12 [whatever NOT 69 XOR (11111 NAND -12) OR 69 equals] 输出: ~1^(2~&3)|1 69 11111 -12 [whatever NOT 69 XOR (11111 NAND -12) OR 69 equals] 所有位运算符具有相同的优先级,从左到右求值。我正在构建的算法基本上是 Get number n1 (or evaluati

我正在尝试实施一个类似于

输入:

~1^(2~&3)|1 69 11111 -12 
[whatever NOT 69 XOR (11111 NAND -12) OR 69 equals]
输出:

~1^(2~&3)|1 69 11111 -12 
[whatever NOT 69 XOR (11111 NAND -12) OR 69 equals]
所有位运算符具有相同的优先级,从左到右求值。我正在构建的算法基本上是

Get number n1 (or evaluation of expression in parenthesis)
Set result = n1
Get operator o1
Get number n2 (or evaluation of expression in parenthesis)
Set result = result op n2
Get operator o2
Get number n3 (or evaluation of expression in paranthesis)
Set result = result o2 n3
Etcetera
我还没有完全完成,但我所拥有的至少应该能够进行评估

((1)) 69
这将导致

69
我已经测试过了

(1) 69
导致

69
这意味着我只需要找出嵌套括号的问题所在

我的代码的相关部分,经过很好的注释,是。。。请容忍我在这里

    private static long? EvalInner ( string eqtn, Tuple<int,int> eqtnBnds, Dictionary<int,long> eqtnArgs)
    {
        //     eqtn: Equation to be parsed 
        // eqtnBnds: Bounds that define sub-equation being evaluated.
        // eqtnargs: Equation arguments

        // Parses and returns the evaluation of the equation eqtn in the bounds [eqtnBands.Item1, eqtnBnds.Item2)

        // Handle case of empty sub-equation:
        if (eqtnBnds.Item1 == eqtnBnds.Item2) throw new Exception(String.Format("Encountered empty equation at index {0}", eqtnBnds.Item1));


        long? result = null; 
        char? lastop = null; // last operator found 
        bool negateNextNum = false;
        PARSEMODE CURMODE = PARSEMODE.NUM; // beginning of equation should be a number since the form of the equation is
                                           // <NUM><OPER><NUM><OPER>...<OPER><NUM>
        int curidx = eqtnBnds.Item1, offend = eqtnBnds.Item2;
        while ( curidx < offend )
        {
            switch ( CURMODE )
            {
                case PARSEMODE.NUM: // Expecting character at current index to be the beginning of a 
                {
                    if ( eqtn[curidx] >= '0' && eqtn[curidx] <= '9' ) // beginning of the int corresponding to the argument index
                    {
                        int begidx = curidx;
                        // Increment curidx to one after the last digit or the end of the subequation
                        while ( ++curidx < offend && eqtn[curidx] >= '0' && eqtn[curidx] <= '9' );
                        // Try to get an integer representation of the argument. If an error is encountered in that parsing,
                        // throw an error. If the argument is one within the range of arguments given in the command line, 
                        // get its value and update result accordingly. If not, throw an error.
                        int argnum; 
                        if ( Int32.TryParse(eqtn.Substring(begidx, curidx - begidx), out argnum) )
                        {
                            if (eqtnArgs.ContainsKey(argnum))
                            {
                                result = (result != null ? BinOpEval(result, lastop, eqtnArgs[argnum]) : eqtnArgs[argnum]);
                                if (negateNextNum)
                                {
                                    result = ~result;
                                    negateNextNum = false;
                                }
                            }
                            else
                                throw new Exception(String.Format("Argument {0} found in the equation beginning at index {1} is out-of-bounds",
                                                                   argnum,
                                                                   begidx)
                                                    );
                        }
                        else
                        {
                            throw new Exception(String.Format("Trouble parsing argument number that begins at index {0}", 
                                                               begidx)
                                                );
                        }
                        CURMODE = PARSEMODE.OPER;
                    }
                    else if ( eqtn[curidx] == Calculator.OPENPAREN ) // beginning of subequation in paranthesis
                    {
                        int begidx = curidx, netparens = 1;
                        while ( ++curidx < offend && netparens != 0 )
                        {
                            if      ( eqtn[curidx] == Calculator.OPENPAREN  )  ++netparens;
                            else if ( eqtn[curidx] == Calculator.CLOSEPAREN )  --netparens;
                        }
                        if ( netparens != 0 ) // didn't find closing parenthesis
                            throw new Exception(String.Format("Couldn't find closing paranthesis for opening paranthesis at index {0}",
                                                               begidx)
                                                );
                        long? presult = null; // to be the result of the evaluated subequation between the set of parenthesis
                        try { presult = EvalInner(eqtn,new Tuple<int, int>(++begidx, curidx - begidx),eqtnArgs); }
                        catch ( Exception e ) { throw e; }
                        result = (result != null ? BinOpEval(result,lastop,presult) : presult);
                        if (negateNextNum)
                        {
                            result = ~result;
                            negateNextNum = false;
                        }
                        // Upon leaving this else-if block, curidx should be 1 after the closing paranthesis
                        // Expect operate to following closing paranthesis
                        CURMODE = PARSEMODE.OPER; // expecting operator after parens
                    }
                    else if ( eqtn[curidx] == Calculator.NOT ) // NOT symbol preceding number
                    {
                        negateNextNum = !negateNextNum;
                        ++curidx;
                        // CURMODE stays as num
                    }
                    else // unexpected character where beginning of number expected
                    {
                        throw new Exception(String.Format("Expected beginning of number at index {0}, instead got {1}",
                                                            curidx,
                                                            eqtn[curidx])
                                            );
                    }
                    break;
                }

                case PARSEMODE.OPER:
                {
                     // ... 
正在打印错误

Error: Encountered empty equation at index 2
让我来分析一下我的逻辑:

首先,
curidx=0
eqtn[curidx]='('
CURMODE=PARSEMODE.NUM
。这导致我们进入块

                    else if ( eqtn[curidx] == Calculator.OPENPAREN ) // beginning of subequation in paranthesis
                    {
                          // ... 
                    }
                    else if ( eqtn[curidx] == Calculator.OPENPAREN ) // beginning of subequation in paranthesis
                    {
                        int begidx = curidx, netparens = 1;
                        while ( ++curidx < offend && netparens != 0 )
                        {
                            if      ( eqtn[curidx] == Calculator.OPENPAREN  )  ++netparens;
                            else if ( eqtn[curidx] == Calculator.CLOSEPAREN )  --netparens;
                        }
                    if ( eqtn[curidx] >= '0' && eqtn[curidx] <= '9' ) // beginning of the int corresponding to the argument index
                    {
                       // ... 
                    }
在块部分的末尾

                        int begidx = curidx, netparens = 1;
                        while ( ++curidx < offend && netparens != 0 )
                        {
                            if      ( eqtn[curidx] == Calculator.OPENPAREN  )  ++netparens;
                            else if ( eqtn[curidx] == Calculator.CLOSEPAREN )  --netparens;
                        }
我们最终回到了街区

                    else if ( eqtn[curidx] == Calculator.OPENPAREN ) // beginning of subequation in paranthesis
                    {
                          // ... 
                    }
                    else if ( eqtn[curidx] == Calculator.OPENPAREN ) // beginning of subequation in paranthesis
                    {
                        int begidx = curidx, netparens = 1;
                        while ( ++curidx < offend && netparens != 0 )
                        {
                            if      ( eqtn[curidx] == Calculator.OPENPAREN  )  ++netparens;
                            else if ( eqtn[curidx] == Calculator.CLOSEPAREN )  --netparens;
                        }
                    if ( eqtn[curidx] >= '0' && eqtn[curidx] <= '9' ) // beginning of the int corresponding to the argument index
                    {
                       // ... 
                    }
之后,很明显,我们已经处理了
1
,将其与参数
69
关联,并通过调用堆栈传递回输出


哪里出错了?

这里元组的第二个元素是子方程的长度还是它的上界

presult = EvalInner(eqtn,new Tuple<int, int>(++begidx, curidx - begidx),eqtnArgs);
presult=EvalInner(eqtn,新元组(++begidx,curidx-begidx),eqtnArgs);
简单地使用两个清晰的命名参数可能会更有帮助,但基于您在递归调用之前的使用情况,它看起来似乎是上界,但您正在传递一个长度


也许这是唯一的问题?不确定。

这里元组的第二个元素是指子方程的长度还是它的上界

presult = EvalInner(eqtn,new Tuple<int, int>(++begidx, curidx - begidx),eqtnArgs);
presult=EvalInner(eqtn,新元组(++begidx,curidx-begidx),eqtnArgs);
简单地使用两个清晰的命名参数可能会更有帮助,但基于您在递归调用之前的使用情况,它看起来似乎是上界,但您正在传递一个长度


也许这是唯一的问题?不确定。

这里元组的第二个元素是指子方程的长度还是它的上界

presult = EvalInner(eqtn,new Tuple<int, int>(++begidx, curidx - begidx),eqtnArgs);
presult=EvalInner(eqtn,新元组(++begidx,curidx-begidx),eqtnArgs);
简单地使用两个清晰的命名参数可能会更有帮助,但基于您在递归调用之前的使用情况,它看起来似乎是上界,但您正在传递一个长度


也许这是唯一的问题?不确定。

这里元组的第二个元素是指子方程的长度还是它的上界

presult = EvalInner(eqtn,new Tuple<int, int>(++begidx, curidx - begidx),eqtnArgs);
presult=EvalInner(eqtn,新元组(++begidx,curidx-begidx),eqtnArgs);
简单地使用两个清晰的命名参数可能会更有帮助,但基于您在递归调用之前的使用情况,它看起来似乎是上界,但您正在传递一个长度


也许这是唯一的问题?不确定。

如果您的代码确实显示了相关的工作,并且修复它可能并不简单,那么我宁愿编写一个递归算法来提供您想要的功能

代码的基本思想如下:

  • removeAllParen
    启动解析过程。它执行基本的 有效性检查(即相同数量的开始括号和结束括号) 决定是否需要对执行实际分析的函数进行新调用。所有这些调用都递归地生成最终输出
  • removeOneParen
    只处理一组括号,最外部的括号(例如,从“((1))”)输出为“((1))”。它 查找第一个左括号和最后一个右括号
请记住,这只是一个示例代码,可帮助您了解如何递归解决此问题。这不是一种全面的括号解析方法,而是一种适合您的特定条件的方法。例如,第二个函数在类似“(1)(1)”的情况下会失败(尽管调整它并不太困难;但您必须依赖于与代码中的操作类似的开始/结束括号计数方法)


由于您的代码确实显示了相关的工作,并且修复它可能并不简单,所以我更喜欢编写一个递归算法来提供您想要的功能

代码的基本思想如下:

  • removeAllParen
    启动解析过程。它执行基本的 有效性检查(即相同数量的开始括号和结束括号) 决定是否需要对执行实际分析的函数进行新调用。所有这些调用都递归地生成最终输出
  • removeOneParen
    只处理一组括号,最外部的括号(例如,从“((1))”)输出为“((1))”。它 查找第一个左括号和最后一个右括号
请记住,这只是一个示例代码,可帮助您了解如何递归解决此问题。这不是一种全面的括号解析方法,而是一种适合您的特定条件的方法。例如,第二个函数在类似“(1)(1)”的情况下会失败(尽管调整它并不太困难;但您必须依赖于与代码中的操作类似的开始/结束括号计数方法)


由于您的代码确实显示了相关的工作,并且修复它可能并不简单,所以我更喜欢编写一个递归算法来提供您想要的功能

代码的基本思想如下:

  • removeAllParen
    启动解析过程。它执行基本的 有效性检查(即相同数量的开始括号和结束括号) 决定磨砺