洗禮靈魂,修煉python(80)--全棧項目實戰篇(8)—— 計算器

来源:https://www.cnblogs.com/yangva/archive/2017/12/29/8143832.html
-Advertisement-
Play Games

用正則表達式開發一個計算器,計算用戶給定的一串帶有加減乘除的公式。 要求:不能使用eval轉換字元串 分析: 要求簡單,就是計算混合運算,但是不能使用eval直接轉換,主要就是把整個式子中的小括弧優先匹配到進行計算再把計算結果替換到式子中,然後再根據小括弧計算,直到沒有小括弧再按照加減乘除優先順序計算 ...


用正則表達式開發一個計算器,計算用戶給定的一串帶有加減乘除的公式。

要求:不能使用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('+',''))

 

 

測試結果就不貼出來了,自己測試了

 

總結:

通過這個小項目,相信你已經對正則表達式很瞭解了,那麼我的目的就達到了

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這篇主要寫配置文件的優化,例如 jdbc.properties 配置文件 ,引入資料庫的文件,例如driver,url,username,password 等,然後在 SqlMapConfig.xml 裡面引入相對應的文件即可,可以簡化配置文件, 在 SqlMapConfig.xml 用 <type ...
  • 本文主要介紹四種實例化bean的方式(註入方式) 或者叫依賴對象實例化的四種方式。上面的程式,創建bean 對象,用的是什麼方法 ,用的是構造函數的方式 (Spring 可以在構造函數私有化的情況下把類對象創建出來) 常用的創建方式有以下四種: 1) setter 方法 2) 構造函數 3) 靜態工 ...
  • 這是在看完了C++ Primer這本書之後又回過頭來碼的筆記,在看的時候也發現,看到後面,前面就忘了,有點像狗熊掰玉米。。。所以決定回過頭來再過一遍,這一次只看那些比較重要的知識點,太詳細了也終歸還是記不住。另外,這篇博客是使用 Markdown寫的,第一次用,估計寫出來的格式可能會有點醜。。 1. ...
  • 數據流分為輸入、輸出流,無論是輸入流還是輸出流,都可看作是在源和目標之間架設一根"管道",這些管道都是單向流動的,要麼流入到記憶體(輸入流),要麼從記憶體流出(輸出流)。 應用於java上,輸入流和輸出流分別為InputStream和OutputStream。輸入流用於讀取(read)數據,將數據載入到 ...
  • Web層用Structs2的action Service層用Spring的IoC和aop以及JdbcTemplate或者Transaction事務(創建對象及維護對象間的關係) Dao層用Hibernate的crude操作 看上去是Structs2和Spring(把Structs2的action交給 ...
  • 都線上購物過吧?那麼你應該體驗過,當沒有登錄賬戶時,點開購物車,個人中心,收藏物品等的操作時,都會直接跳轉到登錄賬戶的界面,然後如果登錄一次後就不用再登錄,直到用戶登出。 是的,本次項目就是做一個登錄驗證系統 需求:1.模擬某購物網站,進入菜單選項:一共有以下頁面,根據用戶輸入的序號,做出不同的反饋 ...
  • 2.1 python3.6 工具使用 運行python 自帶的idle後,輸入python命令,如print('hello world'),回車後輸出 hello world 其中mac系統會出現一段warning :the version of tcl/tk in use may be ustab ...
  • 最近項目用到springcloud,研究了下springcloud的熔斷機制Hystrix。 熔斷機制,就是下游服務出現問題後,為保證整個系統正常運行下去,而提供一種降級服務的機制,通過返回緩存數據或者既定數據,避免出現系統整體雪崩效應。在springcloud中,該功能可通過配置的方式加入到項目中 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...