我正在创建一个后缀计算器,它接受算术表达式并首先将运算符推送到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()
答案 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()
然而,您的代码只处理单个输入作为参数