【问题标题】:Python Postfix Notation Stack ClassPython Postfix Notation Stack 类
【发布时间】:2018-09-11 20:57:29
【问题描述】:

我必须编写一个 Stack 类,该类使用后缀表示法来计算使用 Python 从文本文件输入的问题。我还想更新列表,并且任何时候都不允许超过 10 个项目。我相信我的 push 或 pop 方法似乎有问题。任何建议将不胜感激,谢谢。

更新的书面代码:

class Stack:
    #initializing the data
    def __init__(self):
        self.__data = [None] * 10
        self.__length = 0

    #destroying the existing stack
    def __destroy__(self):
        self.__data = [None] * 10
        self.__length = 0
        return

    #checking to see if the stack is empty
    def is_stack_empty(self):
        return self.__length == 0

    #checking to see if the stack is full
    def is_stack_full(self):
        if self.__length == 10:
            return True
        else:
            return False

    #pushing an item to the stack
    def push(self, item):
        try:
            self.__data.append(item)
            self.__length = self.__length + 1
            return
        except IndexError:
            print("ERROR: Cannot push more than 10 items to the stack.")


    #popping an item from the stack
    def pop(self):
        try:
            return self.__data.pop()
            self.__length = self.__length - 1
            return
        except IndexError: 
            print("ERROR: Cannot pop from an empty list.")


    #checking to see what the last item on the stack is
    def top(self):
        return self.__data[-1]

    #checking the length of the stack
    def __len__(self):
        return self.__length

    #overloading the string operator
    def __str__(self):
        return str(self.__data)





def main():
    file_name = input("Enter the name of the file containing postfix expressions: ")   
    #expression = input("Enter a mathmatical expression: ")
    #e_list = expression.split()
    #validates file
    found = False

    while not found:
        try:
            in_file = open(file_name)
            found = True
        except Exception as ex:
            print(file_name, " is not found.")
            file_name = input("Please re-enter a valid text file name: ")

    stack = Stack()

    for each in in_file:
        try:
            value = int(each)
        except Exception as ex:
            second = stack.pop()
            first = stack.pop()

            if each == "+":
                try:
                    answer = first + second
                    stack.push(answer)
                except Exception as ex:
                    print("ERROR: "+ expression + " is an invalid postfix expression.")
            elif each == "-":
                try:
                    answer = first - second
                    stack.push(answer)
                except Exception as ex:
                    print("ERROR: "+ expression + " is an invalid postfix expression.")  
            elif each == "*":
                try:
                    answer = first * second
                    stack.push(answer)
                except Exception as ex:
                    print("ERROR: "+ expression + " is an invalid postfix expression.")
            elif each == "/":
                try:
                    answer = first / second
                    stack.push(answer)
                except Exception as ex:
                    print("ERROR: "+ expression + " is an invalid postfix expression.")
        else:
            stack.push(value)
    print("Answer: ", stack.pop())


    return


main()

文件内容:

5 10 * 6 +
20 5 /
3 8 6 + *
3 4 + 9 - 12 +
9 3 2 1 + + /
3 + 5
* 3 4 5 + *
4 9 1 3 + -
h 3 +
0 1 2 3 4 5 6 7 8 9 10 11 12 + / - * + + + + + * * /

结果输出:

Enter the name of the file containing postfix expressions: expressions.txt
Expression:  5 10 * 6 +

Answer:  56

Expression:  20 5 /

Answer:  4.0

Expression:  3 8 6 + *

Answer:  42

Expression:  3 4 + 9 - 12 +

Answer:  10

Expression:  9 3 2 1 + + /

Answer:  1.5

ERROR: 3 + 5
is an invalid postfix expression.
Expression:  3 + 5

Answer:  5

ERROR: * 3 4 5 + *
is an invalid postfix expression.
Expression:  * 3 4 5 + *

Answer:  27

Expression:  4 9 1 3 + -

Answer:  5

ERROR: h 3 +
is an invalid postfix expression.
Expression:  h 3 +

Answer:  None

Expression:  0 1 2 3 4 5 6 7 8 9 10 11 12 + / - * + + + + + * * /
Answer:  0.0

预期输出:

Enter the name of the file containing postfix expressions: expressions.txt
Expression:  5 10 * 6 +

Answer:  56

Expression:  20 5 /

Answer:  4.0

Expression:  3 8 6 + *

Answer:  42

Expression:  3 4 + 9 - 12 +

Answer:  10

Expression:  9 3 2 1 + + /

Answer:  1.5

ERROR: 3 + 5 is an invalid postfix expression

ERROR: * 3 4 5 + * is an invalid postfix expression

ERROR: 4 9 1 3 + - is an invalid postfix expression

ERROR: h 3 + is an invalid postfix expression

ERROR: 0 1 2 3 4 5 6 7 8 9 10 11 12 + / - * + + + + + * * / is an invalid postfix expression

【问题讨论】:

  • 在尝试从堆栈中弹出任何内容之前查看each 的值,以了解为什么 int(each) 失败。作为一般规则,不要捕获像 Exception 这样广泛的内容,除非您至少记录您捕获的实际异常,或计划重新提出。
  • 虽然我们在处理它,但您的许多方法过于复杂。而不是if something: return True else: return False,只是return something。如果你只想检查一个列表是否为非空,你可以只使用列表本身(非空序列为真;空序列为假),而不是检查它的长度。
  • 最后一件事:如果pop 打印错误但对空堆栈不执行任何操作,push 可能应该打印错误但对于完整堆栈不执行任何操作,而不是默默地将堆栈扩展它的最大尺寸。 (如果你决定使用固定大小的列表和单独的长度设计,推到一个完整的堆栈会引发一个你没有检查的异常;如果你使用不断增长的列表,它将使堆栈处于无效状态违反其不变量的状态。两者都不是您想要的。)

标签: python stack postfix-notation


【解决方案1】:

您将e_list 替换为in_file,但它们不是一回事:前者是一个符号列表,如['5', '10', '*', '6', '+'],而后者是一个文件的迭代器,因此每个现在都是@987654324 @,不是字符串中的单个元素。

for expression in in_file:
    e_list = expression.split()
    for each in e_list:
        try:
            value = int(each)
        except ValueError as ex:
            second = stack.pop()
            first = stack.pop()

            # ...

【讨论】:

    【解决方案2】:

    您的输入格式是一个行流,每行都是一个由空格分隔的标记流组成一个表达式,如下所示:

    5 10 * 6 +
    20 5 /
    

    但您的代码试图将每一行视为一个标记:

    for each in in_file:
        try:
            value = int(each)
    

    这里需要一个嵌套循环,内部循环在空白处拆分,以按预期处理每一行的每个标记:

    for line in in_file:
        for token in line.split():
    

    尚不清楚您是否应该为每个新行重置堆栈。如果是,则需要为每一行创建一个新的Stack

    for line in in_file:
        stack = Stack()
        for token in line.split():
    

    ... 或destroy 每行末尾的堆栈,以便您可以重复使用它:

    stack = Stack()
    for line in in_file:
        for token in line.split():
            # etc.
        stack.__destroy__()
    

    另外,您的Stack 课程有一个严重的问题需要解决。您的一些方法(__init__is_stack_full、)使用 __data 作为 10 个元素的固定大小列表和一个单独的 __length,它告诉您这些元素中有多少是有效值,而其他方法(@987654333 @、is_stack_emptytop__len____str__) 使用 __data 作为 0-10 个元素的列表,这些元素都是有效的,而其他元素 (pushpop) 将两者混合用同样的方法。您必须选择一种设计,然后使用错误的方法修复方法。


    另外一点:你的__destroy__ 方法是一个由你的主代码调用的公共方法,而不是像__init__ 这样的Python 协议的实现,所以它应该被命名为destroy。您的 __data 属性是常规的“按惯例”私有值,而不是您需要对超类和/或子类隐藏以避免意外冲突的值,因此它应该是 _data


    当然,您的代码中可能还有其他错误,但这应该足以让您克服当前的障碍(以及您未预料到的下一个障碍)。

    【讨论】:

    • 我试图在每次弹出或推入堆栈时更新 self.__length ,因此堆栈中最多只有 10 个项目,但它似乎没有更新。上述代码的处理方式是否有问题,不包括push/pop以外的方法?
    • @ConnorChapin 是的,所有使用len(self.__data) 的方法都忽略了self.__length,因此需要对其进行修复。此外,它们中的一些收缩和扩展self.__data,而不是仅使用self.__length 索引固定大小的列表,这也需要修复。例如,__destroy__ 应该和__init__ 做同样的事情。
    猜你喜欢
    • 2021-09-04
    • 2021-06-27
    • 2017-03-26
    • 2019-11-30
    • 2021-12-09
    • 2011-02-24
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    相关资源
    最近更新 更多