首页 > 其他分享 >结对项目

结对项目

时间:2024-09-28 17:23:27浏览次数:1  
标签:结对 题目 String 项目 int length RPN 运算

结对项目

这个作业属于哪个课程 计科12班
这个作业要求在哪里 作业
这个作业的目标 与团队分工合作做一个小项目

团队成员信息

成员姓名 学号 班级
范志杰 3122004345 计科1班
杨文聪 3122004372 计科1班

项目需求

使用 -n 参数控制生成题目的个数,例如

Myapp.exe -n 10

将生成10个题目。

使用 -r 参数控制题目中数值(自然数、真分数和真分数分母)的范围,例如Myapp.exe -r 10
将生成10以内(不包括10)的四则运算题目。该参数可以设置为1或其他自然数。该参数必须给定,否则程序报错并给出帮助信息。
1. 生成的题目中计算过程不能产生负数,也就是说算术表达式中如果存在形如e1− e2的子表达式,那么e1≥ e2。
2. 生成的题目中如果存在形如e1÷ e2的子表达式,那么其结果应是真分数。
3. 每道题目中出现的运算符个数不超过3个。
4. 程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。例如,23 + 45 = 和45 + 23 = 是重复的题目,6 × 8 = 和8 × 6 = 也是重复的题目。3+(2+1)和1+2+3这两个题目是重复的,由于+是左结合的,1+2+3等价于(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重复的两道题,因为1+2+3等价于(1+2)+3,而3+2+1等价于(3+2)+1,它们之间不能通过有限次交换变成同一个题目。

生成的题目存入执行程序的当前目录下的Exercises.txt文件,格式如下:

1. 四则运算题目1
2. 四则运算题目2
……

其中真分数在输入输出时采用如下格式,真分数五分之三表示为3/5,真分数二又八分之三表示为2’3/8。

在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件,格式如下:

1. 答案1
2. 答案2

特别的,真分数的运算如下例所示:1/6 + 1/8 = 7/24。

1. 程序应能支持一万道题目的生成。
2. 程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计,输入参数如下:

Myapp.exe -e .txt -a .txt

统计结果输出到文件Grade.txt,格式如下:

Correct: 5 (1, 3, 5, 7, 9)

Wrong: 5 (2, 4, 6, 8, 10)

其中“:”后面的数字5表示对/错的题目的数量,括号内的是对/错题目的编号。为简单起见,假设输入的题目都是按照顺序编号的符合规范的题目。

设计结构实现

项目结构:

生成文档:

函数调用过程

1. FourOperation:
main(String[] args)
Calculate:
checkout(String formula, int length)
calculate(String m, String n, String operator)
greatFraction(int integralPart, int molecule, int denominator)
2. Check:
generate(int n,int r)
ifRepeat(String[] ansFormula)
3. Create:
createFormula(int r)
commonFactor(int a,int b)
4. TxtIOUtils:
createProblemSet(int n,int r)
createExeFile(ArrayList txtList)
createAnsFile(ArrayList ansList)
createGradeFile(String submitPath, String answersPath)
output(PrintStream p,ArrayList quesNum)
obtainAnswer(String path)

代码说明

  1. 入口函数:
package com.my.main;

import com.my.utils.TxtIOUtils;

import java.util.Scanner;

public class FourOperation {
    /**
     * 入口
     * @param args 指令字符串数组
     */
    public static void main(String[] args) {
        ord:
        while(true) {
            //若不输入指令直接按回车键,则默认生成10条运算数在10以内的算术题

            int n = 10;//运算题数量,默认为10
            int r = 10;//运算数范围,默认为[0,10)
            String submitPath = null;//题目文件路径
            String answersPath = null;//答案文件路径

            try {
                // 输入指令
                System.out.println("请输入需要执行的指令:(详情请看说明文档.txt)");
                Scanner command = new Scanner(System.in);
                String arr[] = command.nextLine().split("\\s"); //把输入的字符串以\\s为条件分割成一个String数组

                //指令数组长度>1时,获取正常指令
                if (arr.length > 1) {
                    for (int i = 0; i < arr.length; i = i + 2) {
                        switch (arr[i]) {
                            case "-n":
                                n = Integer.parseInt(arr[i + 1]);
                                if (n > 10000 || n < 1) {
                                    System.out.println("输入的n范围错误,这是生成题目的数量,请输入大于0的整数");
                                    return;
                                }
                                break;
                            case "-r":
                                r = Integer.parseInt(arr[i + 1]);
                                if (r < 1) {
                                    System.out.println("输入的r范围错误,这是题目中的数值范围,请输入大于0的整数");
                                    return;
                                }
                                break;
                            case "-e":
                                submitPath = arr[i + 1];
                                if (submitPath == null) {
                                    System.out.println("输入错误!!!找不到题目文件的路径");
                                    return;
                                }
                                break;
                            case "-a":
                                answersPath = arr[i + 1];
                                if (answersPath == null) {
                                    System.out.println("输入错误!!!找不到答案文件的路径");
                                    return;
                                }
                                break;
                            default:
                                System.out.println("输入的指令错误!!!");
                                break;
                        }
                    }
                }else if(arr[0].equals("exit")){//输入exit退出程序
                    System.out.println("退出程序");
                    System.exit(0);
                }
                else if(arr[0].length() != 0){//输入的不是任何指令时报错,重新输入指令
                    System.out.println("输入的指令错误!!!");
                    continue ord;
                }
            } catch (NumberFormatException e) {
                System.out.println("输入的指令错误!!!请重新输入");
                continue ord;
            }

            System.out.println("n: " + n + ", r: " + r);
            TxtIOUtils makefile = new TxtIOUtils();

            //文件不为空时,创建成绩文件;为空时,创建题目文件和答案文件
            if (submitPath != null && answersPath != null)
                makefile.createGradeFile(submitPath,answersPath);
            else
                makefile.createProblemSet(n,r);
        }
    }
}

  1. 运算的主要代码设计:
package com.my.service;

import java.util.HashMap;
import java.util.Stack;

public class Calculate {

    /**
     *
     * @param formula 运算式
     * @param length 返回 RPN字符串数组的长度
     * @return RPN 含有后缀表达式、"="、运算结果和运算式的字符串数组
     */
    public String[] checkout(String formula, int length) {
        Stack<String> stackN = new Stack<>();//用栈来存放运算数
        Stack<String> stackO = new Stack<>();//用栈来存放运算符
        String[] RPN = new String[length];//逆波兰表达式(后缀表达式)
        // 哈希表存放运算符优先级
        HashMap<String, Integer> hashmap = new HashMap<>();
        hashmap.put("(", 0);
        hashmap.put("+", 1);
        hashmap.put("-", 1);
        hashmap.put("×", 2);
        hashmap.put("÷", 2);

        for (int i = 0, j = 0; i < formula.length(); ) {
            StringBuilder digit = new StringBuilder();//数字
            //将式子切割
            char c = formula.charAt(i);  //把运算式的第i个字符赋值给c
            //若c为数字,存入digit
            while (Character.isDigit(c) || c == '/' || c == '\'') { //数字、分数符号、带分数符号都要
                digit.append(c);
                i++;
                c = formula.charAt(i);
            }
            //digit里无数字,开始处理符号
            if (digit.length() == 0) {
                switch (c) {
                    //如果是“(”,就转化为字符串压入字符栈
                    case '(': {
                        stackO.push(String.valueOf(c));
                        break;
                    }
                    //遇到“)”了,则进行计算
                    case ')': {
                        String operator = stackO.pop();
                        //符号栈不为空,取操作数运算
                        while (!stackO.isEmpty() && !operator.equals("(")) {
                            String a = stackN.pop();
                            String b = stackN.pop();
                            //后缀表达式变形
                            RPN[j++] = a;
                            RPN[j++] = b;
                            RPN[j++] = operator;
                            String ansString = calculate(b, a, operator);
                            if (ansString == null)
                                return null;
                            //将结果压入栈
                            stackN.push(ansString);
                            //符号指向下一个计算符号
                            operator = stackO.pop();
                        }
                        break;
                    }
                    //遇到了“=”,计算最终结果
                    case '=': {
                        String operator;
                        while (!stackO.isEmpty()) {
                            operator = stackO.pop();
                            String a = stackN.pop();
                            String b = stackN.pop();
                            //后缀表达式变形
                            RPN[j++] = a;
                            RPN[j++] = b;
                            RPN[j++] = operator;
                            String ansString = calculate(b, a, operator);
                            if (ansString == null)
                                return null;
                            stackN.push(ansString);
                        }
                        break;
                    }
                    //其他
                    default: {
                        String operator;
                        while (!stackO.isEmpty()) {
                            operator = stackO.pop();
                            if (hashmap.get(operator) >= hashmap.get(String.valueOf(c))) { //比较优先级
                                String a = stackN.pop();
                                String b = stackN.pop();
                                //后缀表达式变形
                                RPN[j++] = a;
                                RPN[j++] = b;
                                RPN[j++] = operator;
                                String ansString = calculate(b, a, operator);
                                if (ansString == null)
                                    return null;
                                stackN.push(ansString);
                            } else {
                                stackO.push(operator);
                                break;
                            }

                        }
                        stackO.push(String.valueOf(c));  //将符号压入符号栈
                        break;
                    }
                }
            }
            //处理数字,直接压栈
            else {
                stackN.push(digit.toString());
                continue;
            }
            i++;
        }
        //栈顶数字为答案
        RPN[length - 3] = "=";
        RPN[length - 2] = stackN.peek();
        RPN[length - 1] = formula;
        return RPN;
    }


  1. 检查运算式是否有重复
package com.my.service;

import java.util.ArrayList;
import java.util.Arrays;

public class Check {
    private ArrayList<String> returnList = new ArrayList<>();
    private ArrayList<String> txtList = new ArrayList<>();
    private ArrayList<String> ansList = new ArrayList<>();
    private ArrayList<String[]> ansFoList = new ArrayList<>();


    /**
     * 生成暂存习题和答案,暂存的目的是提前检查运算式是否有重复
     * @param n 运算题数量
     * @param r 运算数范围
     * @return returnList 返回没有重复的运算式集(还含有未标序号的题和答案)
     */
    public ArrayList generate(int n,int r) {
        Create create = new Create();
        //生成n条不重复的运算式
        for(int i = 0 ; i < n;){
            //随机生成运算式
            String[] ansFormula = create.createFormula(r);
            //判断生成的运算式是否重复
            if (ansFormula != null) {
                if (!ifRepeat(ansFormula)) {
                    System.out.println((i+1)+":"+ansFormula[ansFormula.length-1]);
                    i++;
                }
            }
        }

        //把式子及运算结果添加到returnList
        for (int i = 0;i < 2*n;i++) {
            if(i < n) {
                returnList.add(txtList.get(i));
            } else {
                returnList.add(ansList.get(i-n));
            }
        }
        return returnList;
    }


    /**
     * 判断运算式是否重复
     * @param ansFormula 含有后缀表达式、运算结果和运算式的字符串数组
     * @return true(重复) / false(不重复)
     */
    private boolean ifRepeat(String[] ansFormula) {
        String formula = ansFormula[ansFormula.length-1];
        String[] rPNotation = new String[ansFormula.length-1];
        System.arraycopy(ansFormula, 0, rPNotation, 0, ansFormula.length-1);
        boolean ifRepeat = false;

        for (String[] ansFo: ansFoList) {
            if (Arrays.equals(ansFo,rPNotation)) {
                ifRepeat = true;
            } else if (ansFo.length == rPNotation.length && ansFo[ansFo.length-1].equals(rPNotation[rPNotation.length-1])){//若运算结果及长度一致,则式子可能重复,进一步比较
                int j;
                for (j=0;j<rPNotation.length-2;) {
                    boolean opRight = ansFo[j+2].equals("+")||ansFo[j+2].equals("×");
                    boolean exRight = ansFo[j].equals(rPNotation[j + 1]) && ansFo[j + 1].equals(rPNotation[j]) && ansFo[j + 2].equals(rPNotation[j + 2]);
                    boolean copRight = ansFo[j].equals(rPNotation[j]) && ansFo[j + 1].equals(rPNotation[j + 1]) && ansFo[j + 2].equals(rPNotation[j + 2]);
                    //运算符前后两个操作数交换比较
                    if (exRight&&opRight) {
                        j = j + 3;
                    } else if (copRight) {
                        j = j + 3;
                    } else {
                        break;
                    }
                }
                if (j == rPNotation.length-2) {
                    ifRepeat = true;
                    break;
                }
            }
        }

        if (!ifRepeat) {    //运算式不重复
            this.txtList.add(formula);
            this.ansList.add(rPNotation[rPNotation.length-1]);
            this.ansFoList.add(rPNotation);
        }
        return ifRepeat;
    }
}

生成题目和答案

Github链接

https://github.com/xixi-xii/3122004372/tree/main/jiedui1

小结

通过这次项目,我们不仅提升了编码效率,还培养了团队协作的能力。合理的分工、频繁的沟通、良好的版本管理以及项目过程中的反思,都为项目的成功奠定了基础。我们相信,未来在更复杂的项目中,结对编程的这些经验将继续发挥重要作用。

PSP表格

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

标签:结对,题目,String,项目,int,length,RPN,运算
From: https://www.cnblogs.com/fanzhijie/p/18438169

相关文章

  • 今日指数项目股票成交量对比功能
    股票成交量对比功能1.股票成交量对比功能分析1.1模型示列功能描述:统计A股大盘T日和T-1日成交量对比功能(成交量为沪深两市成交量之和)1.2接口示列返回数据格式服务路径:/api/quot/stock/tradeAmt服务方法:GET前端请求频率:每分钟请求参数:无{"code":1,"da......
  • 结对项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标完成一个四则运算项目来了解项目开发流程项目成员李建龙github地址:https://git......
  • .Net8使用Cli命令创建基础项目
    第一步:创建项目结构#创建解决方案dotnetnewsln-nFxcdFx#创建WebAPI层dotnetnewwebapi-nFx.WebApi#创建Application层dotnetnewclasslib-nFx.Application#创建Domain层dotnetnewclasslib-nFx.Domain#创建Infrastructure层dotnetne......
  • 黑马PM-内容项目-需求分析
    需求分析的定义需求分析的时机需求分析的步骤......
  • DC00020基于springboot新闻网站系统java web项目MySQL新闻管理系统
    1、项目功能演示DC00020基于springboot新闻网站系统javaweb项目MySQL2、项目功能描述  基于springboot+vue新闻网站包括用户和系统管理员两个角色。2.1用户功能1、用户登录、用户注册2、新闻信息:点赞、点踩、收藏、查看3、用户分享:点赞、点踩、收藏、查看、添加......
  • 软件工程结对项目
    结对项目这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标结对完成四则运算生成器项目成员伍绍雄学号3122004753陈鸿航学号3......
  • 结队项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标实现四则运算程序,掌握结对合作完成项目的技巧成员一王佳伟3122004880成员二范圣......
  • 项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹轨迹模拟动画,支持
    若该文为原创文章,转载请注明出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/142454993长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…Qt开发专栏:项目实战......
  • 结对项目
    这个作业属于哪个课程https://edu.cnblogs.com/campus/gdgy/CSGrade22-34这个作业要求在哪里https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230这个作业的目标1.加深对项目开发流程的理解2.学会在团队中沟通与合作3.进一步提升编码能力......
  • 9--苍穹外卖-SpringBoot项目中Redis的介绍及其使用实例 详解
    目录Redis入门Redis简介Redis服务启动与停止服务启动命令Redis数据类型5种常用数据类型介绍各种数据类型的特点Redis常用命令字符串操作命令哈希操作命令列表操作命令集合操作命令有序集合操作命令通用命令在java中操作RedisRedis的Java客户端SpringDataRe......