结对项目

作业概述

这个作业属于哪个课程 软件工程
这个作业要求在哪里 结对项目
这个作业的目标 和同伴共同合作完成项目

成员

  • 曹富城 学号:3121005076
  • 何继安 学号:3121005087

一、github链接

https://github.com/flash2-man/calculator
https://github.com/muxingtong/MyCalculator

二、PSP表

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 20
· Estimate · 估计这个任务需要多少时间 20 20
Development 开发 330 380
· Analysis · 需求分析 (包括学习新技术) 40 50
· Design Spec · 生成设计文档 40 50
· Design Review · 设计复审 (和同事审核设计文档) 20 30
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 20
· Design · 具体设计 40 30
· Coding · 具体编码 120 80
· Code Review · 代码复审 20 30
· Test · 测试(自我测试,修改代码,提交修改) 30 90
Reporting 报告 60 80
· Test Report · 测试报告 20 30
· Size Measurement · 计算工作量 20 20
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 20 30
合计 410 480

三、分析

  • 题目:实现一个自动生成小学四则运算题目的命令行程序

需求

  • 通过命令行参数控制程序功能
  • 生成不重复的题目
  • 计算题目答案
  • 批改,对比正确答案
  • 文件输入输出

初步模块设计图

1
2

最终采取的算法有所不同

思路

读取参数->调用对应模块
1、生成模块->检测模块->生成->写入模块
2、读取模块->计算模块->批改模块->写入模块
3、报错

四、实现

  1. 文件读写模块:包括读取文件和写入文件的函数,用于读取题目和答案文件,并将批改结果写入文件。
  2. 命令行参数解析模块:使用argparse库解析命令行参数,根据参数的不同执行不同的功能。
  3. 题目生成模块:根据指定的题目数量和运算数的最大值,生成指定数量的四则运算题目,并将题目和答案分别写入文件。
  4. 题目批改模块:读取题目和答案文件,逐行比较题目和答案,判断答案是否正确,并统计正确和错误的题目数量,最后将批改结果写入文件。

核心代码:

产生运算式子函数:

去重方法:使用集合expressions来保存已经生成的题目的逆波兰表达式。在生成每个题目之前,会将当前题目的逆波兰表达式与集合中的表达式进行比较,如果存在相同的逆波兰表达式或者结果小于0,则重新生成下一个题目。只有当题目的逆波兰表达式不重复且结果大于等于0时,才会将题目添加到集合中,并继续生成下一个题目。

def generate_expression(num_operators, scope):
    if num_operators == 0:
        num = random.randint(1, scope - 1)
        return str(num)
    else:
        operator = random.choice(symbol)
        num1 = generate_expression(num_operators - 1, scope)
        num2 = generate_expression(num_operators - 1, scope)

        expression = f"{num1} {operator} {num2}"
        if random.choice([True, False]):
            expression = f"({expression})"
        return expression
去重函数:
def is_duplicate(expression):
    rpn_expression = convert_to_rpn(expression)
    return rpn_expression in expressions

# 将中缀表达式转换为逆波兰表达式
def convert_to_rpn(expression):
    stack = []
    rpn = []
    for token in expression:
        if token in symbol:
            while stack and stack[-1] in symbol and symbol.index(stack[-1]) >= symbol.index(token):
                rpn.append(stack.pop())
            stack.append(token)
        else:
            rpn.append(token)
    while stack:
        rpn.append(stack.pop())
return tuple(rpn)  # 返回元组以便比较

批改代码部分:

使用正则表达式识别题目

incorrect_questions = []
    correct_questions = []
    for i, (line1, line2) in enumerate(zip(exercises, answers), 1):
        # 正则表达式!!!!!!!
        expression_match = re.match(r'四则运算题目.\d+\t(.*?)=', line1)
        result_match = re.search(r'\t(.*)$', line2)
        if expression_match and result_match:
            expression = expression_match.group(1).strip()
            result = result_match.group(1).strip()
            res = Fraction(eval(expression)).limit_denominator()
            result_end = f"{res.numerator // res.denominator}'{res.numerator % res.denominator}/{res.denominator}" \
                if res.numerator > res.denominator != 1 else str(res)
            if result_end == str(result):
                correct_count += 1
                correct_questions.append(str(i))
            else:
                wrong_count += 1
                incorrect_questions.append(str(i))
    # 清空文件
    open('Grade.txt', 'w').close()
    writefile('Grade.txt', f"Correct: {correct_count} ({', '.join(correct_questions)})\n")
    writefile('Grade.txt', f"Wrong: {wrong_count} ({', '.join(incorrect_questions)})\n")
    print(f"Correct answers: {correct_count},({', '.join(correct_questions)})\n")
    print(f"Wrong answers: {wrong_count},({', '.join(incorrect_questions)})\n")

五、性能测试

生成题目时

3
6

批改题目时

4
5

python main.py 
python main.py -n 10
python main.py -n 10000
python main.py -r 10
python main.py -n 10 -r 10
python main.py -n 10000 -r 1000
python main.py -n -r #报错
python main.py -e path1 -a path2
python main.py -e -a #报错

运行结果

7
9
10

六、结对感受

  • 曹富城同学:

这个项目总体上还是有难度的,之前想用别的语言写,但是实现难度有点大,后面就改用python了,总体来说这个项目做的还是挺可以的,满足了相关要求,在实践中也产生了很多很有价值的灵感,最终在不断实践纠错中提高自己,不过不足的地方在没有实现可视化界面的实现。结对编程让我对一个产品的开发有了更深的认识,可以看到一些之前没出现过的错误,两者相辅相成,将原本的版本修改的更符合用户体验了,同时也更明白了模块化的便捷性和合理性,更有助于开发项目。

  • 何继安同学:

这是我第一次和同伴合作完成项目,总体来说我对这次项目完成感觉还可以,在这个项目里,我认识到了一个程序模块化的重要性,用户体验感的必要性,在优化的过程中,我更深刻地体会到这个程序的运行过程。在实现过程中,我负责代码最终测试和优化,以我的角度去复审同伴的代码,找出其中不足,这让我有不一样的体会,对结对编程和软件工程有了更深刻的认识,让我开始期待团队项目的开始。对于同伴的建议:希望同伴能重视程序的模块化和用户的体验感。

posted @   墨语晨晖  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示