您的位置:首页 > 编程语言 > Python开发

python - 采用TDD的方式,实现计算器功能

2017-09-05 18:46 926 查看
问题:

公司举办了一次TDD的研讨会,讨论的程序为实现计算器的+-*/()。

要求采用TDD的方式进行程序的开发,并且程序是稳定的。

TDD的例子:

str0 = '1 +2 '
str4 = '10+22'
str5 = '10+22-33'
str6 = '10+22-33*44+55 /66 '
str1 = '1+(2-3)*4/5'
str2 = '10+((20-3)*4)/5'
str3 = '1+(((2-3)*4)/5)'
strn = '100+5-2*(4*5+1)+((7/8+6)*9/5-3)'
str_err = 'alsdjfk'


解决方案:

电脑的计算方式和人的大脑的计算方式类似。

1、先找到左括号和右括号,然后计算里面的值。

2、采用递归,完成所有括号的计算,并将计算得出的值替换掉括号。

3、找到*/,并按顺序进行。

4、找到+-,并按顺序进行。

知识点:

1、

return mulordev(list1) # python迭代的坑,每一次迭代必须有返回值

2、

list2 = re.split(r'[+-/*/]', str6)


讨论:

1、暂不考虑浮点计算。

2、计算的程序均采用递归,括号做一次,乘除做一次,加减做一次,有点冗余。

3、比较研讨会上采用C语言来实现。比较:C更加严谨,层次感强。python更加直观,通俗易懂。

源代码:

# coding:utf-8
import random
import re

flag_change = 0 # 用于处理括号

def new_list(str0):
'''生成可计算的字符串'''
# list2 = re.split(r'[+-/*/]', str6)
# for m in range(0,len(list2),1):
# list2[m] = list2[m].strip()
# print list2
list0 = list(str0)
length = len(list0)
num = 0
list_new = []
for m in range(0,length,1):
if '0'<=list0[m]<='9':
flag_change = 1
num = 10*num +int(list0[m])
if '+'==list0[m] or '-'==list0[m] or '*'==list0[m] or '/'==list0[m] or '('==list0[m] or ')'==list0[m]:
if 1 == flag_change:
flag_change = 0
list_new.append(str(num))
num = 0
list_new.append(list0[m])
if length-1 == m and ')'!=list0[m]: # 不以右括号结尾
list_new.append(str(num))
return list_new

def mulordev(list1):
'''计算乘除'''
print list1
length = len(list1)
for m in range(0,length,1):
if length-1 == m:
return list1
if '*' == list1[m]:
list1[m + 1] = str(int(list1[m - 1]) * int(list1[m + 1]))
del list1[m - 1]
del list1[m - 1]
break
if '/' == list1[m]:
list1[m + 1] = str(int(list1[m - 1]) / int(list1[m + 1]))
del list1[m - 1]
del list1[m - 1]
break
return mulordev(list1) # python迭代的坑,每一次迭代必须有返回值

def addormin(list1):
'''计算加减'''
print list1
length = len(list1)
for m in range(0, length, 1):
if '+' == list1[m]:
list1[m + 1] = str(int(list1[m - 1]) + int(list1[m + 1]))
del list1[m - 1]
del list1[m - 1]
break
if '-' == list1[m]:
list1[m + 1] = str(int(list1[m - 1]) - int(list1[m + 1]))
del list1[m - 1]
del list1[m - 1]
break
if length - 1 == m:
return list1
return addormin(list1) # python迭代的坑,每一次迭代必须有返回值

def brackets(list1):
'''计算括号'''
print list1
length = len(list1)
if '(' not in list1 and ')' not in list1:
return list1
flag_left = 0
flag_right = 0
for m in range(0,length,1):
if '(' == list1[m]:
flag_left = m
if ')' == list1[m]:
flag_right = m
list1[flag_left] = addormin(mulordev(list1[flag_left+1 : flag_right]))[0]
del list1[flag_left+1 : flag_right+1]
break
return brackets(list1)

str0 = '1 +2 ' str4 = '10+22' str5 = '10+22-33' str6 = '10+22-33*44+55 /66 ' str1 = '1+(2-3)*4/5' str2 = '10+((20-3)*4)/5' str3 = '1+(((2-3)*4)/5)' strn = '100+5-2*(4*5+1)+((7/8+6)*9/5-3)' str_err = 'alsdjfk'

str_cal = str_err
print '字符串为:%s \n计算结果为:%d\n' % (str_cal, int(addormin(mulordev(brackets(new_list(str_cal))))[0]))

'''
['100', '+', '5', '-', '2', '*', '(', '4', '*', '5', '+', '1', ')', '+', '(', '(', '7', '/', '8', '+', '6', ')', '*', '9', '/', '5', '-', '3', ')']
['4', '*', '5', '+', '1']
['20', '+', '1']
['20', '+', '1']
['21']
['100', '+', '5', '-', '2', '*', '21', '+', '(', '(', '7', '/', '8', '+', '6', ')', '*', '9', '/', '5', '-', '3', ')']
['7', '/', '8', '+', '6']
['0', '+', '6']
['0', '+', '6']
['6']
['100', '+', '5', '-', '2', '*', '21', '+', '(', '6', '*', '9', '/', '5', '-', '3', ')']
['6', '*', '9', '/', '5', '-', '3']
['54', '/', '5', '-', '3']
['10', '-', '3']
['10', '-', '3']
['7']
['100', '+', '5', '-', '2', '*', '21', '+', '7']
['100', '+', '5', '-', '2', '*', '21', '+', '7']
['100', '+', '5', '-', '42', '+', '7']
['100', '+', '5', '-', '42', '+', '7']
['105', '-', '42', '+', '7']
['63', '+', '7']
['70']
字符串为:100+5-2*(4*5+1)+((7/8+6)*9/5-3)
计算结果为:70
'''
******** TDD - 第一次 ****************
# coding:utf-8
import random

def add(a,b):
    return int(a) + int(b)
def min(a,b):
    return int(a) - int(b)
def mul(a,b):
    return int(a) * int(b)
def dev(a,b):
    return int(a) / int(b)

str0 = '1+2'
str4 = '10+22'
str1 = '1+(2-3)*4/5'
str2 = '10+(20-3)*4/5'
str3 = '1+2-3*4/5'
result = 0

list0 = list(str4)
print list0
length = len(list0)
num = 0
list_new = []
for m in range(0,length,1):
    if '0'<=list0[m]<='9':
        num = 10*num +int(list0[m])
    if '+'==list0[m] or '-'==list0[m]:
        list_new.append(str(num))
        list_new.append(list0[m])
        num = 0
    if length-1 == m:
        list_new.append(str(num))
print list_new

length = len(list_new)
for m in range(0,length,1):
    if '+' == list_new[m]:
        print m
        list_new[m-1] = str(int(list_new[m-1]) + int(list_new[m+1]))
        del list_new[m]
        del list_new[m]
        break
        
print list_new

************ TDD - 第二次 **************************
str0 = '1+2'
str4 = '10+22'
str5 = '10+22-33'
str1 = '1+(2-3)*4/5'
str2 = '10+(20-3)*4/5'
str3 = '1+2-3*4/5'
result = 0

list0 = list(str5)
print list0
length = len(list0)
num = 0
list_new = []
for m in range(0,length,1):
    if '0'<=list0[m]<='9':
        num = 10*num +int(list0[m])
    if '+'==list0[m] or '-'==list0[m]:
        list_new.append(str(num))
        list_new.append(list0[m])
        num = 0
    if length-1 == m:
        list_new.append(str(num))
print list_new

length = len(list_new)
for m in range(0,length,1):
    if '+' == list_new[m]:
        list_new[m+1] = str(int(list_new[m-1]) + int(list_new[m+1]))
    if '-' == list_new[m]:
        list_new[m + 1] = str(int(list_new[m-1]) - int(list_new[m+1]))
print list_new[-1]

****************** TDD - 第三次 ********************************************
str0 = '1 +2 '
str4 = '10+22'
str5 = '10+22-33'
str6 = '10+22-33*44+55 /66 '
str1 = '1+(2-3)*4/5'
str2 = '10+(20-3)*4/5'
str3 = '1+2-3*4/5'
result = 0

list2 = re.split(r'[+-/*/]', str6)
for m in range(0,len(list2),1):
    list2[m] = list2[m].strip()
print list2

list0 = list(str6)
print list0
length = len(list0)
num = 0
list_new = []
for m in range(0,length,1):
    if '0'<=list0[m]<='9':
        num = 10*num +int(list0[m])
    if '+'==list0[m] or '-'==list0[m] or '*'==list0[m] or '/'==list0[m]:
        list_new.append(str(num))
        list_new.append(list0[m])
        num = 0
    if length-1 == m:
        list_new.append(str(num))
print list_new
print '***'
def mulordev(list1):
    print list1
    length = len(list1)
    for m in range(0,length,1):
        if length-1 == m:
            return list1
        if '*' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) * int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if '/' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) / int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
    return mulordev(list1) # python迭代的坑,每一次迭代必须有返回值

def addormin(list1):
    print list1
    length = len(list1)
    for m in range(0, length, 1):
        if '+' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) + int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if '-' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) - int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if length - 1 == m:
            return list1
    return addormin(list1) # python迭代的坑,每一次迭代必须有返回值

print addormin(mulordev(list_new))

*************** TDD - 第四次 *******************************
# coding:utf-8
import random
import re

def new_list(str0):
    '''生成可计算的字符串'''
    # list2 = re.split(r'[+-/*/]', str6)
    # for m in range(0,len(list2),1):
    #     list2[m] = list2[m].strip()
    # print list2
    list0 = list(str0)
    length = len(list0)
    num = 0
    list_new = []
    for m in range(0,length,1):
        if '0'<=list0[m]<='9':
            num = 10*num +int(list0[m])
        if '+'==list0[m] or '-'==list0[m] or '*'==list0[m] or '/'==list0[m]:
            list_new.append(str(num))
            list_new.append(list0[m])
            num = 0
        if length-1 == m:
            list_new.append(str(num))
    return list_new

def mulordev(list1):
    '''计算乘除'''
    # print list1
    length = len(list1)
    for m in range(0,length,1):
        if length-1 == m:
            return list1
        if '*' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) * int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if '/' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) / int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
    return mulordev(list1) # python迭代的坑,每一次迭代必须有返回值

def addormin(list1):
    '''计算加减'''
    # print list1
    length = len(list1)
    for m in range(0, length, 1):
        if '+' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) + int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if '-' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) - int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if length - 1 == m:
            return list1
    return addormin(list1) # python迭代的坑,每一次迭代必须有返回值

str0 = '1 +2 '
str4 = '10+22'
str5 = '10+22-33'
str6 = '10+22-33*44+55 /66 '
str1 = '1+(2-3)*4/5'
str2 = '10+(20-3)*4/5'
str3 = '1+2-3*4/5'
result = 0
str_cal = str6
c623
print '字符串为:%s \n计算结果为:%d\n' % (str_cal, int(addormin(mulordev(new_list(str_cal)))[0]))

****************** TDD - 第五次 *******************************************************
# coding:utf-8
import random
import re

flag_change = 0 # 用于处理括号

def new_list(str0):
    '''生成可计算的字符串'''
    # list2 = re.split(r'[+-/*/]', str6)
    # for m in range(0,len(list2),1):
    #     list2[m] = list2[m].strip()
    # print list2
    list0 = list(str0)
    length = len(list0)
    num = 0
    list_new = []
    for m in range(0,length,1):
        if '0'<=list0[m]<='9':
            flag_change = 1
            num = 10*num +int(list0[m])
        if '+'==list0[m] or '-'==list0[m] or '*'==list0[m] or '/'==list0[m] or '('==list0[m] or ')'==list0[m]:
            if 1 == flag_change:
                flag_change = 0
                list_new.append(str(num))
                num = 0
            list_new.append(list0[m])
        if length-1 == m and ')'!=list0[m]: # 不以右括号结尾
            list_new.append(str(num))
    return list_new

def mulordev(list1):
    '''计算乘除'''
    print list1
    length = len(list1)
    for m in range(0,length,1):
        if length-1 == m:
            return list1
        if '*' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) * int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if '/' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) / int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
    return mulordev(list1) # python迭代的坑,每一次迭代必须有返回值

def addormin(list1):
    '''计算加减'''
    print list1
    length = len(list1)
    for m in range(0, length, 1):
        if '+' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) + int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if '-' == list1[m]:
            list1[m + 1] = str(int(list1[m - 1]) - int(list1[m + 1]))
            del list1[m - 1]
            del list1[m - 1]
            break
        if length - 1 == m:
            return list1
    return addormin(list1) # python迭代的坑,每一次迭代必须有返回值

def brackets(list1):
    '''计算括号'''
    print list1
    length = len(list1)
    flag_left = 0
    flag_right = 0
    for m in range(0,length,1):
        if '(' == list1[m]:
            flag_left = m
        if ')' == list1[m]:
            flag_right = m
            list1[flag_left] = addormin(mulordev(list1[flag_left+1 : flag_right]))[0]
            del list1[flag_left+1 : flag_right+1]
            break
    return list1

    # return brackets(list1)

str0 = '1 +2 '
str4 = '10+22'
str5 = '10+22-33'
str6 = '10+22-33*44+55 /66 '
str1 = '1+(2-3)*4/5'
str2 = '10+((20-3)*4)/5'
str3 = '1+(((2-3)*4)/5)'

str_cal = str1
# print '字符串为:%s \n计算结果为:%d\n' % (str_cal, int(addormin(mulordev(new_list(str_cal)))[0]))
print brackets(new_list(str_cal))
print '字符串为:%s \n计算结果为:%d\n' % (str_cal, int(addormin(mulordev(brackets(new_list(str_cal))))[0]))

附:研讨会版本 和 zhengrq版本
**********研讨会版本***********
 #include <string.h>

#define OP_ADD  '+'
#define OP_SUB  '-'
#define OP_EOF  '\0'

typedef struct Ctx_t
{
    char * str;
    int    pos;
} Ctx;

typedef struct Env_t
{
    Ctx ctx;
    int res;
} Env;

typedef struct OpEnv_t
{
    Ctx  ctx;
    char op;
} OpEnv;

static Env num(const Ctx ctx)
{
    Env env;

    env.res     = ctx.str[ctx.pos] - '0';
    env.ctx.str = ctx.str;
    env.ctx.pos = ctx.pos + 1;

    return env;
}

static OpEnv getOp(const Ctx ctx)
{
    OpEnv env;

    env.op      = ctx.str[ctx.pos];
    env.ctx.str = ctx.str;
    env.ctx.pos = ctx.pos + 1;

    return env;
}
static int addOrSub(const int left, const int right, const char op)
{
    if (op == OP_ADD)
    {
        return left + right;
    }
    else
    {
        return left - right;
    }
}

static Env calc(const Ctx ctx)
{
    Env   env;
    OpEnv opEnv;
    int   res = 0;

    env = num(ctx);
    res = env.res;

    while ((opEnv = getOp(env.ctx)).op != OP_EOF)
    {
        env   = num(opEnv.ctx);
        res   = addOrSub(res, env.res, opEnv.op);
    }
    env.res = res;
    
    return env;
}

int expr(const char * str)
{
    Ctx   ctx = {(char *)str, 0};

    return calc(ctx).res;
}

***********zhengrq版本********************
expr.h:
#include <stdio.h>
#include <ctype.h>
const int maxn = 1000;

int cal(const char *c, int i, int l);

int get(const char *c, int *i)
{
    if (c[*i] == '(')
    {
    int cnt = 1, b = *i + 1;
        for ((*i)++; cnt; (*i)++)
            if (c[*i] == '(') cnt++;
            else if (c[*i] == ')') cnt--;
        return cal(c, b, *i - 1);
    }
    int res = 0;
    for (; c[*i] && c[*i] >= '0' && c[*i] <= '9'; (*i)++) res = 10 * res + c[*i] - '0';
    return res;
}

int cal(const char *c, int i, int l)
{
    int s[maxn], top = 0, flag = 1;
    while (i < l)
    {
        if (c[i] == '+') flag = 1, i++;
        else if (c[i] == '-') flag = -1, i++;
        else if (c[i] == '*') i++, s[top] *= get(c, &i);
        else if (c[i] == '/') i++, s[top] /= get(c, &i);
        else s[++top] = get(c, &i) * flag;
    }
        int res = 0;
    while (top) res += s[top--];
    return res;
}

int expr(const char *c)
{
    int l = 0;
    while (c[l]) l++;
    return cal(c, 0, l);
}

main.cpp:

#include <stdio.h>
#include "expr.h"
#include <assert.h>

int main()
{
    char c[100];
    int x;
    while(~scanf("%d", &x))
        printf("%d\n", ~x);
    while(~scanf("%s", c)) printf("%d\n", expr(c));
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python