我正在创建一个后缀计算器,它接受算术表达式并首先将运算符推送到 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.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
我们收到了一条正确的错误消息,其中有一个尖尖的“图形”指示检测到错误的位置。
我们可以更进一步,因为我们知道所有操作都需要堆栈上的两个元素,并给出更详细的错误消息,例如:
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/