♥软工结对作业♥

结对成员:萨伊拜 3221005241
     阿比旦 3221005195


GitHub地址

一、作业题目及要求:

作业题目 实现一个自动生成小学四则运算题目的命令行程序
作业需求 博客园-flowet

二、 程序实现:

项目代码

image
总体流程图


image

  1. 命令行参数解析和选项处理:
    1.1 设计思路:
  • 这个模块的目标是解析命令行参数并根据参数执行相应的功能。使用getopt库来解析参数。

    1.2 关键步骤:

  • 导入getopt和sys模块。

  • 定义默认的参数值,如n_default(题目数量,默认为10)、r_default(数值范围,默认为10)、input_np(题目文件路径,默认为空)、input_rp(答案文件路径,默认为空)、back(是否需要回退,默认为1,表示不需要回退)。

  • 使用getopt.getopt函数解析命令行参数,接受用户提供的参数和选项。

  • 根据选项的不同,更新相应的参数变量,例如n_default和r_default。

  • 如果用户提供了-e和-a选项,表示需要执行批改操作,并记录题目文件和答案文件的路径。

  • 返回解析后的参数值供后续模块使用。

代码如下
 n_default = 10  # 默认题目数量
    r_default = 10  # 默认数值范围
    try:
        input_np= ''  # 题目文件
        input_rp = ''  # 答案文件
        opts, args = getopt.getopt(argv, "hgn:r:e:a:", ["ifile=", "ofile="])
    except getopt.GetoptError:
        print('输入错误:  \n 请按以下格式输入:-n num -r num / -e -a \n(可输入参数-h输出帮助信息)')
        sys.exit(2)
2. 生成四则运算题目和答案:
2.1 设计思路:
  • 这个模块的目标是生成满足题目要求的四则运算题目和对应的答案。

    2.2 关键步骤:

  • 定义makeproblem(n_num,r_num)函数,接受用户指定的题目数量n_num和数值范围r_num。

  • 创建两个空列表exercises_txt和answers_txt,用于存储生成的题目和答案。

  • 使用循环生成指定数量的题目,每次生成一个题目和对应的答案。

  • 在生成题目时,确保题目满足要求,包括数值范围、运算符个数、运算过程不产生负数等。

  • 计算生成题目的答案。

  • 将生成的题目和答案分别添加到exercises和answers列表中。

  • 并将题目和答案存到TXT文件中

  • 返回生成的题目和答案列表供后续模块使用。

查看代码

def makeproblem(n_num, r_num):
Exercises_txt = open('Exercises' + '.txt', "w", encoding='utf-8')
Answers_txt = open('Answers' + '.txt', "w", encoding='utf-8')

getmain = Rmain(r_num, n_num)
for i in range(len(getmain[0])):
    Exercises_txt.write(str(i + 1) + ". " + getmain[0][i] + '\n')
    Answers_txt.write(str(i + 1) + ". " + getmain[1][i] + '\n')
    print('正在生成算式...')
Exercises_txt.close()
Answers_txt.close()
print("已生成" + str(n_num) + "个题目,其中题目中的数值(自然数、真分数和真分数分母)的范围在[0," + str(r_num) + "]")
return getmain
  1. 批改题目和答案:
    3.2 设计思路:
  • 这个模块的目标是批改题目和答案,并输出批改结果。

    3.2 关键步骤:

  • 定义check_exercises_and_answers函数,接受题目列表exercises和答案列表answers。

  • 初始化正确题目数量correct_count为0,正确题目的编号列表correct_indices为空,错误题目数量wrong_count为0,错误题目的编号列表wrong_indices为空。

  • 使用循环遍历题目列表和答案列表,逐个比对题目的用户答案和正确答案。

  • 如果用户答案与正确答案一致,将correct_count增加1,并将题目的编号添加到correct_indices列表中。

  • 如果用户答案与正确答案不一致,将wrong_count增加1,并将题目的编号添加到wrong_indices列表中。

  • 返回正确题目数量、正确题目的编号列表、错误题目数量和错误题目的编号列表供后续模块使用。

查看代码

def jianchadaan(file1, file2):
    try:
        question_path = open(file1, 'r', encoding='utf-8')
        question_text = question_path.read()
    except IOError:
        print("读取失败".format(file1))
    else:
        try:
            answer_path = open(file2, 'r', encoding='utf-8')
            answer_text = answer_path.read()
        except IOError:
            print("读取失败".format(file2))
        else:
        q_spilt = re.split('\n', question_text)
        a_spilt = re.split('\n', answer_text)
        q_spilt = [i for i in q_spilt if i != '']
        a_spilt = [i for i in a_spilt if i != '']
        q_spilt = renameaq(q_spilt)
        a_spilt = renameaq(a_spilt)
        if (len(q_spilt) == len(a_spilt)):
            print("正在检查问题答案对错.....\n" + "\n问题来源:" + file1 +
                  "\n答案来源:" + file2 + "\n即将批改" + str(len(q_spilt)) + "道题目\n\n")
            # print('检查题目: 已检查' + str(len(q_spilt)) + '道题目')
            aq_dict = dict(zip(q_spilt, a_spilt))
            checkanswers = checkAnswers(aq_dict)
            wrong_list = wrongAnswers(aq_dict)
            correct_str = "Correct: " + str(len(checkanswers)) + '(' + ",".join(
                str(i) for i in checkanswers) + ')'
            wrong_str = "   Wrong: " + str(len(wrong_list)) + '(' + ",".join(str(i) for i in wrong_list) + ')'
            print(correct_str + wrong_str + "\n正确率:" + str(
                round((len(q_spilt) - len(wrong_list)) / len(q_spilt),
                      2)))
            getdown = pigaijieguo(aq_dict)
            Grade_txt = open('Grade' + '.txt', "w", encoding='utf-8')
            Grade_txt.write(getdown)
            Grade_txt.close()
        else:
            print("题目总数和答案总数不相等:\n题目个数" + str(len(q_spilt)) + "\n答案个数:" + str(
                len(a_spilt)) + "\n请检查上传的问题答案文件n\n")
4. 辅助函数: 4.1 设计思路: - 这个模块包括一些辅助函数,用于处理真分数、计算四则运算、获取当前时间等。

4.2 关键步骤:

  • 根据需要编写函数来处理真分数的表示、进行四则运算的计算、获取当前时间等功能。
  • 这些函数可以在不同的地方被调用,以提高代码的可维护性和可读性。

查看代码

def get_current_time():
    current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
    return current_time

def renameaq(aq):
last_aq = []
for change in aq:
print(change)
last_aq.append("".join(str(i) for i in pro_suanshi(change)))
return last_aq

5. 异常处理: 5.1 设计思路: - 异常处理模块用于处理可能发生的异常情况,例如文件读写错误、输入参数错误等。

5.2 关键步骤:

  • 在程序中使用try和except语句来捕获和处理可能的异常。
  • 根据不同的异常类型采取相应的处理措施,例如打印错误信息、终止程序等。
  • 在关键的文件读写操作前后加入异常处理机制,以防止文件不存在或无法读写的情况。

查看代码

 try:
        input_np= ''  # 题目文件
        input_rp = ''  # 答案文件
        opts, args = getopt.getopt(argv, "hgn:r:e:a:", ["ifile=", "ofile="])
    except getopt.GetoptError:
        print('输入错误:  \n 请按以下格式输入:-n num -r num / -e -a \n(可输入参数-h输出帮助信息)')
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(
                " 程序指令说明\n-n <数字>(大于0) ,指定生成题目的数量,默认为10"
                "\n-r <数字>(大于0) ,指定题目中数值范围,默认[0,10]"
                "\n-e .txt -a .txt 对给定的题目文件和答案文件,判定答案中的对错并进行数量统计 ")
            sys.exit(2)
        elif opt in ("-n", "--num"):
            n_default = arg
        elif opt in ("-r", "--range"):
            r_default= arg
        elif opt in ("-e", "--question"):
            input_np= arg
        elif opt in ("-a", "--answer"):
            input_rp = arg
if (input_np == '' and input_rp == ''):
    makeproblem(n_default, r_default)
else:
    jianchadaan(input_np ,input_rp)


6. 帮助信息:
6.1 设计思路:

  • 在命令行参数解析模块中提供帮助信息,解释每个选项的用途和格式。

    6.2 关键步骤:

  • 在解析命令行参数时,如果用户提供了-h选项,则打印帮助信息,并提供程序的使用说明。

  • 帮助信息应包括每个选项的说明,以便用户了解如何正确使用程序。

查看代码

 if opt == '-h':
            print(
                " 程序指令说明\n-n <数字>(大于0) ,指定生成题目的数量,默认为10"
                "\n-r <数字>(大于0) ,指定题目中数值范围,默认[0,10]"
                "\n-e .txt -a .txt 对给定的题目文件和答案文件,判定答案中的对错并进行数量统计 ")
            sys.exit(2)

7. 主程序入口: 7.1 设计思路: - 主程序入口模块用于根据用户提供的命令行参数执行相应的功能,包括生成题目、批改题目、输出结果等。

7.2 关键步骤:

  • 在if name == 'main':中调用parse_command_line_arguments函数解析命令行参数,获取各个选项的值。
  • 根据back的值,判断用户是要生成题目还是批改题目,并执行相应的操作。
  • 如果生成题目,调用generate_exercises_and_answers函数生成题目和答案,并保存到文件。
  • 如果批改题目,调用check_exercises_and_answers函数批改题目和答案,并输出批改结果到文件。

查看代码

if __name__ == '__main__':
    main(sys.argv[1:])
    # jianchadaan('1.txt','2.txt')
    import cProfile
    import re
#
cProfile.run('re.compile("foo|bar")')

三、 程序结果:

  1. 使用 -n 参数控制生成题目的个数

    image
    image
    image

  2. 使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围
    image
    image
    image

  3. 在生成题目的同时计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件
    image
    4.生成一万道题目
    image
    image
    5.程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计
    image

image

四、 PSP表格:

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

五、 总结与体会

通过这次结对编程项目,我深刻体会到了合作与协作的力量,这些体会对个人和团队都有着重要的意义:

1)团队协作的重要性:在项目中,与队友紧密协作的重要性变得非常明显。良好的协作可以提高项目的效率,减少误解和偏差,确保项目朝着正确的方向前进。不断的交流、分享思路和问题解决对于团队的成功至关重要。

2)分工与互补:合理的角色分工是项目成功的关键。根据队友的技能和兴趣,可以将任务分配得更合理。这样可以充分发挥每个人的专长,提高项目的质量和效率。同时,不同背景和经验的人在项目中可以相互补充,带来更多创新和多样性。

3)问题解决和学习:在项目中,我们遇到了各种各样的挑战和问题。与队友一起解决这些问题是一次宝贵的学习机会。通过合作,我们能够共同寻找解决方案,学习新的知识和技能,不断提高自己的能力。

4)沟通与理解:良好的沟通是协作的基础。在项目中,我学会了更加积极地倾听队友的意见,表达自己的想法,并确保信息的传递是清晰和明确的。这有助于避免误解和提高工作效率。

5)团队凝聚力:共同努力完成一个项目可以增强团队的凝聚力。互相支持、鼓励和分享成功是建立友谊和信任的途径。我们为共同取得的成就感到自豪,这种成就感可以持续激励我们继续前进。

6)成果展示与分享:完成项目后,我们有机会展示和分享自己的成果。这不仅是对我们努力工作的认可,也是向他人展示我们的能力和经验。同时,分享经验也有助于其他人学习和成长。

总的来说,结对编程项目为我提供了一个宝贵的机会,不仅在技术层面有所收获,还锻炼了团队协作、沟通和问题解决的能力。通过与队友共同努力,我不仅学到了更多知识,还建立了深厚的友谊,这将对我的职业生涯产生长远的影响。

posted on 2023-09-26 21:23  萨伊拜  阅读(16)  评论(0编辑  收藏  举报