存储前缀表达式(递归)

时间:2015-11-11 19:28:41

标签: c++ recursion expression prefix

感谢阅读。我真的需要一些帮助。我遇到了一个问题,涉及我使用递归方法来存储用户输入的完全标记的前缀表达式。在这个特定的例子中,数字用符号" n"标识,而符号等就像它们一样。所以,例如,这个:

%18 + 14 /(12 - 11) - 1183%17

将输入到命令提示符中:

  • %n18 / n14 - n12 n11%n1183 n17

现在,在项目早期,我的任务是存储一个中缀表达式,但是从已经构建的代码中获得了很多帮助。所以,这就是我对处理完全带括号的中缀函数所拥有的。我必须使用类似的方式创建一个方法(实际上在同一个文件中),然后从那里开始使用它。我已经掌握了打印功能,所以我真的只是想让存储空间正常运行。这是读取中缀表达式的代码:

Expr * readFPInfix(std::istream & infile)
{
    static std::string ops("*+/%-");
    char symbol;
    infile >> symbol;
    if (symbol == 'n')
    {
        long number;
        infile >> number;
        return new Atom(number);
    }
    else if (symbol == '(')
    {
        Expr * left = readFPInfix(infile);
        char op;
        infile >> op;
        if (ops.find(op) == std::string::npos) {
            std::cout << "Unknown operator symbol '" << op << "'" << std::endl;
            system("pause");
            exit(0);
        }
        Expr * right = readFPInfix(infile);
        infile >> symbol;
        // read the ending right parenthesis
        if (symbol != ')') {
            std::cout << "Invalid symbol '" << symbol << "':  ')' expected" << std::endl;
            system("pause");
            exit(0);
        }
        switch (op)
        {
        case '*':
            return new Times(left, right);
        case '+':
            return new Plus(left, right);
        case '/':
            return new Divide(left, right);
        case '%':
            return new Mod(left, right);
        case '-':
            return new Subtract(left, right);
        default:
            std::cout << "Read error" << std::endl;
            system("pause");
            exit(0);
        }
    }
    else
    {
        std::cout << "Invalid symbol '" << symbol << "':  'n' or '(' expected" << std::endl;
        system("pause");
        exit(0);
    }
}

现在,我假设我们必须使用相同的东西,所以我的主要问题是阅读该死的表达。我知道在这种方法中我们会逐个符号地读取它,然后根据提示测试该符号,以测试它是运算符还是数字。好吧,很酷。但是我如何左右移动,所以我可以输入类似Plus(左,右)的东西。我真的很挣扎,所以任何帮助都会非常感激。

注意:这是一项家庭作业,所以如果有人给我答案,那就没问题了,或者伪代码也没关系。谢谢。

1 个答案:

答案 0 :(得分:0)

现在......正如我上面所评论的,这不是我们简单地向您提供设计或编码的地方。但是,我认为我仍然可以解释中缀如何分解为左右操作数。

中缀只有两种类型的操作数:终端(常量或变量)和表达式。

每个表达式都具有相同的形式:

operator left-operand right-operand

事实证明,您可以使用以下两个规则轻松解析复杂表达式:每次敲击运算符时,都会启动一个新表达式(即进行递归调用)。让我们逐步介绍您给定示例的合法版本:

% 18 + 14 / - 12 11 % 1183 17

我们发现的第一件事是%;保存运算符,然后在剩余的字符串18 + 14 / - 12 11 % 1183 17中查找左右操作数。左边是微不足道的;那里有一个不变的。

// expression 1
operator = '%'
left = '18'
right = '+ 14 / - 12 11 % 1183 17'

这为我们提供了完整的顶级表达。但是,我们仍然需要解析正确的操作数。这是另一种表达方式。将+作为运算符存储并解析两个操作数。

同样,左派是微不足道的;右边是表达的其余部分:

// expression 2
operator = '+'
left = '14'
right = '/ - 12 11 % 1183 17'

同样,我们仍然需要解析正确的操作数。将/作为操作员存放,并且......哈!这一次,左操作数是一个表达式。我们仍将整个字符串传递给表达式解析器。

// expression 3
operator = '/'
left = <something from> '- 12 11 % 1183 17'
right = <on hold>

到目前为止,我已经跳过了以下步骤。当我们进行递归调用时,我们传递整个表达式。左操作数评估将吃掉它需要的任何东西,剩下的就是正确的评估。让我们现在更仔细地看一下......

//表达式4    operator =' - '    左= 12    对= 11    余数='%1183 17'

必须将此余数传递回调用实例以用于正确的运算符。找到左操作数(并将其评估为1)后,我们将返回到表达式3的解析:

// expression 3
operator = '/'
left = 1
right = '% 1183 17'

现在我们同样解析正确的字符串,得到1183%17或10的值。注意我并没有带我们通过这个表达式5;像表达式4一样,这是一个简单的操作,['%',1183,17]。

最后,我们返回表达式3并执行1/10(整数运算为此给出0)。那个0成为表达式2的右侧,我们评估14 + 0.最后,该结果成为表达式1的右侧,最终答案是18%14或4。

现在......你能从那里做编程吗?