python小项目编程-初级(1、计算器)
1. 需求分析
1.1 功能需求
1)支持基本的四则运算:加法(+)、减法(-)、乘法(*)、除法(/);2)支持多步运算,例如 1 + 2 * 3;3)不支持括号,但运算符优先级遵循数学规则(先乘除,后加减)
1.3 非功能需求
1)提供简单的错误处理,例如除零错误或非法运算表达式输入;2)通过单元测试确保代码的正确性并人工测试保证可用性。
2、设计
2.1 总体设计
1、输入:用户通过命令行输入一个字符串表达式,例如1+2*2,
2、解析输入:将字符串解析为数字和操作符的列表,例如 [1, '+', 2, '*', 2]
。
3、计算:先计算乘法和除法(优先级高)再计算加法和减法(优先级低)。
4、结果:返回最终的计算结果。
2.2 模块设计
1、parse_expression模块:将输入的字符串解析为数字和操作符的列表。使用正则表达式提取数字和操作符
2、calculate模块:按照运算符优先级计算表达式先处理乘和法,再处理加和减。
3、main模块:接收用户输入,处理输入异常,调用解析和计算模块,输出结果
2.3 数据结构
使用列表存储解析后的表达式,例如 [1, '+', 2, '*', 3]
。
2.4 错误处理
检查除零错误。检查非法输入进行输入规则校验保证合法输入,对非法输入抛出异常。使用正则表达式pattern来验证输入的表达式格式。正则表达式的规则确保了表达式只包含数字、运算符和括号,并且遵循正确的格式。如果输入不符合规则,抛出ValleError异常,并给出相应的错误提示。
实现
3.1 代码实现
import re
def parse_expression(expression):
"""
将表达式字符串解析为数字和操作符的列表。
例如:"1+2*3" -> [1, '+', 2, '*', 3]
"""
# 使用正则表达式匹配数字和操作符
tokens = re.findall(r'\d+|\+|\-|\*|\/', expression)
# 将数字转换为整数或浮点数
for i, token in enumerate(tokens):
if token.isdigit():
tokens[i] = int(token)
return tokens
def calculate(tokens):
"""
计算解析后的表达式列表。
处理乘法和除法的优先级。
"""
# 先处理乘法和除法
i = 0
while i < len(tokens):
if tokens[i] == '*':
tokens[i - 1] = tokens[i - 1] * tokens[i + 1]
del tokens[i:i + 2]
elif tokens[i] == '/':
tokens[i - 1] = tokens[i - 1] / tokens[i + 1]
del tokens[i:i + 2]
else:
i += 1
# 再处理加法和减法
result = tokens[0]
i = 1
while i < len(tokens):
if tokens[i] == '+':
result += tokens[i + 1]
elif tokens[i] == '-':
result -= tokens[i + 1]
i += 2
return result
def main():
print("支持的运算:加(+)、减(-)、乘(*)、除(/)")
print("输入 'exit' 退出计算器")
pattern = r'^\s*[\d]+(\.\d+)?(\s*[\+\-\*\/]\s*[\d]+(\.\d+)?)*\s*$'
while True:
expression = input("请输入表达式(例如 1+2*3):")
if expression.lower() == 'exit':
print("感谢使用,再见!")
break
try:
if not re.match(pattern, expression):
raise ValueError("输入格式错误,请确保只包含数字、运算符,并遵循正确的格式。")
tokens = parse_expression(expression)
result = calculate(tokens)
print(f"结果: {result}")
except Exception as e:
print(f"输入错误:{e}")
if __name__ == "__main__":
main()
测试:
测试用例
测试样例 | 测试结果 | 预期 |
1+1 | 2 | 2 PASS |
2*3+6 | 12 | 12 PASS |
10 - 4/2 | 8.0 | 8.0 PASS |
1+2*3 | 7 | 7 PASS |
10/0 | 输入错误:除零错误 | 输入错误:除零错误 PASS |
1+a | 输入错误 | 输入错误 PASS |
UT单元测试
import unittest
from calculator import parse_expression, calculate
class TestCalculator(unittest.TestCase):
def test_parse_expression(self):
self.assertEqual(parse_expression("1+2*3"), [1, '+', 2, '*', 3])
self.assertEqual(parse_expression("10-4/2"), [10, '-', 4, '/', 2])
def test_calculate(self):
self.assertEqual(calculate([1, '+', 2, '*', 3]), 7)
self.assertEqual(calculate([10, '-', 4, '/', 2]), 8.0)
with self.assertRaises(ValueError):
calculate([10, '/', 0])
if __name__ == "__main__":
unittest.main()