[原創]python之簡單計算器(超詳解,只有基本功能+-*/,還有括號處理)


 

                           不想看過程的話,直接看文章最后的正式源碼

 

 作業需求及分析:

 

 

流程圖

 

https://www.processon.com/diagraming/580c5276e4b03c844a5a9716

 

 

 

初期感受

 

      今天10/23,這個作業是我19號拿到的,當時一臉蒙逼,知道么?這里我不可能不可能做出來的感覺!!!

覺得不可能不是沒有理由的,

1. 有多括號要怎么區配出最里面那個?? 雖然我前兩篇博文有寫關與正則表達式的,但還是不會。

2.輸入的可是字符串字符串啊

3.如何加減乘除

4.如何先乘除,后加減

實際上遇到比這些還多,但現在就只記起這些……

 

 

分析需求:

 

1.先判斷有無括號,無括號直接+-*/

2.有括號先提取出最里面的括號(利用正則表達式)

3.括號外面還有括號怎么辦?我這里是用迭代,直到沒有括號

4.沒有括號,再傳給1處理,OK ,搞定

 

 

我不會,但我可以去我別人的博客么,但我也看不懂……

 

媽的,這怎么行!

 

先寫加減乘除,試試吧

 1 def mul_mov(s):  2     result = 0
 3     if s[1] == '*':  4         result = int(s[0]) * int(s[2])  5     elif s[1] == '/':  6         result = float(s[0]) / int(s[2])  7         result = int(result)  8 
 9     for i in range(3): # 去掉前三個 10         s.remove(s[0]) 11 
12     s.insert(0, result) #局部變量引用賦值前的結果 13 
14     if len(s) == 1: 15  print(result) 16     else: 17  mul_mov(s) 18 
19 
20 def main(): 21     choose = input("請選擇:1.加減;2.乘除") 22     num = input("please input:") 23     if choose == '1': 24         sa = re.split(r'(\D)', num) 25  add_substract(sa) 26     elif choose == '2': 27         sa = re.split(r'(\D)', num) 28  mul_mov(sa) 29 
30 
31 if __name__=="__main__": 32     main()

 

大概花了半個晚上,死活總算是搞出來了!

 

但這樣肯定還有問題。我當時是這樣想的:

#問題:讓用戶選擇1,2不現實,如何讓用戶輸入然后自動加減乘除
#思考:現在已經能夠處理,單個的加減或乘除
#可否在混合中先分組出(乘除) eg: ['8+9+','9*4/3','-','4*2‘,‘+5-2’]
#這樣可以處理乘除,如何分組呢??



再后來,我卡住了,我回去看我寫正則表達式的文章一遍雙一遍,還是想不出怎么分組? 感覺太難了,
eg:  ['8+9+','9*4/3','-','4*2‘,‘+5-2’] 如何單獨的匹配出'9*4/3' ??
PS:如果大神你知道,可以評論和我說下,謝謝!



卡住怎么辦?我+-*/乘除都做出來了,肯定不能就此打住的。

於是我打別人的博客看,終於找到一篇我看得懂看得懂的了!!http://www.cnblogs.com/loyfee/p/5764926.html#3538071

參考代碼
# coding:utf-8

# 將輸入的字符串格式統一轉換成列表,將數字、符號、括號都成一個獨立元素,
# 如: 12+3*(14+5)  ----> ["12","+","3","*","(","14","+","5",")"]
def format_input(input_re_value):
    input_re_value = input_re_value.replace(" ","")
    format_list = [] 
    for i in input_re_value:
        format_list.append(i)
    snum = 0
    while 1:
        try:
            if format_list[snum].isnumeric():
                if format_list[snum+1].isnumeric():
                    format_list[snum] = format_list[snum] + format_list[snum+1]
                    format_list.pop(snum+1)
                else:
                    snum += 1                    
            else:
                snum += 1
        except IndexError:
            return format_list
            break
            
# 計算沒有括號的列表的值。
def comput(re_value):
    while "*" in re_value or "/" in re_value:
        for i,j in enumerate(re_value):
            if j == "*":
                re_cheng = float(re_value[i-1])*float(re_value[i+1])
                re_value.pop(i-1)
                re_value.pop(i-1)
                re_value.pop(i-1)
                re_value.insert(i-1,re_cheng)

            if j == "/":
                re_chu = float(re_value[i-1])/float(re_value[i+1])
                re_value.pop(i-1)
                re_value.pop(i-1)
                re_value.pop(i-1)
                re_value.insert(i-1,re_chu)
    while "+" in re_value or "-" in re_value:
        for i,j in enumerate(re_value):
            if j == "+":
                re_jia = float(re_value[i-1])+float(re_value[i+1])
                re_value.pop(i-1)
                re_value.pop(i-1)
                re_value.pop(i-1)
                re_value.insert(i-1,re_jia)

            if j == "-":
                re_jian = float(re_value[i-1])-float(re_value[i+1])
                re_value.pop(i-1)
                re_value.pop(i-1)
                re_value.pop(i-1)
                re_value.insert(i-1,re_jian)
    return re_value[0]


# 通過循環,先查找列表的第一個")",然后在")"位置向列表前找到第一個"("所在位置,
# 並將其中的元素提取出來,生成新的列表,交給comput計算,
# 返回值再插入列表當中,繼續循環,直到沒有"("為止
def bracket_filter(list1):
    while "(" in list1:
        i = list1.index(")")
        for m in range(i,-1,-1):
            if list1[m] == "(":
                list_new = list1[(m+1):i]
                re_res = comput(list_new)
                list1.insert(m,str(re_res))
                for item1 in range(i+1-m):
                    list1.pop(m+1)
                break
    return comput(list1)
    
input_sn = input("pls input:")
f_re = format_input(input_sn)
result = bracket_filter(f_re)
print("The result is:",result)
View Code

他思路和我一樣一樣的。這里他有一個BUG,等下講。

我得到了啟發!可以把輸入的字符串分割成列表的一個一個元素。這樣就可以解決+-*/的問題了

 

 

接下來就是困惑我最久的括號問題。

在正式講括號問題前,先看看我自己在這之中調試過一些例子,看下面:

 1 s = ["12","pp"]  2 print(s[0].isnumeric())  #True 這里我了解了isnumeric()方法,新技能GET
 3 s1 = ["pp","12"]  4 print(s1[0].isnumeric())  #False
 5 
 6 s2 = '1'
 7 s3 = '2'
 8 s4 = s2 + s3  9 print(s4) #輸出12 10 
11 
12 s5 = "eret67y"
13 s6 = s5[3:6] 14 print(s6) 輸出:t67 15 
16 
17 import re 18 s7 = "5*4-2+((45/3-10*2)-2)"
19 sa = re.split(r'(\D)', s7) 20 print(sa) 21 #['5', '*', '4', '-', '2', '+', '', '(', '', '(', '45', '/', '3', '-', '10', '*', '2', ')', '', '-', '2', ')', '']
22 while True: 23     if "" in sa: 24       sa.remove("")       #去掉""
25     else: 26         break
27 print(sa) 28 
29 i =7
30 for m in range(i, -1, -1): #start stop step 31     print(m) 32 # 7
33 # 6
34 # 5
35 # 4
36 # 3
37 # 2
38 # 1
39 # 0
40 
41 s8 = "(2+(1+(4+5)+9)*2)"
42 s81= "(594)"
43 
44 
45 s9 = re.split("\((\d+\))",s81) 46 print(s9)             #獲取括號內數字
47 #['', '594', '']
48 data = re.split(r'\(([^()]+)\)', s8)  #我覺得,()在這里是有特殊意義的,代表分組,要單純表示括號,就得加轉義字符
49 print(data)    #['(2+(1+', '4+5', '+9)*2)']
50 
51 
52 s10 = "abdcdeff"
53 s11 = re.search("[^cd]+", s10)   #天吶!不是非c或d,而是非c且非d
54 print(s11)     #<_sre.SRE_Match object; span=(0, 2), match='ab'>
55 
56 
57 s12 = len("re") 58 print(s12)  #2
59 
60 
61 re_str = "3455454+97"
62 if "+" not in re_str and "-" not in re_str and "*" not in re_str \ 63         and "/" not in re_str and "(" not in re_str and ")" not in re_str: 64     print("AA") 65 else: 66     print("BB") 67 
68 num = 50/2
69 print(num)    #25.0 #有小數點,這里我也蒙比了!等一下講。
70 num1 = 50 * 2
71 print(num1)

 

上面的懂了之后,我開始搞代碼了

 

一、字符串分割為列表元素

# 將輸入的字符串格式統一轉換成列表,將數字、符號、括號都成一個獨立元素, # 如: 12+3*(14+5) ----> ["12","+","3","*","(","14","+","5",")"]
def format_input(input_re_value): input_re_value = input_re_value.replace(" ", "")     #去掉輸入的空格
    input_re_value = re.split(r'(\D)', input_re_value) while True: if "" in input_re_value: input_re_value.remove("")     #將列表中""去掉
        else: break

    return input_re_value

這里用了正則表達式的split(),不大懂的可以看我前面的博文,format_input()傳入一個字符串,返回一個列表。

 

二、+-*/

# 計算沒有括號的列表的值。加減乘除
def comput(re_value):
    while "*" in re_value or "/" in re_value:
        for i, j in enumerate(re_value):
            if j == "*":
                re_cheng = int(re_value[i - 1]) * int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_cheng)
                break

            if j == "/":
                re_chu = int(re_value[i - 1]) / int(re_value[i + 1])
                re_chu = int(re_chu)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_chu)
                break
    while "+" in re_value or "-" in re_value:
        for i, j in enumerate(re_value):
            if j == "+":
                re_jia = int(re_value[i - 1]) + int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_jia)
                print("re_jia",re_jia)
                print("re_value",re_value)
                break

            if j == "-":
                re_jian = int(re_value[i - 1]) - int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_jian)
                print(re_jian)
                print(re_value)
                break
    return re_value[0]
View Code

這里有一個坑,就是我前面說參考別人的博文,但是他寫的有一個BUG,有興趣可以研究下。這上面的代碼是我改正過的。

 

三、括號處理

這里不貼代碼,下面源碼有。就說下我的思路:

如果輸入的有括號的話:   1.用li = re.split(r'\(([^()]+)\)', input_str)將其折分

             2.data = re.search(r'\(([^()]+)\)', input_str).group() 取出最里面括號的數(包括())
         3.去除括號,找出最里面括號的數的下標,最后進行替換。

           4.還有括號的話,進行迭代,直到無括號


調試代碼:

import re
import sys

# 將輸入的字符串格式統一轉換成列表,將數字、符號、括號都成一個獨立元素,
# 如: 12+3*(14+5)  ----> ["12","+","3","*","(","14","+","5",")"]
def format_input(input_re_value):
    input_re_value = input_re_value.replace(" ", "")     #去掉輸入的空格
    input_re_value = re.split(r'(\D)', input_re_value)
    while True:
        if "" in input_re_value:
          input_re_value.remove("")     #將列表中""去掉
        else:
            break

    return input_re_value


# 計算沒有括號的列表的值。加減乘除
def comput(re_value):
    while "*" in re_value or "/" in re_value:
        for i, j in enumerate(re_value):
            if j == "*":
                re_cheng = int(re_value[i - 1]) * int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_cheng)
                break

            if j == "/":
                re_chu = int(re_value[i - 1]) / int(re_value[i + 1])
                re_chu = int(re_chu)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_chu)
                break
    while "+" in re_value or "-" in re_value:
        for i, j in enumerate(re_value):
            if j == "+":
                re_jia = int(re_value[i - 1]) + int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_jia)
                print("re_jia",re_jia)
                print("re_value",re_value)
                break

            if j == "-":
                re_jian = int(re_value[i - 1]) - int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_jian)
                print(re_jian)
                print(re_value)
                break
    return re_value[0]


def bracket(input_str):
    if not re.search(r'\(([^()]+)\)', input_str):    #若沒有括號
        s = format_input(input_str)
        print("s_format",s)
        print("comput(s)",comput(s))
        return comput(s)
    else:      #有括號
        li = re.split(r'\(([^()]+)\)', input_str)
        print("li:",li)        #['(', '9+8', '-8)']   輸入((9+8)-8)
        data = re.search(r'\(([^()]+)\)', input_str).group()
        print("data:",data)    # 輸出:(9+8)
        data_strip = data.strip("()")
        print("data_strip:",data_strip)   #9+8
        inde = li.index(data_strip)  #取得其下標
        print("index:",inde)       # 1

        ret = comput(format_input(data_strip))   #參數為列表形式
        print("ret:",ret)    #17.0
        # 如何把小括號計算后再替換進去
        li.pop(inde)
        li.insert(inde, str(ret))
        print("li:",li)   #['(', '17.0', '-8)']

        re_str = "".join(li)
        print("re_str",re_str)   #(17.0-8)


        if "+" not in re_str and "-" not in re_str and "*" not in re_str \
                and "/" not in re_str and "(" not in re_str and ")" not in re_str:
            print("有沒有return ",re_str)
            return re_str    #為什么沒有return
        else:
            return bracket(re_str)   #迭代


if __name__ == '__main__':
    while True:
        input_str = input("please input(q=quit):")
        if input_str.strip() == "":
            continue
        elif input_str == 'q' or input_str == 'quit':
            sys.exit()
        else:
            bracket_reture = bracket(input_str)
            print("result:",bracket_reture,type(bracket_reture))
View Code
 
        
 

調試實例:

C:\Python34\python3.exe C:/Users/Administrator/PycharmProjects/laonanhai/day6_test/test1.py
please input(q=quit):12+45-85+2
s_format ['12', '+', '45', '-', '85', '+', '2']
re_jia 57
re_value [57, '-', '85', '+', '2']
-28
[-28, '+', '2']
re_jia -26
re_value [-26]
comput(s) -26
result: -26 <class 'int'>
please input(q=quit):
please input(q=quit):  
please input(q=quit):(((9+9)-6)+45)+45/3*2
li: ['((', '9+9', '-6)+45)+45/3*2']
data: (9+9)
data_strip: 9+9
index: 1
re_jia 18
re_value [18]
ret: 18
li: ['((', '18', '-6)+45)+45/3*2']
re_str ((18-6)+45)+45/3*2
li: ['(', '18-6', '+45)+45/3*2']
data: (18-6)
data_strip: 18-6
index: 1
12
[12]
ret: 12
li: ['(', '12', '+45)+45/3*2']
re_str (12+45)+45/3*2
li: ['', '12+45', '+45/3*2']
data: (12+45)
data_strip: 12+45
index: 1
re_jia 57
re_value [57]
ret: 57
li: ['', '57', '+45/3*2']
re_str 57+45/3*2
s_format ['57', '+', '45', '/', '3', '*', '2']
re_jia 87
re_value [87]
comput(s) 87
result: 87 <class 'int'>
please input(q=quit):q

Process finished with exit code 0
View Code

 

 

正式源碼:

import re
import sys

# 將輸入的字符串格式統一轉換成列表,將數字、符號、括號都成一個獨立元素,
# 如: 12+3*(14+5)  ----> ["12","+","3","*","(","14","+","5",")"]
def format_input(input_re_value):
    input_re_value = input_re_value.replace(" ", "")     #去掉輸入的空格
    input_re_value = re.split(r'(\D)', input_re_value)
    while True:
        if "" in input_re_value:
          input_re_value.remove("")     #將列表中""去掉
        else:
            break

    return input_re_value


# 計算沒有括號的列表的值。加減乘除
def comput(re_value):
    while "*" in re_value or "/" in re_value:
        for i, j in enumerate(re_value):
            if j == "*":
                re_cheng = int(re_value[i - 1]) * int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_cheng)
                break

            if j == "/":
                re_chu = int(re_value[i - 1]) / int(re_value[i + 1])
                re_chu = int(re_chu)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_chu)
                break
    while "+" in re_value or "-" in re_value:
        for i, j in enumerate(re_value):
            if j == "+":
                re_jia = int(re_value[i - 1]) + int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_jia)
                break

            if j == "-":
                re_jian = int(re_value[i - 1]) - int(re_value[i + 1])
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.pop(i - 1)
                re_value.insert(i - 1, re_jian)
                break
    return re_value[0]


def bracket(input_str):
    if not re.search(r'\(([^()]+)\)', input_str):    #若沒有括號
        s = format_input(input_str)
        return comput(s)
    else:      #有括號
        li = re.split(r'\(([^()]+)\)', input_str)
        data = re.search(r'\(([^()]+)\)', input_str).group()
        data_strip = data.strip("()")
        inde = li.index(data_strip)  #取得其下標

        ret = comput(format_input(data_strip))   #參數為列表形式
        li.pop(inde)
        li.insert(inde, str(ret))
        re_str = "".join(li)

        if "+" not in re_str and "-" not in re_str and "*" not in re_str \
                              and "/" not in re_str and "(" not in re_str and ")" not in re_str:
            return re_str    #為什么沒有return
        else:
            return bracket(re_str)   #迭代


if __name__ == '__main__':
    while True:
        input_str = input("please input(q=quit):")
        if input_str.strip() == "":
            continue
        elif input_str == 'q' or input_str == 'quit':
            sys.exit()
        else:
            bracket_reture = bracket(input_str)
            print("result:",bracket_reture)
View Code

 

輸出源碼:

C:\Python34\python3.exe C:/Users/Administrator/PycharmProjects/laonanhai/day6_test/fina_howo.py
please input(q=quit):50+48*82/2
result: 2018
please input(q=quit):100+15
result: 115
please input(q=quit):(((9+9)-9)+9)
result: 18
please input(q=quit):15/3*2*8/4
result: 20
please input(q=quit):
Process finished with exit code 1
View Code

 

 

歡迎轉發!
This is zcl‘s article! Thanks for your support!
文章出處:http://www.cnblogs.com/0zcl
作者:zcl

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM