博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洗礼灵魂,修炼python(80)--全栈项目实战篇(8)—— 计算器
阅读量:6243 次
发布时间:2019-06-22

本文共 3623 字,大约阅读时间需要 12 分钟。

用正则表达式开发一个计算器,计算用户给定的一串带有加减乘除的公式。

要求:不能使用eval转换字符串

 

分析:

要求简单,就是计算混合运算,但是不能使用eval直接转换,主要就是把整个式子中的小括号优先匹配到进行计算再把计算结果替换到式子中,然后再根据小括号计算,直到没有小括号再按照加减乘除优先级计算,最后计算出结果。每次计算前把加减乘除符号格式化一下,比如有+和-同时存在的时候

 

 

代码发布区:

 

#!usr/bin/env python#-*- coding:utf-8 -*-# author:yangva# datetime:2017/12/23 0023 21:31import redef format_string(string): #格式化字符串,把符号格式化    string = string.replace('++','+')    string = string.replace('-+','-')    string = string.replace('--','+')    string = string.replace('*+','*')    string = string.replace('/+','/')    string = string.replace(' ','')    return stringdef 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 stringdef 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 stringdef 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_flagif __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('+',''))

 

 

测试结果就不贴出来了,自己测试了

 

总结:

通过这个小项目,相信你已经对正则表达式很了解了,那么我的目的就达到了

 

转载于:https://www.cnblogs.com/yangva/p/8143832.html

你可能感兴趣的文章
一起同过窗
查看>>
XMLHttpRequest详解
查看>>
9 数字载波传输1
查看>>
iOS开发之功能模块--高仿Boss直聘的IM界面交互功能
查看>>
Flume Source 实例
查看>>
MySQL 缓存表建触发器
查看>>
.NetCore~C#6的一些新特性
查看>>
Recurrent Neural Networks(RNN) 循环神经网络初探
查看>>
多线程中数的原子性加减
查看>>
客户被绑,蒙眼,惊问:“想干什么?” 对方不语,鞭笞之,客户求饶:“别打,要钱?” 又一鞭,“十万够不?” 又一鞭,“一百万?” 又一鞭。客户崩溃:“你们TMD到底要啥?” “要什么?......
查看>>
jQuery.fly插件实现添加购物车抛物线效果
查看>>
[svc]linux的ip命令操作接口和路由表
查看>>
39.Node.js域名解析---DNS模块
查看>>
Ajax 跨域,这应该是最全的解决方案了
查看>>
vs2010下release版本调试设置
查看>>
Windows连接Linux虚拟机里面的Docker容器
查看>>
MYSQLDUMP参数详解(转)
查看>>
SLA
查看>>
MyProject / FuzzyPages | Elias的个人主页
查看>>
三子棋局-挑战你的逻辑思维
查看>>