python - 程序不接受参数 Python

标签 python stdin postfix-notation

我正在创建一个后缀计算器,它接受算术表达式并首先将运算符推送到 stacl。

./pythonfilename 3 4 1 + - 用作我的输入。但是,由于没有显示输出,我尝试调试我的程序以了解为什么我的程序没有接受我的参数。 不会导致打印任何输出。我按 Ctrl+C 显示回溯调用,它指出 x = sys.stdin.readlines。

#!/usr/bin/python

import sys
import fileinput

class Stack:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def push(self,item):
        self.items.append(item)

    def pop(self):
        return self.items(pop)

    def peek(self):
        return self.items[len(self.items)-1]

    def size(self):
        return len(self.items)

    def is_number(line):
        try:
            float(line)
        except ValueError:
            return False        

def infixtoPostfix():
    initStack=Stack()
    x = sys.stdin.readlines() #read user input 
    for lines in x:#for lines in fileinput.input():
        for line in lines.strip().split(" "):
            if is_number(line):
                initStack.push(line)
                line = float(line)
            elif line =='+':
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum + secNum
                initStack.push(result)
                print initStack.peek()              

            elif line == '-':
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum - secNum
                initStack.push(result)
                print initStack.peek()

            elif line == '*':
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum * secNum
                initStack.push(result)
                print initStack.peek()
            elif line == "/":
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum / secNum
                initStack.push(result)
                print initStack.peek()
            elif line == "%":
                firstNum = initStack.pop()
                secNum = initStack.pop()
                result = firstNum % secNum
                initStack.push(result)
                print initStack.peek()

infixtoPostfix()

最佳答案

从管道 ( cat ... | python myprog.py ) 读取数据的标准方法是

import sys

for line in sys.stdin:
    print ">", line

line这里将包括最终的 '\n'

如果您想在命令行上获取参数 ( python myprog.py 3 4 1 + - ),则可以使用 sys.argv[1:] ( sys.argv[0] 包含 myprog.py )。

要获得一致的输入词法分析,您需要首先检查 sys.argv然后分割sys.stdin :

def lex_input():
    "Returns a list of tokens."
    tokens = []
    if len(sys.argv) > 1:
        tokens = sys.argv[1:]
    else:
        for line in sys.stdin:
            tokens += line.split()
    return tokens

那么你只需要更改你的 infixPostfix()函数来使用此标记数组(而不是在同一函数中同时进行解析和评估)。

ps:编写各个子句的更简洁的方式是:

elif token == '+':
    push(pop() + pop())

但这取决于您想要实现的目标..

更新:完整的解决方案

更新2:使用调试语句来可视化堆栈(为了简洁起见,删除了 Stack 类,改为使用常规列表)

import sys

STACK = []
push = STACK.append
pop = STACK.pop

OPERATIONS = {
    '+': lambda b, a: a + b,
    '-': lambda b, a: a - b,
    '*': lambda b, a: b * a,
    '/': lambda b, a: b / a,
}

def infixtoPostfix(tokens):
    print '%-15s %5s %-15s' % ('STACK before', 'token', 'STACK after')
    print '-'*15, '-'*5, '-'*15

    for token in tokens:
        print '%15s %5r' % (STACK, token),

        if token not in OPERATIONS:
            push(int(token))
        else:
            push(OPERATIONS[token](pop(), pop()))

        print '%15s' % STACK

def lex_input():
    "Returns a list of tokens."
    tokens = []
    if len(sys.argv) > 1:
        tokens = sys.argv[1:]
    else:
        for line in sys.stdin:
            tokens += line.split()
    return tokens

if __name__ == "__main__":
    infixtoPostfix(lex_input())
    # well formed programs should leave a single value on the STACK
    print "\nResult is:", STACK[0]

测试:

(dev) go|c:\srv> python rpn.py 3 4 1 + -
STACK before    token STACK after
--------------- ----- ---------------
             []   '3'             [3]
            [3]   '4'          [3, 4]
         [3, 4]   '1'       [3, 4, 1]
      [3, 4, 1]   '+'          [3, 5]
         [3, 5]   '-'            [-2]

Result is: -2

(如果 cat rpn.txt | python rpn.py 包含 rpn.txt3 4 1 + - 将输出相同的内容)。

如果您尝试使用语法错误的 rpn 程序,则该程序将引发异常,例如:

(dev) go|c:\srv> python rpn.py 3 4 + -
STACK before    token STACK after
--------------- ----- ---------------
             []   '3'             [3]
            [3]   '4'          [3, 4]
         [3, 4]   '+'             [7]
            [7]   '-'
Traceback (most recent call last):
  File "rpn.py", line 60, in <module>
    infixtoPostfix(lex_input())
  File "rpn.py", line 45, in infixtoPostfix
    push(OPERATIONS[token](pop(), pop()))
  File "rpn.py", line 26, in pop
    return STACK.pop()
IndexError: pop from empty list

在真正的编译器中,这会很糟糕,因为您不希望最终用户看到您的实现的详细信息。相反,您希望向他们提供一条诊断错误消息,以及您的程序找到它的确切位置。

在这种情况下,这并不困难。我省略了打印堆栈的调试语句:

def infixtoPostfix(tokens):
    # make a copy of the input, for use in error handling
    input_tokens = tokens[:]  
    try:
        for i, token in enumerate(tokens):
            if token not in OPERATIONS:
                push(int(token))
            else:
                push(OPERATIONS[token](pop(), pop()))
    except IndexError:
        print 'Detected Syntax Error at token no.:', i + 1  # people count from 1..
        print ' '.join(input_tokens)
        print '%s%s' % ('-' * (1 + len(' '.join(input_tokens[:i]))), '^')
        push('SYNTAX ERROR')  # the top of the stack contains the result of the current operation..

需要对结果打印进行一个小更改,打印列表中的最后一个元素( STACK[-1] ),它是堆栈的顶部,而不是依赖于列表/堆栈末尾只有一个元素:

if __name__ == "__main__":
    infixtoPostfix(lex_input())
    # well formed programs should leave a single value on the STACK
    print "\nResult is:", STACK[-1]

如果我们向这个版本的程序提供语法错误:

(dev) go|c:\srv> python rpn.py 34 4 + -
Detected Syntax Error at token no.: 4
34 4 + -
-------^

Result is: SYNTAX ERROR

我们收到了一条正确的错误消息,其中有一个尖尖的“图形”指示检测到错误的位置。

我们可以更进一步,因为我们知道所有操作都需要堆栈上的两个元素,并给出更详细的错误消息,例如:

Syntax Error at token "-":  Stack underflow
   The "-" operation requires two stack arguments and the stack 
   contained only one:

        Stack      token
        ---------- -----
        [37]        '-'

我将把它的实现作为练习。

正如您所看到的,即使在这个简单的示例中,错误处理代码也比评估代码多,这在编写简单的编译器时并不奇怪。

关于python - 程序不接受参数 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33447266/

相关文章:

python - 用停止填充 pandas 系列中的 NA 值

c++ - 使用 stdin stdout 和 stderr 启动 exe/进程?

java - Java Println 如何评估特殊符号和算术运算?

c# - 用一元/二元运算符中缀的后缀

c++ - 在 C++ 中使用堆栈计算后缀表达式

python - 合并数组并根据python中的键添加

python - 带引号的子进程命令不起作用

python - Python:从stdin读取和写入Powershell中的二进制文件

bash - 使用 echo 输出作为脚本标准输入的输入

python - Python 中的构造 "if __name__ == ' __main_ _' "