Skip to content

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

python
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