汉语版:
这个小程序是基于栈实现的计算器。用python很好实现,python列表的概念和栈有很大的相同之处。所以,我们并不需要实现stack这个类。目前项目是托管在
https://gitee.com/tostronger/data_structure。
项目的整体是一个基于Django框架的web显示。至于如何安装和部署Django项目,网上都有大量的教程。我这里就不再讲解了。
E-version:
this program was implemented by Python, the main data structure is Stack, i use python for that in python there are a lot of commons between list and stack, which you can append or pop a value on the end. so we need not implement STACK class. Now this program was gited on oschina. you can download form this website. when you run this program ,you can access it by the url 127.0.0.1/;because this is a Django project and i won`t told you how prepare Django. Good lucky!
1.接收请求参数,经过计算后返回值,通过模板将返回信息,写入到网页。
I.get the post request param, match the URL and action then return the result
def getresult(request):
ctx = {}
if request.POST:
str_input = request.POST['iWord']
ctx['original'] = str_input
ctx['rlt'] = stacks.get_stack_value(str_input)
return render(request, "home.html", ctx)
2.下面这个函数是获取参数的返回值
II.return the final result
def get_stack_value(input_str):
# 存放操作数
operator = []
# 存放操作符
operate = []
# 存放顶部操作符
top = ''
# 存放flag,flag为真,不添加当前字符
flag = False
# 临时操作数
temp_str = ''
# 预处理:basic_work(input_str)
input_str = tool.basic_work(input_str)
for index in range(len(input_str)):
# 遇到操作符,进行下面操作
if len(operate) >= 1:
top = operate[len(operate) - 1]
else:
top = ''
# 测试专用一:打印每次操作数和操作符
# print('top',operator)
# print('top',operate)
if input_str[index] == '+':
flag,temp_str = tool.set_operator_value(temp_str,operator)
tool.simple_caculate('+', top, 'out', input_str[index], operate, operator)
if input_str[index] == '-':
flag, temp_str = tool.set_operator_value(temp_str, operator)
tool.simple_caculate('-', top, 'out', input_str[index], operate, operator)
if input_str[index] == '*':
flag, temp_str = tool.set_operator_value(temp_str, operator)
tool.simple_caculate('*', top, 'out', input_str[index], operate, operator)
if input_str[index] == '/':
flag, temp_str = tool.set_operator_value(temp_str, operator)
tool.simple_caculate('/', top, 'out', input_str[index], operate, operator)
if input_str[index] == '%':
flag, temp_str = tool.set_operator_value(temp_str, operator)
tool.simple_caculate('%', top, 'out', input_str[index], operate, operator)
if input_str[index] == '^':
flag, temp_str = tool.set_operator_value(temp_str, operator)
tool.simple_caculate('^', top, 'out', input_str[index], operate, operator)
if input_str[index] == '&':
flag, temp_str = tool.set_operator_value(temp_str, operator)
tool.simple_caculate('&', top, 'out', input_str[index], operate, operator)
if input_str[index] == '.':
flag = False
if input_str[index] == '(':
operate.append(input_str[index])
flag = True
if input_str[index] == ')':
flag, temp_str = tool.set_operator_value(temp_str, operator)
if tool.compare_operation(')', top, 'out') == '<':
if len(operator) >= 2:
while operate[len(operate) - 1] == '(':
operate.pop()
operator.append(tool.compute_result(operator.pop(), operator.pop(), operate.pop()))
# 测试专用二:调试带括号的问题
# print(operator)
# print(operate)
if len(operate) >= 1 and operate[len(operate) - 1] == '(':
operate.pop()
else:
if len(operator) >= 2 :
operator.append(tool.compute_result(operator.pop(), operator.pop(), operate.pop()))
operate.pop()
# 遇到数字非法,直接退出;否则,组成临时字符
if (input_str[index] < '0' or input_str[index] > '9') and tool.not_operate(input_str[index]):
input_str = 'error in the\t'+str(index+1) + '\tcharacter!\t' + input_str + '->' + input_str[index]
return input_str
elif input_str[index] == ' ':
continue
else:
if flag:
flag = False
else:
temp_str += input_str[index]
# 遇到‘=’且为最后一个字符,返回结果
if input_str[index] == '=' and index == len(input_str)-1:
length = len(operate)
if length >= 1:
operate.pop()
else:
pass
while len(operate) > 0:
if len(operator) >= 2:
operator.append(tool.compute_result(operator.pop(), operator.pop(), operate.pop()))
else:
operate.pop()
return str(operator)
3.这里没有特别需要说明的,函数进口是定义了操作数栈和操作符栈,然后进行基本的字符处理
III.basic dealings for the raw Strings
# 文本预处理
def basic_work(input_str):
# 适应操作符连续输入
for index in range(len(input_str)-1):
if is_operator(input_str[index]) and is_operator(input_str[index+1]):
input_str = 'error in statement, duplicate operator :'+str(input_str[index])
return input_str
# 适应首字符存在符号可能性
if input_str[0] == '-':
input_str = '0'+input_str
length = len(input_str)
# 适应用户不输入等号
if input_str[length-1] == '=':
input_str = input_str[0:length-1]
input_str += '+0='
else:
input_str += '+0='
# 适应括号非对称输入
if input_str.count('(') != input_str.count(')'):
input_str = 'error in brackets! it was off-balance'
return input_str
4.执行栈算法,先比较优先级,代码如下
IV.compare the parity among operators
# 比较运算符优先级
def compare_operation(operate_one, operate_two, stack_type):
if operate_one == ')' and operate_two == '(':
return '<'
if operate_two == '' or operate_two == '(':
return '>'
if stack_type == 'out':
if '+' == operate_one:
if '(' == operate_two:
return '>'
else:
return '<'
if '-' == operate_one:
if '(' == operate_two:
return '>'
else:
return '<'
if '*' == operate_one:
if operate_two == '+' or operate_two == '-'or operate_two == '=':
return '>'
else:
return '<'
if '/' == operate_one:
if operate_two == '+' or operate_two == '-'or operate_two == '=':
return '>'
else:
return '<'
if '%' == operate_one:
if operate_two == '+' or operate_two == '-' or operate_two == '=':
return '>'
else:
return '<'
if '^' == operate_one:
if operate_two == '+' or operate_two == '-' or operate_two == '=' \
or operate_two == '*' or operate_two == '%' or operate_two == '/':
return '>'
else:
return '<'
if '&' == operate_one:
if operate_two == '+' or operate_two == '-' or operate_two == '=' \
or operate_two == '*' or operate_two == '%' or operate_two == '/':
return '>'
else:
return '<'
if ')' == operate_one:
if operate_two == '=':
return '>'
else:
return '<'
V.STACK operation ,push and pop then caculate
# 出栈,压栈运算
def simple_caculate(operate_type, top, temp, input_index, operate=[], operator=[]):
if compare_operation(operate_type, top, temp) == '>':
operate.append(input_index)
if compare_operation(operate_type, top, temp) == '<':
operator.append(compute_result(operator.pop(), operator.pop(), operate.pop()))
operate.append(input_index)
# 临时字符运算
def set_operator_value(temp_str, operator=[]):
if temp_str == '':
pass
else:
if temp_str.count('.') > 1:
operator.append(str(math.inf))
else:
operator.append(temp_str)
temp_str = ''
return True,temp_str
6.遇到非法字符要退出,所以有非法字符检测
VI.check the vaild input
# 非法字符检测器
def not_operate(character):
if character != '+' and character != '-' and character != '*' and character != '/' and character != '^' \
and character != '(' and character != ')' and character != '&' and character != '=' \
and character != '%' and character != '.' and character !=' ':
return True
else:
return False
7.数字过滤器
VII.filter the numbers
# 是否为数字判断
def is_operator(character):
if character == '+' or character == '-' or character == '*' or character == '/' or character == '^' \
or character == '&' or character == '='or character == '%' or character == '.':
return True
else:
return False
8.对两个数进行计算
VIII.caculate two number
# 计算数值结果
def compute_result(number_one, number_two, operate):
if number_one == '':
number_one = '0'
if number_two == '':
number_two == '0'
param_one = float(number_one)
param_two = float(number_two)
if operate == '+':
return param_two + param_one
if operate == '-':
return param_two - param_one
if operate == '*':
return param_two * param_one
if operate == '/':
if param_one == 0:
return math.inf
return param_two / param_one
if operate == '%':
return param_two % param_one
if operate == '^':
if param_two < 0:
if param_one > 0 and param_one % 2 == 1:
return param_two ** (1/param_one)
elif param_one < 0 and param_one % 2 == 1:
return 1/(param_two ** (1/param_one))
else:
return math.inf
if param_two > 0:
if param_one > 0:
return param_two ** (1/param_one)
elif param_one < 0:
return 1/(param_two ** (1/param_one))
else:
return math.inf
if operate == '&':
return param_two ** param_one
then we get the test page.