洗礼灵魂,修炼python(80)--全栈项目实战篇(8)—— 计算器
用正则表达式开发一个计算器,计算用户给定的一串带有加减乘除的公式。
要求:不能使用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('+',''))
测试结果就不贴出来了,自己测试了
总结:
通过这个小项目,相信你已经对正则表达式很了解了,那么我的目的就达到了
洗礼灵魂,修炼python(80)--全栈项目实战篇(8)—— 计算器的更多相关文章
- 洗礼灵魂,修炼python(82)--全栈项目实战篇(10)—— 信用卡+商城项目(模拟京东淘宝)
本次项目相当于对python基础做总结,常用语法,数组类型,函数,文本操作等等 本项目在博客园里其他开发者也做过,我是稍作修改来的,大体没变的 项目需求: 信用卡+商城: A.信用卡(类似白条/花呗) ...
- 洗礼灵魂,修炼python(73)--全栈项目实战篇(1)——【转载】前提准备之学习ubuntu
本篇是为项目实战做准备,学习Linux是必备的,不然都不好意思叫全栈对吧?下面是一位资深大神写的文章,够详细,我也不用浪费时间再写了 原文链接:Ubuntu学习——第一篇 内容: 一. Ubuntu简 ...
- 洗礼灵魂,修炼python(78)--全栈项目实战篇(6)—— 多级目录菜单之地址管理系统
相信各位都在在网上买过东西吧?那么今天我的主题就是写个在线购物系统,是不可能的,哈哈(后期确实有这个项目),那么购物都填写过快递地址吧?然后网上查个地址都有地址管理吧? 要求: 1.打印出省.市.县等 ...
- 洗礼灵魂,修炼python(86)--全栈项目实战篇(12)—— 利用socket实现文件传输/并发式聊天
由于本篇博文的项目都很简单,所以本次开个特例,本次解析两个项目,但是都很简单的 项目一:用socket实现文件传输 本项目很简单,作为小项目的预热的,前面刚学完socket,这里马上又利用socket ...
- 洗礼灵魂,修炼python(79)--全栈项目实战篇(7)—— 多级目录菜单之地址管理系统升级版
要求: 1.在上一篇的地址管理系统的基础上做升级改动 2.添加增删改的功能 3.尽量的贴近生活常识中的地址管理 分析: 需求不用多说了,干就完了 相关文件源码地址:github 这次由于要有增删改的操 ...
- 洗礼灵魂,修炼python(77)--全栈项目实战篇(5)—— ATM自动存取机系统
要求: 1.完成常识中的ATM存取款机功能 2.把ATM机故障考虑进去 3.不能直接输入账户名和卡号等等信息,模拟出插银行卡让ATM机自动读取卡信息 4.密码验证超过三次错误即锁定账户 5.操作类型有 ...
- 洗礼灵魂,修炼python(76)--全栈项目实战篇(4)—— 购物车系统
要求: 1.基本符合日常购物车的要求(根据你的想法开放性提升功能) 2.展示商品信息,并且可随时上新商品 3.用户购买每一样商品时都对所剩的钱做一次对比,如果够则提示“已购买”,如果不够提示“余额不足 ...
- 洗礼灵魂,修炼python(75)--全栈项目实战篇(3)—— 账户注册登录管理系统
要求: 1.系统可以创建用户和登录用户,根据用户的输入不同,做出不同的反应(创建还是登录) 2.创建用户不能创建已存在的用户名 3.登录用户的操作最多只能有三次,超过三次冻结账户,每使用一次提示用户还 ...
- 洗礼灵魂,修炼python(81)--全栈项目实战篇(9)—— 购物商城登录验证系统
都在线购物过吧?那么你应该体验过,当没有登录账户时,点开购物车,个人中心,收藏物品等的操作时,都会直接跳转到登录账户的界面,然后如果登录一次后就不用再登录,直到用户登出. 是的,本次项目就是做一个登录 ...
随机推荐
- SpringBoot2.0应用(四):SpringBoot2.0之spring-data-jpa
如何整合spring data jpa 1.pom依赖 <dependency> <groupId>org.springframework.boot</groupId&g ...
- 13 Tensorflow API主要功能
要想使用Tensorflow API,首先要知道它能干什么.Tensorflow具有Python.C++.Java.Go等多种语言API,其中Python的API是最简单和好用的. Tensor Tr ...
- Jenkins入门之新建任务
简单了解了Jenkins界面之后,下面我们简单介绍一下如何使用jenkins创建一个任务.打开Jenkins web管理界面之后,点击左侧最上方的NewItem图标 便会进入如下界面 产生要输入一个构 ...
- 翻译:SET Variable(已提交到MariaDB官方手册)
本文为mariadb官方手册:SET Variable的译文. 原文:https://mariadb.com/kb/en/set-variable/我提交到MariaDB官方手册的译文:https:/ ...
- 跨域学习笔记3--web.config设置之system.webServer 详细介绍,为网站设置默认文档
自己并不懂,在此先记录下来,留待以后学习... 如何:为 IIS 7.0 配置 <system.webServer> 节2008-06-14 22:26http://technet.mic ...
- Postman Post请求上传文件
Postman Post请求上传文件一.选择post请求方式,输入请求地址 二.填写Headers Key:Content-Type :Value:multipart/form-data 如下图 三. ...
- 不容易系列之一(hdu1465)错排+递推
不容易系列之一 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- 写一个可插入自定义标签的 Textarea 组件
- “插入自定义标签是什么鬼?” - “比如你要插入一个<wise></wise>的标签...” - “什么情况下会有这种需求?” - “得罪了产品的情况下...” 一.需求背 ...
- CSS之IE浏览器的hasLayout,IE低版本的bug根源
什么是hasLayout? hasLayout是IE特有的一个属性.很多的ie下的css bug都与其息息相关.在ie中,一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元素来计算尺寸和组 ...
- loj#6029. 「雅礼集训 2017 Day1」市场(线段树)
题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...