• [原创]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:Python34python3.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:Python34python3.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

  • 相关阅读:
    源代码的下载和翻译
    Git使用入门
    搭建Andriod开发环境
    Andriod系统移植与驱动开发概述
    直观打印二叉树
    深度优先遍历图(DFS)
    《UNIX网络编程 卷1 套接字联网API》(第三版)阅读笔记----2018.5.22
    C/C++
    实现具有getMin功能的栈
    用两个栈来模拟一个队列
  • 原文地址:https://www.cnblogs.com/0zcl/p/5983236.html
Copyright © 2020-2023  润新知