用正則表達式開發一個計算器,計算用戶給定的一串帶有加減乘除的公式。 要求:不能使用eval轉換字元串 分析: 要求簡單,就是計算混合運算,但是不能使用eval直接轉換,主要就是把整個式子中的小括弧優先匹配到進行計算再把計算結果替換到式子中,然後再根據小括弧計算,直到沒有小括弧再按照加減乘除優先順序計算 ...
用正則表達式開發一個計算器,計算用戶給定的一串帶有加減乘除的公式。
要求:不能使用eval轉換字元串
分析:
要求簡單,就是計算混合運算,但是不能使用eval直接轉換,主要就是把整個式子中的小括弧優先匹配到進行計算再把計算結果替換到式子中,然後再根據小括弧計算,直到沒有小括弧再按照加減乘除優先順序計算,最後計算出結果。每次計算前把加減乘除符號格式化一下,比如有+和-同時存在的時候
代碼發佈區:github
#!usr/bin/env python #-*- coding:utf-8 -*- # author:yangva # datetime:2017/12/23 0023 21:31 import re def format_string(string): #格式化字元串,把符號格式化 string = string.replace('++','+') string = string.replace('-+','-') string = string.replace('--','+') string = string.replace('*+','*') string = string.replace('/+','/') string = string.replace(' ','') return string def counter_md(string): #乘除 pattern_str2 = '\d+\.?\d*[*/][+\-]?\d+\.?\d*' #匹配乘除法,帶上正負號,[]中的 - 有特殊意義,所以要轉義 while re.findall(pattern_str2,string): expression = re.search(pattern_str2,string).group() #如果有乘法,分割並分別運算 if expression.count('*'): x,y = expression.split('*') mul_result = str(float(x)*float(y)) string = string.replace(expression,mul_result) string = format_string(string) #如果有除法,分割並分別運算 if expression.count('/'): x,y = expression.split('/') div_result = str(float(x)/float(y)) string = string.replace(expression,div_result) string = format_string(string) return string def counter_as(string): #加減 pattern_add = '[\-]?\d+\.?\d*\+[+\-]?\d+\.?\d*' #匹配加法 pattern_sub = '[\-]?\d+\.?\d*\-[+\-]?\d+\.?\d*' #匹配減法 #處理加法 while re.findall(pattern_add,string): add_list = re.findall(pattern_add,string) #將結果分割成一個小式子 for add_str in add_list: #迭代每個小式子,分別計算 x,y = add_str.split('+') add_result = '+'+str(float(x)+float(y)) string = string.replace(add_str,add_result) #得到的結果替換到式子中 #處理減法 while re.findall(pattern_sub,string): sub_list = re.findall(pattern_sub,string) for sub_str in sub_list: numbers = sub_str.split('-') #如果分割出來的小式子里有如-5-3的式子,會分割出['','5','3']則再分割一次 if len(numbers) == 3: result = 0 #定義變數,方便後續存儲結果 for v in numbers: if v: result -= float(v) else: #正常結果,比如4-5,分割得到的則是['4','5'] x,y = numbers result = float(x) - float(y) #替換字元串 string = string.replace(sub_str,str(result)) return string def check(string): #檢查合法性 check_flag = True #標誌位 if not string.count('(') == string.count(')'): print('括弧數量不統一') check_flag = False if re.findall('[a-zA-Z]+',string): check_flag = False print('非法字元') check_flag = False return check_flag if __name__ == '__main__': #info = '20-4+9*((44-22+134/3 - (-3+33+34*5/2*5-9/3*55)-45-3)+55+3*234-2-3×57)' # 檢驗合法性 info = input('請輸入式子:') if check(info): print('info:',info) info = format_string(info) print(info) print('eval(info):',eval(info)) #作為與輸出結果對比的驗證 while info.count('(') > 0: #計算括弧內的式子 pattern_str = re.search('\([^()]*\)',info).group() #按照運算優先順序,先計算乘除法的結果 md_result = counter_md(pattern_str) #再計算加減法的結果 as_result = counter_as(md_result) #把計算得到的結果作[1:-1]切片,把括弧去掉再重新格式化替換原數據替換到式子中 info = format_string(info.replace(pattern_str,as_result[1:-1])) else: #計算括弧外的式子,不用再匹配直接運算 md_result = counter_md(info) as_result = counter_as(md_result) info = info.replace(info,as_result) print('the result is :',info.replace('+',''))
測試結果就不貼出來了,自己測試了
總結:
通過這個小項目,相信你已經對正則表達式很瞭解了,那麼我的目的就達到了