首页 > 其他分享 >结对项目:自动生成四则运算题目

结对项目:自动生成四则运算题目

时间:2023-09-28 19:56:10浏览次数:36  
标签:结对 题目 operatorStack postfix 四则运算 生成 运算符 表达式

结对项目:自动生成四则运算题目

项目成员:

李奇龙 3121004869

李钰平 3121004870

github地址:作业仓库

这个作业属于哪个课程 点击这里
这个作业要求在哪里 点击这里
这个作业的目标 与队友共同完成结对项目——四则运算生成器

一、PSP表格

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

二、项目结构

  1. Main类:主程序入口
  2. CheckUtils类:检查答题对错情况和操作符顺序
  3. FileUtils类:用于读取文件
  4. GenerateUtils类:最主要的工具类,用于生成题目等等
  5. SaveUtils类:保存答案到文件等等操作

三、设计思路和实现过程

  1. 命令行参数解析部分:根据命令行参数的不同,程序执行相应的功能。通过判断参数个数和参数值来确定执行生成题目、检查答案还是输出帮助信息。
  2. 题目生成部分:通过随机数生成器Random,循环生成指定数量的四则运算式子。每个式子由随机生成的操作数和操作符构成,操作符从预定义的OPERATORS数组中随机选择。
  3. 数字生成部分:利用随机数生成器Random生成随机的分子和分母,并根据范围限制确定整数部分和是否有分数部分。根据不同情况,将数字以特定格式转化为字符串表示。
  4. 题目保存部分:通过BufferedWriter将生成的题目保存到名为"Exercises.txt"的文本文件中。同时,使用计数器变量保持题目序号,方便阅读。
  5. 答案计算和保存部分:根据生成的题目,将每个题目表达式按照空格拆分为运算项,通过后缀表达式转换和求值的方法计算每个题目的结果。使用BufferedWriter将答案保存到名为"Answers.txt"的文本文件中。
  6. 用户回答问题并写入自己答案的部分:根据生成的题目,把自己对于题目的回答用BufferedWriter写入”AnswersOfMine.txt”文件中。
  7. 后缀表达式转换部分:通过两个栈,一个保存运算项的后缀表达式(postfix),另一个保存运算符的栈(operatorStack),遍历每个运算项,根据运算项是运算符还是操作数进行相应的处理和判断。最后,将运算符栈中剩余的运算符按照顺序弹出,放入后缀表达式栈中。
  8. 答案检查部分:通过读取题目文件和答案文件的内容,并逐行进行比较,对每个题目求解并与答案比对,统计正确和错误数量。通过两个StringBuilder分别保存正确和错误题目的序号,方便最后输出成绩单。
  9. 文件读写部分:使用BufferedReader和BufferedWriter实现文件的读取和写入操作,其中使用try-with-resources语句,自动关闭资源,提高代码的可读性和简洁性。
  10. 成绩单保存部分:通过BufferedWriter将正确题目数量、正确题目的序号列表、错误题目数量和错误题目的序号列表保存到名为"Grade.txt"的文本文件中。

后缀表达式的转换:

通过使用两个栈来实现后缀表达式的转换。

  1. 首先,定义一个栈 operatorStack ,用于保存运算符。

​ 遍历输入的中缀表达式,对于每个运算项(数字或运算符)执行以下操作:

  1. 如果当前运算项是数字,则直接将其输出到后缀表达式栈 postfix 中。

  2. 如果当前运算项是左括号"(",则将其入栈。

  3. 如果当前运算项是右括号")",则将 operatorStack 栈顶的运算符弹出并输出到后缀表达式栈 postfix 中,直到遇到左括号"("为止,然后将左括号从 operatorStack 中弹出,但不输出到 postfix 中。

  4. 如果当前运算项是运算符,比较其与 operatorStack 栈顶运算符的优先级:如果 operatorStack 栈顶的运算符优先级大于等于当前运算符,将 operatorStack 栈顶的运算符弹出并输出到 postfix 中,重复此步骤,直到栈顶运算符优先级小于当前运算符或栈为空。

  5. 将当前运算符入栈。

  6. 当所有运算项遍历完毕后,将 operatorStack 中剩余的运算符依次弹出并输出到 postfix 中。

  7. 转换完成后,栈 operatorStack 中剩余的运算符就是按照优先级逆序排列的后缀表达式。

代码如下:

/**
 * 计算表达式的函数
 */
public static double calculateExpression(String[] terms) {
    List<String> postfix = infixToPostfix(terms);  // 将中缀表达式转换为后缀表达式
    return evaluatePostfixExpression(postfix);  // 计算后缀表达式的值
}

/**
 * 将表达式转换为后缀表达式
 */
private static List<String> infixToPostfix(String[] terms) {
    List<String> postfix = new ArrayList<>();
    List<String> operatorStack = new ArrayList<>();

    for (String term : terms) {
        if (isOperator(term)) {
            //用栈来存储原表达式中操作符的顺序
            while (!operatorStack.isEmpty() && isOperator(operatorStack.get(operatorStack.size() - 1))) {
                String topOperator = operatorStack.get(operatorStack.size() - 1);
                if (CheckUtils.compareOperatorPrecedence(topOperator, term) >= 0) {
                    postfix.add(operatorStack.remove(operatorStack.size() - 1));
                } else {
                    break;
                }
            }
            operatorStack.add(term);
        } else {
            postfix.add(term);
        }
    }

    while (!operatorStack.isEmpty()) {
        postfix.add(operatorStack.remove(operatorStack.size() - 1));
    }
    return postfix;
}

/**
 * 计算后缀表达式的值
 * @return double 返回值
 */
private static double evaluatePostfixExpression(List<String> postfix) {
    List<Double> operandStack = new ArrayList<>();

    for (String term : postfix) {
        if (isOperator(term)) {
            double operand2 = operandStack.remove(operandStack.size() - 1);
            double operand1 = operandStack.remove(operandStack.size() - 1);

            // 根据运算符进行计算
            switch (term) {
                case "+":
                    operandStack.add(operand1 + operand2);
                    break;
                case "-":
                    operandStack.add(operand1 - operand2);
                    break;
                case "*":
                    operandStack.add(operand1 * operand2);
                    break;
                case "÷":
                    operandStack.add(operand1 / operand2);
                    break;
            }
        } else {
            operandStack.add(parseNumber(term));
        }
    }
    return operandStack.get(0);
}

四、效能分析

Override如下:


内存分布如下:

由于操作时要将数字大量的转为字符串,同时在判断算数运算符的时候需要使用到char,因此char类型和string类型占用的空间内存最大

五、测试与运行

测试代码如下:

public class MainTest {
    @Test
    public void mainTest(){
        // 生成10个题目以及范围为6
        System.out.println(">>>生成问题");
        System.out.println();
        String[] args = {"-n","10","-r","6"};
        Main.main(args);
        System.out.println(">>>回答问题");
        System.out.println();
        // 第二个分支
        String[] args2 = {"-e","src/main/java/com/jiedui/test/Exercises.txt","-a","src/main/java/com/jiedui/test/AnswersOfMine.txt"};
        Main.main(args2);

        // 异常分支
        System.out.println(">>>故意进入异常分支");
        Main.main(new String[0]);
    }
}

测试结果如下:

覆盖率如下:


生成的文件如下:

第一次:

(利用命令行参数输入题目个数n=5,数值范围r=4,自动生成题目和答案)

(生成的5个题目)

(题目对应的答案)

(输入自己的回答)

(利用命令行参数检查自己的答题情况)

(答题情况)

第二次:

(利用命令行参数输入题目个数n=10,数值范围r=6,自动生成题目和答案)

(生成的10个题目)

(题目对应的答案)

(输入自己的回答)

(利用命令行参数检查自己的答题情况)

(答题情况)

六、项目小结

李钰平:负责了大部分的代码设计以及编码规范等等。同时在写代码的时候由于有同伴的提醒和纠错,帮助提高了自身素质和代码质量。同时,在设计项目初始的时候,合作思考可以考虑的更加全面。

李奇龙:主要负责文档编写和代码测试,以及代码注释的编写等等。在代码测试的时候,可以帮助找到代码中的一些bug,也为使用idea的调试功能更加熟练。

标签:结对,题目,operatorStack,postfix,四则运算,生成,运算符,表达式
From: https://www.cnblogs.com/lqlzzz/p/17734445.html

相关文章

  • 结对项目:实现一个自动生成小学四则运算题目的命令行程序
    结对项目软件工程首页-计科21级12班-广东工业大学-班级博客-博客园作业要求结对项目-作业-计科21级12班-班级博客-博客园作业目标实现一个自动生成小学四则运算题目项目成员3121004692甘盛培3121004702李梦承GitHubGitH......
  • 结对项目:实现自动生成小学四则运算题目
    这个作业属于哪个课程软件工程这个作业要求在哪里结对项目这个作业的目标学会团队配合的流程完成结对项目:四则运算生成器团队成员信息姓名学号Github作业链接傅浩钊3121004993傅浩钊:GitHub作业链接车文超3121002783车文超:GitHub作业链接P......
  • 结对项目:实现自动生成小学四则运算题目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade21-12这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade21-12/homework/13016这个作业的目标实现小学四则运算的自动生成Github链接https://github.com/lsw11322/lsw11322/tree......
  • 结对项目——实现一个自动生成小学四则运算题目的命令行程序—陈泽瀚and林桂旭
    软工作业3:结对项目:实现一个自动生成小学四则运算题目的命令行程序作业属于课程课程首页-计科21级1班-广东工业大学-班级博客-博客园作业要求个人项目-作业2-计科21级1班-广东工业大学-班级博客-博客园这个作业的目标实现一个自动生成小学四则运算题......
  • 结对项目-Java实现四则运算题目生成器
    软件工程21级计科1班作业要求结对项目作业目标了解结对合作开发流程,提高合作开发效率项目成员姓名学号江卓颖3121004699詹慧丹3221004855Github地址github仓库链接PSP表PSP2.1PersonalSoftwareProcessStages预估耗时(分钟)实际耗......
  • 结对项目
    小学四则运算这个作业属于哪个课程软件工程这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade21-34/homework/13025这个作业的目标1、尝试结对编程2、深入熟悉开发过程3、设计一个能自动生成小学四则运算题并批改题目的程序合作者姓名学......
  • 四则运算
    软件工程计科21级四班作业地址https://edu.cnblogs.com/campus/gdgy/CSGrade21-12/homework/13016作业目标结对项目GitHub地址https://github.com/2077435277/FourOperation成员信息姓名学号冯威炀3121005123曾中港3121005151PSP表格P......
  • 用 Python 自动生成小学四则运算题目
    这个作业属于哪个课程软件工程这个作业要求在哪里结对项目这个作业的目标熟悉多人协作成员......
  • 结对项目:实现自动生成小学四则运算题目
    软件工程计科21级2班作业要求结对项目-实现四则运算题目生成作业目标合作完成四则运算题目生成项目成员信息姓名学号杨恒3121005146游烽3121005148Github:https://github.com/wcng010/SoftwareWork2PSP表格PSP2.1PersonalSoftwarePr......
  • 结对项目
    结对项目——小学四则运算这个作业属于哪个课程软件工程这个作业要求在哪里结对项目这个作业的目标1、尝试结对编程2、深入熟悉开发过程3、设计一个能自动生成小学四则运算题并批改题目的程序一、合作者姓名学号冯逸华3121005162马传丞312100......