洗礼灵魂,修炼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)—— 购物商城登录验证系统
都在线购物过吧?那么你应该体验过,当没有登录账户时,点开购物车,个人中心,收藏物品等的操作时,都会直接跳转到登录账户的界面,然后如果登录一次后就不用再登录,直到用户登出. 是的,本次项目就是做一个登录 ...
随机推荐
- 这一年多来,阿里Blink测试体系如何从0走向成熟?
引言 Apache Flink是面向数据流处理和批处理的分布式开源计算框架,2016年阿里巴巴引入Flink框架,改造为Blink.2017年,阿里整合了所有流计算产品,决定以Blink引擎为基础,打 ...
- Jenkins构建部署Maven项目
1 创建新项目 2 构建maven项目 3 配置 3.1 源代码管理 svn 用户名,密码 4 配置maven打包 配置SSH 保存之后 立即构建 执行成功
- solr查询特殊字符的处理
1. 使用solr的页面功能时,遇到语法错误 2. 确认原因 从lexical error分析时特殊字符的问题. 首先 solr查询有哪些特殊字符? 查找官方文档:http://lucene.apac ...
- 浅谈Quartz定时任务调度
一 开发概述 对于具有一定规模的大多数企业来说,存在着这样一种需求:存在某个或某些任务,需要系统定期,自动地执行,然而,对大多数企业来说,该技术的实现,却是他们面临的一大难点和挑战. 对于大部分企 ...
- tcp_wrapper过滤
1.1 wrap简介 wrap工作在内核空间和应用程序中间的库层次中.在内核接受到数据包准备传送到用户空间时都会经过库层次,对于部分(只是部分)应用程序会在经过库层次时会被wrap库文件阻挡下来检查一 ...
- 深入MySQL复制(二):基于GTID复制
相比传统的MySQL复制,gtid复制无论是配置还是维护都要轻松的多.本文对gtid复制稍作介绍. MySQL基于GTID复制官方手册:https://dev.mysql.com/doc/refman ...
- 【转】CentOS系统操作下安装相关各种软件
CentOS系统是非常强大经常应用的系统,我就对CentOS系统深入探讨学习,对大家概括讲述CentOS系统应用,希望对大家有用.虽然CentOS Linux使用了RHEL的源代码,但是由于这些源代码 ...
- JSJ—编译器与虚拟机哪个重要?
阅读本文约“2分钟” 熟悉Java的朋友都知道虚拟机还有编译器,那么它们各自主要的功能是什么?谁比较重要呢?让我们来了解一下这两位美女的故事. 虚拟机可以说就是Java,她能让程序运行起来. 但是编译 ...
- python面向对象学习(四)继承
目录 1. 单继承 1.1 继承的概念.语法和特点 1.2 方法的重写 1.3 父类的 私有属性 和 私有方法 2. 多继承 2.1 多继承的使用注意事项 2.2 新式类与旧式(经典)类 1. 单继承 ...
- 【Linux命令】grep命令
1.作用 Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expression Print,表示全 ...