写在前面
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 练习文件中包含无关符号、要用正则表达式处理;
2. 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格式);
屏幕输出读入的文件、截屏显示
2. 从exercise中计算每一个算式的结果,要求复用第三章的算式类
屏幕输出每一个算式的结果、截屏显示
3. 批改练习:检查结果是否正确,记录统计结果,屏幕输出或存入CSV格式的文件,给出证据
三、构造任务5:生成100以内加法/减法的算式基。
新加一个类BinaryOperationBase,产生算式基、存储到文件,从算式基随机选择算式组成练习,
考核点及验证:
- 分别生产正确的加法算式基、减法算式基;验证:2个截屏(数值范围可以是20)。
- 要求复用第三章的类,否则本题不得分。
加法算式基、减法算式基分别存入CSV格式的文件;
验证:CSV格式的2个文件。
从CSV格式的读入算式基、并分别组成一定数量练习;
验证:35道加法算式、48道减法算式,截屏。
3. 把加法算式基和减法算式基合并在一个数据结构,存入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 {@Overrideprotected int operate(int operand1, int operand2) {return operand1 + operand2;}@Overrideprotected int generateOperand2() {Random rand = new Random();return rand.nextInt(101 - operand1); // 第二个操作数不能超过100减去第一个操作数}@Overrideprotected String getOperator() {return " + ";}
}// 减法类
class Subtraction extends BinaryOperation {@Overrideprotected int operate(int operand1, int operand2) {return operand1 - operand2;}@Overrideprotected int generateOperand2() {Random rand = new Random();return rand.nextInt(operand1 + 1); // 第二个操作数不能超过第一个操作数}@Overrideprotected 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(); // 消耗无效输入}}}
}