23451: 交互四则运算计算器_带错误表达式版
http://cs101.openjudge.cn/practice/23451/
实现一个人机交互四则运算计算器。该程序可以根据用户输入的 含任意多层圆括号* 的四则运算表达式给出计算结果,其中合法的输入数字包括正负整数和小数(例如10,-10,10.5,-10.5,每个数最多带有一个符号),运算符包括 +、-、、/。
相关要求和说明如下:
程序应该允许用户在任何位置添加任意多个空格,比如 -10 * 3.4、0.1 + 1.0 + -2 / 3、0.85 * (10 / -2) * 05 都是合法的表达式
程序应该允许用户多次输入运算表达式并完成计算,直到用户输入 "quit";每个表达式占一行
程序输出的所有计算结果都保留小数点后 3 位数字,例如,当用户输入 -10.1 + 4.3 * 8.5 - 6 / 4 时,程序输出计算结果24.950
除括号以外,所有等运算优先级的运算都是左结合的。比如 2 / 4 / 2 应当视为 (2 / 4) / 2 = 0.250,而不是 2 / (4 / 2) = 1.000
输入保证小数点的两侧均有数字。即 1 + 1. 、 .5 + 0 等表达式都是不存在的
数据保证运算的中间量和结果均在[-1000, 1000]的区间里。
数据保证不存在精度损失问题。
本题中输入的表达式可能非法。非法情况可能包括:
括号不匹配。此时应输出单个字符串 "Unmatched bracket."
表达式里出现不正常的算符(除四则运算符、数字、小数点之外的任何字符)。此时应输出单个字符串 "Unknown operator."
表达式不完整,也即二元运算符的两侧未按要求分别为两个数字。此时应输出单个字符串 "Not implemented."
空表达式。此时应输出单个字符串 "No expression." 注意,此情况可能表示多组匹配的括号,但没有任何数值。比如().
祝你好运!——Pasu
输入
输入 N+1 行 其中 N 行为待运算的表达式 最后一行为 quit
输出
N 行计算结果 计算结果保留小数点后 3 位数字
样例输入
(((-10.1 + 4.3) * 8.5) - 6) / 4
((1+ 2)*3
(1+1+1. 1) / 3
1 ++ 1
1 +++ 1
1^2
quit样例输出
-13.825
Unmatched bracket.
1.033
No expression.
2.000
Not implemented.
Unknown operator.提示
本题目禁用eval函数。
而且,请注意,本题目明确给出了要求“每个数最多带有一个符号”,因此类似“1+++1”的表达式是不合法的,中间总会有一个“+”满足非法情况中的第三条。 但是“1++1”是合法的,因为后一个“+”可以被理解为后一个“1”的符号。 上述这一点与python内置的eval函数的规则不同,eval函数允许单个数带有多个符号。因此仅使用eval函数也是无法通过该题目的。
如果觉得有困难,可以考虑先转成对应的“逆波兰表达式”。
来源: Pasu
class stack():
def __init__(self):
self.val=[]
def isempty(self):
return len(self.val)==0
def push(self,item):
self.val.append(item)
def top(self):
return self.val[-1]
def pop(self):
del self.val[-1]
def operatorcheck():
for i in range(len(exp)):
if exp[i] not in ch:
return 0
return 1
def bracketcheck():
bracket=stack()
for i in range(len(exp)):
if exp[i]=='(':
bracket.push('(')
if exp[i]==')':
if bracket.isempty():
return 0
else:
bracket.pop()
if bracket.isempty():
return 1
else:
return 0
def onlybracket():
for i in range(len(exp)):
if exp[i]!='(' and exp[i]!=')':
return 0
return 1
def cut():
i=0
while i<=len(exp)-1:
if exp[i]=='*' or exp[i]=='/' or exp[i]=='(' or exp[i]==')':
expression.append(exp[i])
i+=1
continue
if exp[i]=='+' or exp[i]=='-':
if i==0 or exp[i-1] not in ch[5:]:
temp=''+exp[i]
i+=1
while i<=len(exp)-1 and exp[i] in ch[6:]:
temp=temp+exp[i]
i+=1
expression.append(float(temp))
continue
else:
expression.append(exp[i])
i+=1
continue
if exp[i] in ch[6:]:
temp=''
while i<=len(exp)-1 and exp[i] in ch[6:]:
temp=temp+exp[i]
i+=1
expression.append(float(temp))
continue
def value(s,x,y):
if s=='+':
return x+y
if s=='*':
return x*y
if s=='-':
return x-y
if s=='/':
return x/y
def calc():
operator=stack()
operand=stack()
for i in range(len(expression)):
if expression[i] not in ch[0:6]:
operand.push(expression[i])
elif expression[i]=='(':
operator.push('(')
elif expression[i]==')':
while operator.top()!='(':
b=operand.top()
operand.pop()
a=operand.top()
operand.pop()
operand.push(value(operator.top(),a,b))
operator.pop()
operator.pop()
elif expression[i] in ch[0:4]:
while not operator.isempty() and prior[operator.top()]>=prior[expression[i]]:
b=operand.top()
operand.pop()
a=operand.top()
operand.pop()
operand.push(value(operator.top(),a,b))
operator.pop()
operator.push(expression[i])
while not operator.isempty():
b=operand.top()
operand.pop()
a=operand.top()
operand.pop()
operand.push(value(operator.top(),a,b))
operator.pop()
print('{:.3f}'.format(operand.top()))
ch=['+','-','*','/','(',')','.','0','1','2','3','4','5','6','7','8','9']
prior={'*':3,'/':3,'+':2,'-':2,'(':1}
while True:
s=list(map(str,input().split()))
if s==["quit"]:
break
if len(s)==0:
print("No expression.")
continue
exp=""
for i in range(len(s)):
exp=exp+s[i]
if operatorcheck()==False:
print("Unknown operator.")
continue
if bracketcheck()==False:
print("Unmatched bracket.")
continue
if onlybracket()==True:
print("No expression.")
continue
expression=[]
try:
cut()
calc()
except:
print("Not implemented.")
continue