Python使用re实现计算器
re 正则表达式 计算器
海瑞博客-学习python之路•2016-12-01•Python• 59• 0•A+ A-
re是一门小型语言
元字符
. 通配符除了\n
^ 以什么开始的匹配
$ 以什么结尾的匹配
* 重复前一个条件,最少0个,[0,∞]
+ 重复前一个条件,最少1个,[1,∞]
? 重复前面的条件,最少0个,最多1个[0,1]
{x} 重复前面的x次,x为数字,{x,y}最少x次,最多y-1次,{x,}最少x次,最多不限
| 或的意思
\ 反斜杠后跟元字符去除特殊功能
\. 就是匹配点.
\+ 匹配+
\\\\ 匹配\ 等于 r“\\"
r是代表原生字符,不需要python转义就传入re
反斜杠后跟普通字符实现特殊功能
\d 代表数字0-9 [0-9]
\D 代表非数字0-9 [^0-9]
\s 代表匹配空白字符[\t\n\r\f\v]
\S 代表匹配非空白字符 [^\t\n\r\f\v]
\w 代表匹配非空白字符[a-zA-Z0-9]
\W 代表匹配非非字母和数字[^a-zA-Z0-9]
\d 代表匹配一个特殊边界,如匹配单词
字符集
[ ]代表字符集
[a,b,c] 匹配a或b或c中任意一个
[a-z] 匹配a到z中的任意小型字母 [A-Za-z0-9]
- 代表什么到什么之间
^取反的意思,非
\ 将特殊符号转换成普通字符
注:字符集内取消元字符的特殊功能(\ ^ -除外)
[a-z,*] 匹配a-z的字母或*号,还有,号
[^a-z] 匹配非a-z的字母的所有
分组
()代表分组
(1|2) 匹配1或2的字符
(?P<id>\w) 匹配一个字母或数字 这个组的名称是ID
(:?\d+) 取消分组的权限
正则表达式方法
findall(规则,字符串) 寻找所有满足规则的元素
search(规则,字符串) 寻找第一个满足规则的元素并返回一个对象,配合group() 显示内容
1 re.search("123","1jkj123asda").group() #不建议这样写,如果没找到会报错 2 #建议以下方法 3 a = re.search("123","1jkj123asda") 4 if a:a = a.group() 5 else:print("没有找到")
match(规则,字符串) 只在开始匹配规则,满足返回对象,不满足返回None
split(规则,字符串) 通过规则分割字符串 注:先匹配第一个,并分割,再从第一个分割后的匹配第二个,并分割。。。
sub(规则,新内容,字符串) 通过规则匹配字符串内容,并把匹配结果替换成新内容
compile(规则) 将规则封装一个对象中,下次可以直接用对象查询,不需要输规则
finditer(规则,字符串)将查找的结果成一个迭代器,使用next方法取,每个内容用group再取数
习题:
计算器
要求可以计算+ - * \ ()**算法。
计算公式:1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )
思路:
-
判断字符串是否包含字母,两个点,括号不相等情况,并去除空白
-
提取字符串内的最里面的括号,并返回括号内容
-
传递替换 ++ +- -+ -- *+ /+的操作
-
传入其他运算模块 ** // 等
-
传入 乘除模块进行计算 返回计算完毕的结果
-
传入 加减法模块 计算返回计算结果 返回最终结果
-
将结果替换括号,重复前2-7面步骤
-
直到无法检测出字符串内包含的+-*/ 不包含最后结果
-
注意点:*- /-的问题 负数+正数的问题处理 加减法和乘除法都要按照从左到右计算
- 海瑞博客 www.hairuinet.com
1 #!/usr/bin/env python 2 # -*- coding=utf-8 -*- 3 # Created on: 2016年12月11日 4 # @author: 郑建文 5 # blog:www.hairuinet.com 6 import re, time 7 def hefaxin(xx): 8 '''数据合法性''' 9 b = 0 10 for i in xx: # 判断 11 if b < 0:break 12 if i == "(":b += 1 13 elif i == ")":b -= 1 14 zimu = re.search("[a-zA-Z\=]", xx) # 没有字母为空 15 kh = len(re.findall("\d+\.?\d*[\(]", xx)) # 判断括号是否有 数字(的情况 16 kh1 = len(re.findall("[()]", xx)) # 判断括号 17 dian = re.search("(\d+\.\.\d+)", xx) # 判断是否有 .. 18 if kh1 % 2 == b == kh and dian == zimu: return xx.replace(" ", "") 19 return 0 20 def tihfh(xx): 21 '''符号替换''' 22 xx = str(xx) 23 xx = xx.replace("++", "+") 24 xx = xx.replace("+-", "-") 25 xx = xx.replace("-+", "-") 26 xx = xx.replace("--", "+") 27 xx = xx.replace("*+", "*") 28 xx = xx.replace("/+", "/") 29 return xx 30 def ccf(xx): 31 '''乘除法''' 32 if re.search("\(", xx): xx = xx[1:-1] # 去括号 33 while re.search("[\*\/]",xx): 34 cenfa = re.search("\d+\.?\d*[\*\/]{1}\-?\d+\.?\d*", xx) 35 if cenfa: 36 cenfa = cenfa.group() 37 if cenfa.count("*") == 1: # 一个乘法 38 a, b = cenfa.split("*") 39 xx = xx.replace(cenfa, str(float(a) * float(b))) 40 elif cenfa.count("*") == 2: 41 a, b = cenfa.split("**") 42 xx = xx.replace(cenfa, str(float(a) ** float(b))) 43 elif cenfa.count("/") == 1: 44 a, b = cenfa.split("/") 45 xx = xx.replace(cenfa, str(float(a) / float(b))) 46 elif cenfa.count("/") == 2: 47 a, b = cenfa.split("//") 48 xx = re.sub(cenfa, str(float(a) // float(b)), xx) 49 else: 50 return xx 51 return xx 52 def jjf(xx): 53 '''加减法,按匹配顺序计算''' 54 if "(" in xx: xx = xx[1:-1] # 去括号 55 while re.search("\d+\.?\d*[\+\-]\d+\.?\d*",xx): 56 findret = re.search("[\-]?\d+\.?\d*[\+\-]\d+\.?\d*", xx) 57 if findret: 58 findret = findret.group() 59 if re.search("\d+\.?\d*\+\d+\.?\d*",findret): # 加法 60 a, b = findret.split("+") 61 xx = xx.replace(findret, str(float(a) + float(b))) 62 elif re.search("\d+\.?\d*\-\d+\.?\d*",findret): # 减法 63 a, b = findret.split("-") 64 xx = xx.replace(findret, str(float(a) - float(b))) 65 else:return xx 66 return xx 67 def kuohao(xx): 68 '''寻找括号''' 69 xx = re.search("(\([^()]+\))", xx) 70 if xx: return xx.group() # 找到就返回找到结果 71 return 0 # 没找到返回0 72 if __name__ == '__main__': 73 while True: 74 jishuan = input("请输入公式,保留2位小数。\n绿色为正确,红色结果错误!\n>>>") 75 db = hefaxin(jishuan) # 合法性判断 76 if db: # 返回正确执行精算 77 while db.count("(") > 0: # 循环一直有括号的 78 kh = kuohao(db) # 寻找括号 79 db = db.replace(kh, str(jjf(ccf(tihfh(kh))))) # 替换括号 80 else: # 无括号的情况 81 ret = jjf(ccf(tihfh(db))) 82 if "+" in ret: ret = ret[1:] # 取正数前面符号 83 while len(re.findall("\d+\.?\d*[\+\-\*\/]+\d+\.?\d*",ret)) > 0: 84 ret = jjf(ccf(tihfh(ret))) 85 if eval(jishuan) == float(ret):s = 32 # 正确就显示绿色 86 else:s = 31 # 错误就是红色 87 print("\33[%d;1m%s=%.2f\n\33[1m" % (s, jishuan, float(ret))) 88 else:print("\33[31;1m程序不合法,无法计算!\33[1m\n\n") 89 # 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )" 90 #jishuan = "1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )" 91 # 2*3*4*-1=6.0*-4.0