(2022级)成都工业学院软件构造实验三:面向数据的软件构造

写在前面

1、基于2022级软件工程实验指导书

2、代码仅提供参考

3、如果代码不满足你的要求,请寻求其他的途径

运行环境

window11家庭版

IntelliJ IDEA 2023.2.2

jdk17.0.6

实验要求

任务:

‍一、构造任务4:批量产生习题并用文件存储。

二、构造任务6:批改练习并存储

三、构造任务5:生成100以内加法/减法的算式

以下为详细说明:

一、构造任务4:批量产生习题并用文件存储。

构造任务4.2.1:以第3章面向对象的版本为基础,完成构造任务4,建议新加一个类ExerciseFiles、增加方法,批量产生并存储习题(CSV文件格式)。

要求:

截屏和.txt文件,内容是CSV格式的练习题(20~50题),加、减、混合题各一套;

构造任务4.2.2:复用BinaryOperation, Exercise, ExerciseSheet,建议新加一个类ExerciseFiles、在其中增加方法,从CSV格式的文件中读入习题。

下面是4个CSV加法、减法练习文件,有的文件格式无任何多余符号、有的文件中有无关符号

文件1:exercise_add_50_1

文件2:exercise_add_70_2

文件3:exercise_sub_50_1

文件4:exercise_sub_60_2

要求:读入教师指定的上述4套CSV格式的练习文件并相应处理,按照3~5列:

2.1 屏幕显示读到的文件内容。

2.2 在上述基础上添加运算结果,例如33+22=55,屏幕显示,要求复用第三章的算式类;

技术考核点:

  1. 防御性编程

1.1 异常的使用和处理,比如不存在的文件、数值超出范围或者不满足约束条件;

1.2 练习文件中包含无关符号、要用正则表达式处理;

  1. junit的使用

2.1 测试异常,成功和失败各一次

2.2 参数化测试

2.3 测试套件

二、构造任务6:批改练习并存储。

练习结果以CSV格式写入一个练习文件;程序读入该文件,与相应习题中的每个算式答案比较;统计批改,屏幕显示,同时存入CSV格式的批改文件。练习结果文件的参考格式:

文件名:answers_add_50_19

76,65,61, 58,78,42,45,-1, 56, 63,...

要求练习答案的顺序和数目与对应的习题一致。对于没有做出的算式,录入到CSV文件时,用1表示。批改、统计练习后,存储文件的参考格式:

练习题:文件名

算式总数:50

正确:45

错误:5

得分:90

dd_50_3 exercise_add_50_3

Test2: answers_mix_70_3 exercise_ mix _70_3

功能考核点:

  1. 读入CSV格式的练习exercise文件,简单防御性处理:两者数量不一致,文件不存在,打不开文件(或者不是CSV格式);

屏幕输出读入的文件、截屏显示

  1. 从exercise中计算每一个算式的结果,要求复用第三章的算式类

屏幕输出每一个算式的结果、截屏显示

  1. 批改练习:检查结果是否正确,记录统计结果,屏幕输出或存入CSV格式的文件,给出证据

三、构造任务5:生成100以内加法/减法的算式基。

新加一个类BinaryOperationBase,产生算式基、存储到文件,从算式基随机选择算式组成练习,

考核点及验证:

  1. 分别生产正确的加法算式基、减法算式基;验证:2个截屏(数值范围可以是20)。
  2. 要求复用第三章的类,否则本题不得分。

加法算式基、减法算式基分别存入CSV格式的文件;

验证:CSV格式的2个文件。​

从CSV格式的读入算式基、并分别组成一定数量练习;

验证:35道加法算式、48道减法算式,截屏。

  1. 把加法算式基和减法算式基合并在一个数据结构,存入CSV格式的文件,并且从中组成一定数量练习;验证:一个截屏和CSV格式的文件,50题混合算式的练习,截屏。

不完成3个任务、要求复用第三章的类,否则本题不得分。

源代码

BinaryOperation.java

import java.util.*;

abstract class BinaryOperation {
    protected int operand1;
    protected int operand2;
    protected int result;

    public BinaryOperation() {
        // 生成操作数和计算结果
        Random rand = new Random();
        operand1 = rand.nextInt(101); // 生成0到100的随机数
        operand2 = generateOperand2();
        result = operate(operand1, operand2);
    }

    protected abstract int operate(int operand1, int operand2);

    // 生成第二个操作数
    protected abstract int generateOperand2();

    public String getExpression() {
        return operand1 + "\t" + getOperator() + "\t" + operand2 + "\t" + " = ";
    }

    protected abstract String getOperator();

    public int getResult() {
        return result;
    }
}

// 加法类
class Addition extends BinaryOperation {
    @Override
    protected int operate(int operand1, int operand2) {
        return operand1 + operand2;
    }

    @Override
    protected int generateOperand2() {
        Random rand = new Random();
        return rand.nextInt(101 - operand1); // 第二个操作数不能超过100减去第一个操作数
    }

    @Override
    protected String getOperator() {
        return " + ";
    }
}

// 减法类
class Subtraction extends BinaryOperation {
    @Override
    protected int operate(int operand1, int operand2) {
        return operand1 - operand2;
    }

    @Override
    protected int generateOperand2() {
        Random rand = new Random();
        return rand.nextInt(operand1 + 1); // 第二个操作数不能超过第一个操作数
    }

    @Override
    protected String getOperator() {
        return " - ";
    }
}

Exercise.java

//构造要求2:实现Exercise
class Exercise {
    private BinaryOperation operation;

    public Exercise(BinaryOperation operation) {
        this.operation = operation;
    }

    public String getExpression() {
        return operation.getExpression();
    }

    public int getResult() {
        return operation.getResult();
    }
}

ExerciseSheet.java

import java.util.HashSet;
import java.util.Set;

//构造要求2:实现ExerciseSheet
class ExerciseSheet {
    private Exercise[] exercises;

    public ExerciseSheet(int numExercises, Class<? extends BinaryOperation> operationType) {
        exercises = new Exercise[numExercises];
        try {
            Set<String> expressions = new HashSet<>(); // 使用集合来确保题目不重复
            for (int i = 0; i < numExercises; i++) {
                BinaryOperation operation = operationType.newInstance();
                String expression = operation.getExpression();
                // 如果集合中已经有了相同的表达式,则重新生成直到不重复为止
                while (expressions.contains(expression)) {
                    operation = operationType.newInstance();
                    expression = operation.getExpression();
                }
                expressions.add(expression);
                exercises[i] = new Exercise(operation);
            }
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public Exercise[] getExercises() {
        return exercises;
    }
}

ExerciseFIles.java

import java.io.*;
import java.util.Random;
//构造任务1:批量产生习题并用文件存储
public class ExerciseFiles {
    private static final int NUM_EXERCISES = 50;

    // 生成加法练习题并写入CSV文件
    public static void generateAdditionCSV(String filename) {
        generateCSV(filename, Addition.class);
    }

    // 生成减法练习题并写入CSV文件
    public static void generateSubtractionCSV(String filename) {
        generateCSV(filename, Subtraction.class);
    }

    // 生成加减混合练习题并写入CSV文件
    public static void generateMixedOperationCSV(String filename) {
        try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
            Random rand = new Random();
            for (int i = 0; i < NUM_EXERCISES; i++) {
                Class<? extends BinaryOperation> operationType = rand.nextBoolean() ? Addition.class : Subtraction.class;
                ExerciseSheet sheet = new ExerciseSheet(1, operationType);
                Exercise[] exercises = sheet.getExercises();
                writer.println(exercises[0].getExpression());
            }
            System.out.println("CSV文件已生成:" + filename);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    // 生成CSV文件
    private static void generateCSV(String filename, Class<? extends BinaryOperation> operationType) {
        try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
            ExerciseSheet sheet = new ExerciseSheet(NUM_EXERCISES, operationType);
            Exercise[] exercises = sheet.getExercises();
            for (Exercise exercise : exercises) {
                writer.println(exercise.getExpression());
            }
            System.out.println("CSV文件已生成:" + filename);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 读取并计算CSV文件中的算式
    public static void calculateAndPrintCSV(String filename) {
        try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
            String line;
            int count = 0; // 记录已输出的算式数量
            while ((line = reader.readLine()) != null) {
                // 对每一行数据进行预处理,去除可能存在的额外空格
                line = line.trim().replaceAll("\\s+", "\t");
                String[] parts = line.split("\t");
                int operand1 = Integer.parseInt(parts[0]);
                int operand2 = Integer.parseInt(parts[2]);
                String operator = parts[1];
                int result;

                // 判断运算符并进行相应的计算
                switch (operator) {
                    case "+":
                        result = operand1 + operand2;
                        break;
                    case "-":
                        result = operand1 - operand2;
                        break;
                    default:
                        System.out.println("警告:不支持的运算符:" + operator);
                        continue; // 跳过本次循环,继续处理下一个算式
                }

                // 输出算式及其结果
                System.out.printf("%-10s", line + result + "\t\t");
                count++;
                if (count % 5 == 0) // 每行五个算式
                    System.out.println();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void generateAll() {
        // 生成加法练习题CSV文件
        ExerciseFiles.generateAdditionCSV("addition_exercises.csv");

        // 生成减法练习题CSV文件
        ExerciseFiles.generateSubtractionCSV("subtraction_exercises.csv");

        // 生成加减混合练习题CSV文件
        ExerciseFiles.generateMixedOperationCSV("mixed_operation_exercises.csv");
    }

    public static void calculateAndPrintAll() {
        // 读取并计算加法练习题CSV文件
        System.out.println("读取并计算加法练习题CSV文件:");
        ExerciseFiles.calculateAndPrintCSV("addition_exercises.csv");

        // 读取并计算减法练习题CSV文件
        System.out.println("\n读取并计算减法练习题CSV文件:");
        ExerciseFiles.calculateAndPrintCSV("subtraction_exercises.csv");

        // 读取并计算加减混合练习题CSV文件
        System.out.println("\n读取并计算加减混合练习题CSV文件:");
        ExerciseFiles.calculateAndPrintCSV("mixed_operation_exercises.csv");
    }

}

ExerciseCorrection.java

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//构造任务2:批改练习并存储
public class ExerciseCorrection {
    // 从文件中读取习题
    private static List<String> readExercisesFromFile(String filename) throws IOException {
        List<String> exerciseList = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
            String line;
            while ((line = reader.readLine()) != null) {
                exerciseList.add(line);
            }
        }
        return exerciseList;
    }

    // 获取用户输入的答案
    private static List<Integer> getUserAnswers(List<String> exerciseList) {
        List<Integer> userAnswers = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        for (int i = 0; i < exerciseList.size(); i++) {
            String exercise = exerciseList.get(i);
            System.out.println("第 " + (i + 1) + " 题:" + exercise);
            String userInput = scanner.nextLine();
            try {
                int answer = Integer.parseInt(userInput);
                userAnswers.add(answer);
            } catch (NumberFormatException e) {
                userAnswers.add(-1);
            }
        }
        return userAnswers;
    }

    // 写入用户答案到文件
    private static void writeAnswersToFile(List<Integer> userAnswers, String filename) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
            for (Integer answer : userAnswers) {
                writer.write(answer + ",");
            }
            writer.newLine();
        }
    }

    // 批改并统计结果
    private static void correctAndReport(List<String> exerciseList, List<Integer> answersList, List<Integer> userAnswersList) {
        int totalExercises = exerciseList.size();
        if (totalExercises == 0 || answersList.size() == 0 || userAnswersList.size() == 0) {
            System.out.println("习题文件或答案文件为空,请检查文件内容。");
            return;
        }

        int correctCount = 0;
        for (int i = 0; i < totalExercises; i++) {
            int correctAnswer = evaluateExpression(exerciseList.get(i));
            int userAnswer = userAnswersList.get(i);
            if (userAnswer == correctAnswer) {
                correctCount++;
            }
        }

        // 统计结果
        int incorrectCount = totalExercises - correctCount;
        int score = (int) ((double) correctCount / totalExercises * 100);

        System.out.println("算式批改结果已存入文件");
        // 写入批改结果到文件
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("correction_results.csv"))) {
            writer.write("练习题:" + "user_answers.csv");
            writer.newLine();
            writer.write("算式总数:" + totalExercises);
            writer.newLine();
            writer.write("正确:" + correctCount);
            writer.newLine();
            writer.write("错误:" + incorrectCount);
            writer.newLine();
            writer.write("得分:" + score);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 计算表达式的值
    private static int evaluateExpression(String expression) {
        // 使用正则表达式匹配数字和运算符,忽略不可见的空白字符
        Pattern pattern = Pattern.compile("\\s*(\\d+)\\s*([-+])\\s*(\\d+)\\s*=\\s*");
        Matcher matcher = pattern.matcher(expression);
        if (matcher.matches()) {
            int operand1 = Integer.parseInt(matcher.group(1));
            String operator = matcher.group(2);
            int operand2 = Integer.parseInt(matcher.group(3));

            if (operator.equals("+")) {
                return operand1 + operand2;
            } else if (operator.equals("-")) {
                return operand1 - operand2;
            }
        }
        return 0;
    }

    public static void menu() {
        Scanner scanner = new Scanner(System.in);
        // 用户选择习题文件类型
        System.out.println("请选择习题文件类型:");
        System.out.println("1. 加法习题");
        System.out.println("2. 减法习题");
        System.out.println("3. 混合运算习题");
        System.out.print("请选择:");
        int choice = scanner.nextInt();
        String exerciseFilename = "";
        switch (choice) {
            case 1:
                exerciseFilename = "addition_exercises.csv";
                break;
            case 2:
                exerciseFilename = "subtraction_exercises.csv";
                break;
            case 3:
                exerciseFilename = "mixed_operation_exercises.csv";
                break;
            default:
                System.out.println("无效选择。");
                System.exit(-1);
        }
        String answersFilename = "user_answers.csv";
        try {
            List<String> exerciseList = readExercisesFromFile(exerciseFilename);

            // 获取用户输入答案
            List<Integer> userAnswersList = getUserAnswers(exerciseList);

            // 写入用户答案到文件
            writeAnswersToFile(userAnswersList, answersFilename);

            // 从文件中读取正确答案
            List<Integer> answersList = new ArrayList<>();
            try (BufferedReader reader = new BufferedReader(new FileReader(answersFilename))) {
                String line = reader.readLine();
                if (line != null) {
                    String[] answersArray = line.split(",");
                    for (String answer : answersArray) {
                        answersList.add(Integer.parseInt(answer));
                    }
                }
            }

            // 批改并统计结果
            correctAndReport(exerciseList, answersList, userAnswersList);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BinaryOperationBase.java

import java.io.*;
import java.util.*;
//构造任务3:生成100以内加法/减法的算式
public class BinaryOperationBase {
    private List<String> additionBase;
    private List<String> subtractionBase;

    public BinaryOperationBase() {
        this.additionBase = new ArrayList<>();
        this.subtractionBase = new ArrayList<>();
    }

    // 生成加法算式基
    public void generateAdditionBase(int numOperations) {
        for (int i = 0; i < numOperations; i++) {
            BinaryOperation addition = new Addition();
            additionBase.add(addition.getExpression() + addition.getResult());
        }
    }

    // 生成减法算式基
    public void generateSubtractionBase(int numOperations) {
        for (int i = 0; i < numOperations; i++) {
            BinaryOperation subtraction = new Subtraction();
            subtractionBase.add(subtraction.getExpression() + subtraction.getResult());
        }
    }

    // 生成混合算式基
    public void generateMixedOperationBase(int numOperations) {
        generateAdditionBase(numOperations / 2);
        generateSubtractionBase(numOperations / 2);
    }

    // 将加法算式基存储到文件
    public void saveAdditionBaseToFile(String filename) {
        saveBaseToFile(additionBase, filename);
    }

    // 将减法算式基存储到文件
    public void saveSubtractionBaseToFile(String filename) {
        saveBaseToFile(subtractionBase, filename);
    }

    // 将算式基存储到文件
    private void saveBaseToFile(List<String> base, String filename) {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
            for (String operation : base) {
                writer.write(operation);
                writer.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 从加法算式基中随机选择指定数量的算式
    public List<String> getRandomAdditionOperations(int numOperations) {
        return getRandomOperations(additionBase, numOperations);
    }

    // 从减法算式基中随机选择指定数量的算式
    public List<String> getRandomSubtractionOperations(int numOperations) {
        return getRandomOperations(subtractionBase, numOperations);
    }

    // 从混合算式基中随机选择指定数量的算式
    public List<String> getRandomMixedOperationOperations(int numOperations) {
        List<String> mixedOperations = new ArrayList<>();
        mixedOperations.addAll(additionBase);
        mixedOperations.addAll(subtractionBase);
        Collections.shuffle(mixedOperations);
        return mixedOperations.subList(0, numOperations);
    }

    // 从算式基中随机选择指定数量的算式
    private List<String> getRandomOperations(List<String> base, int numOperations) {
        List<String> randomOperations = new ArrayList<>();
        Random rand = new Random();
        for (int i = 0; i < numOperations; i++) {
            int index = rand.nextInt(base.size());
            randomOperations.add(base.get(index));
        }
        return randomOperations;
    }

    public static void menu() {
        BinaryOperationBase base = new BinaryOperationBase();

        // 生成加法算式基并存储到文件
        base.generateAdditionBase(100);
        System.out.println("加法算式基已生成");
        base.saveAdditionBaseToFile("addition_base.csv");
        System.out.println("加法算式基已存入文件");
        // 生成减法算式基并存储到文件
        base.generateSubtractionBase(100);
        System.out.println("减法算式基已生成");
        base.saveSubtractionBaseToFile("subtraction_base.csv");
        System.out.println("减法算式基已存入文件");

        // 生成混合算式基并存储到文件
        base.generateMixedOperationBase(100);
        System.out.println("混合算式基已生成");
        base.saveSubtractionBaseToFile("mixed_operation_base.csv");
        System.out.println("混合算式基已存入文件");

        // 从随机抽取的算式基中随机选择50个算式
        List<String> randomAdditionOperations = base.getRandomAdditionOperations(50);
        List<String> randomSubtractionOperations = base.getRandomSubtractionOperations(50);
        List<String> randomMixedOperations = base.getRandomMixedOperationOperations(50);

        // 将随机抽取的算式存入对应的CSV文件中
        base.saveBaseToFile(randomAdditionOperations, "addition_exercises.csv");
        base.saveBaseToFile(randomSubtractionOperations, "subtraction_exercises.csv");
        base.saveBaseToFile(randomMixedOperations, "mixed_operation_exercises.csv");
    }
}

Main.java

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int choice = -1;
        while (choice != 0) {
            System.out.println("请输入你的选择:");
            System.out.println("1、批量产生习题并用文件存储");
            System.out.println("2、读入习题并添加答案");
            System.out.println("3、批改练习并储存");
            System.out.println("4、生成算式基并用文件储存");
            System.out.println("0、退出");
            System.out.printf("你的选择是:");
            if (scanner.hasNextInt()) {
                choice = scanner.nextInt();
                switch (choice) {
                    case 1:
                        ExerciseFiles exerciseFiles = new ExerciseFiles();
                        exerciseFiles.generateAll();
                        break;
                    case 2:
                        ExerciseFiles exerciseFiles1 = new ExerciseFiles();
                        exerciseFiles1.calculateAndPrintAll();
                        break;
                    case 3:
                        ExerciseCorrection exerciseCorrection = new ExerciseCorrection();
                        exerciseCorrection.menu();
                        break;
                    case 4:
                        BinaryOperationBase binaryOperationBase = new BinaryOperationBase();
                        binaryOperationBase.menu();
                        break;
                    case 0:
                        System.out.println("程序已退出。");
                        break;
                    default:
                        System.out.println("无效的选项,请重新输入。");
                        break;
                }
            } else {
                System.out.println("输入无效,请重新输入数字选项。");
                scanner.next(); // 消耗无效输入
            }
        }
    }
}

运行结果

相关推荐
sleepybear11133 天前
JetBrains IDEA 2024 在使用 lombok 后构建失败/编译失败解决方案
java·ide·intellij-idea·软件构建
XCNMJZ18 天前
澎峰科技助力中国移动 重磅发布智算“芯合”算力原生基础软件栈2.0
java·人工智能·python·科技·aigc·软件工程·软件构建
人才程序员23 天前
详解 Qt QtPDF之QPdfPageNavigator 页面跳转
c语言·开发语言·c++·qt·pdf·软件构建·用户界面
豆豆1 个月前
如何选择国产化CMS来建设政务网站?
服务器·开发语言·前端·php·软件构建·政务
豆豆1 个月前
如何选择企业网站模版来搭建网站?
服务器·开发语言·前端·php·软件构建
李启柱2 个月前
项目开发流程规范文档
运维·软件构建·个人开发·设计规范
帅次2 个月前
基于云平台的智能家居管理系统设计与通信协议分析
设计模式·重构·软件工程·软件构建·需求分析·代码规范·设计规范
帅次2 个月前
基于边缘计算的智能门禁系统架构设计分析
软件工程·团队开发·软件构建·需求分析·规格说明书·代码复审·极限编程
豆豆2 个月前
如何制作一个自己的网站?
服务器·开发语言·前端·php·软件构建
豆豆2 个月前
如何选择适合自己搭建网站的CMS?
服务器·开发语言·前端·php·软件构建