中缀符号,堆栈和队列

时间:2017-07-13 00:41:36

标签: python python-3.x

我正在为我的大学课程完成作业,我们需要编写一个脚本来评估一系列用括号括起来的数学表达式(即'(((4) 3)* 2)* 5)')。我们还需要使用堆栈和队列来完成教授为我们提供的这项任务。我让我的代码工作,但它没有给我正确的输出。对我做错的任何见解都很有帮助。

这是我用Python 3编写的代码:

import isfloat
import Queue
import Stack

def expr_eveluate(expr_string):
    """
    :Pre: Given a mathematical expression, this function
    evaluates it per pairs of brackets.
    :Post: The expression must be evaluated per pairs of brackets
    :param expr_string: A string of mathematical expressions
    :return:
    """
    #  A queue for data to be processed.
    waiting_line = Queue.create()
    #  A stack where processed operators go.
    operator_stack = Stack.create()
    #  A stack where processed numbers go.
    numerical_value = Stack.create()


    #  Put all the items in Queue
    expr = expr_string.split()
    for item in expr:
        Queue.enqueue(waiting_line, item)

    while not Queue.is_empty(waiting_line):
        item = Queue.dequeue(waiting_line)

        if item == '(':
            pass
        elif isfloat.isfloat(item):
            Stack.push(numerical_value, item)
        elif not isfloat.isfloat(item):
            Stack.push(operator_stack, item)
        else:
            num1 = Stack.pop(numerical_value)
            num2 = Stack.pop(numerical_value)
            op = Stack.pop(operator_stack)
            if op == '*':
                val = num1 * num2
                Stack.push(numerical_value, val)
            if op == '/':
                val = num1 / num2
                Stack.push(numerical_value, val)
            if op == '+':
                val = num1 + num2
                Stack.push(numerical_value, val)
            if op == '-':
                val = num1 - num2
                Stack.push(numerical_value, val)
            else:
                print("Syntax Error")
                return None

    return Stack.pop(numerical_value)

1 个答案:

答案 0 :(得分:0)

我发现您的代码有几个问题。这是一个破败。

  1. 您永远不会将您的数字转换为实际的数字类型。您可能希望在float(item)案例中将numeric_stack推送到item而不只是isfloat.isfloat(item)

  2. if / elif / else链中的条件彼此不一致。你可以保留一些相同的逻辑,如果你改变了块的顺序,但我认为如果你改善条件,当前的顺序是好的。

    特别是,在行elif not isfloat.isfloat(item):中,条件将始终为真(因为您已经处理了上一个elif块中的数字)。这意味着右括号将被推送到运算符堆栈,else块将永远不会运行。我认为你应该在这里明确地测试预期的运算符,类似于elif item in ("*", "/", "+", "-"):

    同样,顶级else块应该是elif item == ")",明确测试它希望处理的令牌。

  3. 当前if区块中的else可能应该是ifelif的链,因为您只希望其中一个是一次跑。目前,最后的else子句将针对任何非-运算符运行,而不是针对未知运算符值。

    说到内部else块,它应该可以缩进一个级别,以便它是外部if / elif链的一部分而不是内部运算符处理链。您需要检查顶层的无效令牌,因为operator_stack希望不会再被忽略了。

  4. 当您从numeric_stack中弹出两个数字时,您将按错误的顺序处理它们。从堆栈顶部出来的第一个数字始终是运算符右侧的值,而弹出的第二个数字将是左侧的值。目前,您将3 / 4解释为4 / 3。只需在您进行num1调用的行中交换num2pop,即可轻松解决此问题。您甚至可以考虑重新命名这些变量,例如rightleft,以便更清楚地了解操作的完成方式。

  5. 这个问题与您的代码不是一个问题,但是您已经显示了示例输入。如果您在'( ( (4 / 3) * 2) * 5)'上运行代码,由于括号紧紧包裹,它将无法正确处理。您需要将'( ( ( 4 / 3 ) * 2 ) * 5 )'传递给它,因此您正在使用的split调用将正确地分隔所有令牌。我会检查你的任务细节,看你是否需要编写更复杂的标记器,或者你是否可以更加小心你用于测试的输入。