洗礼灵魂,修炼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)—— 购物商城登录验证系统
都在线购物过吧?那么你应该体验过,当没有登录账户时,点开购物车,个人中心,收藏物品等的操作时,都会直接跳转到登录账户的界面,然后如果登录一次后就不用再登录,直到用户登出. 是的,本次项目就是做一个登录 ...
随机推荐
- 字体反爬--css+svg反爬
这个验证码很恶心,手速非常快才能通过.. 地址:http://www.dianping.com/shop/9964442 检查一下看到好多字没有了,替代的是<x class="xxx& ...
- Netty源码分析(一):Netty总览
作为当前最流行的网络通信框架,Netty在互联网领域大放异彩,本系列将详细介绍Netty(4.1.22.Final). 代码事例 服务端 public final class EchoServer { ...
- Win32文件系统编程
Win32文件系统编程 一丶了解什么是文件系统 文件系统是抽象的.是windows在软件层面提供的一层虚拟的数据结构. 文件系统分为NTFS 跟 FAT32. 具体看看两者的区别吧. 磁盘分区容量. ...
- 手动生成/etc/shadow文件中的密码
shadow文件的格式就不说了.就说说它的第二列——密码列. 通常,passwd直接为用户指定密码就ok了.但在某些情况下,要为待创建的用户事先指定密码,还要求是加密后的密码,例如kickstart文 ...
- 使用meterpreter让没有安装python解释器的肉鸡设备执行任意python程序
目标设备不需安装python解释器就能让其执行python程序 # 需要在与目标meterpreter的session中加载python模块 meterpreter > load python ...
- zepto 事件分析4(事件队列)
前面分析了zepto的事件绑定,接下来分析事件解绑,先看一下zepto中解绑的off方法: $.fn.off = function(event, selector, callback){ var $t ...
- anoconda包管理汇总
anoconda默认的seaborn版本是0.8.1 seaborn的最新版本是0.9.0 并且已经没有0.8.1的文档了. 升级anoconda的seaborn版本 进入anoconda prom ...
- [转]centos6.5修改yum安装的mysql默认目录
本文转自:https://www.cnblogs.com/fefjay/p/6044444.html 0.说明 Linux下更改yum默认安装的mysql路径datadir.linux下,MySQL默 ...
- 水晶报表Crystal 无效索引
这几天项目用到水晶报表做报表打印,没有前辈指导,都自己摸着石头过河,真是痛并快乐着.其实水晶报表还是挺好用的,对初学者也并不难(我就是初学者).昨天遇到一个问题:无效索引 ……开始以为是报表设置的问题 ...
- Message": "请求的资源不支持 http 方法“GET”
今天用postman测试后端api,总是报错,下面是问题解决方案. 一.测试方法 public ApiResult Get(int id){ApiResult result = new ApiResu ...