程序不接受Python的参数

时间:2015-10-31 01:48:37

标签: python stdin postfix-notation

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

./ pythonfilename 3 4 1 + - 用作我的输入。但是,由于没有显示输出,我试图调试我的程序,看看为什么我的程序没有参与我的论点。 不会导致打印任何输出。我按Ctrl + C显示Traceback Call,它指出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()

2 个答案:

答案 0 :(得分:3)

从管道(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())

但这取决于你想要完成的事情......

更新:完整' ish解决方案

Update2:使用调试语句可视化堆栈(为了简洁起见,删除了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.txt),3 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

我们收到了正确的错误消息,其中包含一些尖锐的图片&#39;指示检测到错误的位置。

我们可以更进一步,因为我们知道我们的所有操作都在堆栈上占用了两个元素,并提供了更详细的错误消息,例如:

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

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

我将执行此操作作为练习。

正如您所看到的,即使在这个简单的示例中,错误处理代码也多于评估代码,在编写简单的编译器时也不会太令人惊讶。

答案 1 :(得分:0)

./ pythonfilename 3 4 1 + -

实际上是3 4 1 + - 作为参数而不是作为输入传递。

如果您想从文件中读取,请使用open('filename')

使用./pythonfilename'3 4 1 + - '

x = [sys.argv [1]]

代替x = sys.stdin.readlines()

然而,您的代码只处理单个输入作为参数