第一次周期大作业总结
第一次周期大作业总结
--wudibaolongsho
前言:
第一次周期的大作业的训练结束了,实话实说我的oop课程的强度有点不适应,自己也是当了一次卧龙凤雏了,相比与C语言的课程,java语言的课程需要自己更加独立的思考,与我往年学习模式都不相同,此时的我不免有点“巨婴“了。但是婴儿的成长也是最快的,我最这段时间也是成长了不少,也是借这此来总结一下“巨婴:的成长吧。
第一作业总结:
第一作业也是比较简单的,像是最后的晚餐,美味可口。那就让我简单来介绍其中的菜品吧。
开门见山的是一道对fan的类设计,也是非常全面的解释了OOP语言的特点,对初学者来说十分友好。大道至简不过如此。随后的便是类与对象的使用和类的调用以及类的关联。基本的类的使用,面面俱到,可见老师的用心,不过我作为一个初学者,也没辜负老师,在这几道题目中深刻的体会了面向过程与面向对象语言的区别。这几道题轻松,就像前菜,开胃,不免期待下面的题了。但第一次的大作业却让我大为震惊,因为我从来没用处理怎么复杂的数据。才知道java的输入格式与数组的严密,频繁的非零返回把我搞得要炸毛了,这也是我单次写作业最久的一次。不过让我遇到了处理字符串输入的大杀器正则表达式,老师说其深不可测,我会不太相信,直到在B站大学里看到一位老教授讲解的视频有20多个小时,我才知道其的厉害。
运用正确的正则表达式确实可以极大优化输入格式的问题> Pattern pattern = Pattern.compile("#N:\s(\d+)\s#Q:\s([^#]+)\s#A:\s(\S+)");就比如我写这道题的表达式既可以解决不同位子出现空格情况的兼容性也可以运用matcher.group()来获得一行输入的不同信息。解决信息的处理,下面的判题算法就十分简单。当然在处理输入信息时还用了split(""),replace(str,"");等方法的处理。**
点击查看代码
public static void main(String[] args) {
Pattern pattern = Pattern.compile("#N:\\s*(\\d+)\\s*#Q:\\s*([^#]+)\\s#A:\\s*(\\S+)");
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
sc.nextLine(); // Consume the newline character
Test[] test1 = new Test[num];
for (int i = 0; i < num; i++)
{
String sen = sc.nextLine();
Matcher matcher = pattern.matcher(sen);
if (matcher.find()) {
String number = matcher.group(1);
String question = matcher.group(2);
String answer = matcher.group(3);
int a = Integer.parseInt(number);
test1[a-1] = new Test();
test1[a-1].setNum(a);
String question1=question.trim();
String answer1=answer.trim();
test1[a-1].setQuestion(question1);
test1[a-1].setStandardAnswer(answer1);
} else {
}
}
String sen1 = sc.nextLine();
String str = "#A:";
String newStr = sen1.replace(str,"");
String newStr1 = newStr.trim();
String[] newStr3 = newStr1.split(" ");
Question[] question = new Question[num];
for (int i = 0; i < num; i++)
{
question[i] = new Question();
question[i].setAnswer(newStr3[i]);
}
for (int i = 0; i < num; i++)
{
System.out.println(test1[i].getQuestion() + "~" + question[i].getAnswer());
}
for(int i=0;i<num;i++)
{
a(question[i].getAnswer(),test1[i].getStandardAnswer());
if(i!=num-1)
{
System.out.print(" ");
}
}
System.out.println();
}
public static void a(String m1, String m2) {
if (m1.equals(m2)) {
System.out.print("true");
} else {
System.out.print("false");
}
}
}
这就是我写的第一次大作业的主要代码,还请不要笑话...
UML类图:
方法:
可以看出当时的我对面对象的语言理解不深,只是把除Main类的其他类当成一个C语言中结构体来用,导致程序的圈复杂度基本都在Main类中。在后面的学习中我认识到了这一点,看到这代码我就想起当时的自己。
不过我还是想讲一下Pattern pattern = Pattern.compile("#N:\s(\d+)\s#Q:\s([^#]+)\s#A:\s(\S+)");的妙处,在这个正则表达式中在每一个分组的两端都有\s*其作用是只匹配有用的信息(剃除空格)在用replace()与split()来细化信息。这也是当时我能想出最好的方法。
再次总结
第一次作业对我们而言是一次热身也是一次洗礼。
从那以后我开始认识java这门语言的魅力
也学到了许多:
1.类与对象的使用;
2.java数组与C语言的区别
3.java中对输入数据的解析与处理
4.一个java人该有的品质(在敲代码中领悟的)(只可意会不可言传)
第二次作业总总结
第二次作业的难度进一步加大(不是一点点哦),在写的时候也是抓耳挠腮,时间也耗了许多,我上面提的java程序员的品质也是越来越重要。但难度并不是成正态分布的,而是第二次大作业最难,所以我会重点讲第二次大作业的内容。而话说回来,我认为第二次作业对我的帮住是最大的,它进一步加深了我的类,封装,及面向对象的理解,第三次作业的方法也基本来源于第二次作业的练习。
第一题总结:
第一题就比较有趣了,因为它运用了当时我从未接触的方法“接口“与“方法重写”。
利用implements Comparable接口再重写其中的方法compareTo()其后应用 Collections.sort()来对有多个属性的类创造的对象按其中的一项进行排序。 这个方法让我看到了类的优势与特点。是一道有趣的小题。下面是代码
点击查看代码
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
class MobliePhone implements Comparable<MobliePhone> {
private String type;
private int price;
public MobliePhone(String type, int price) {
this.type = type;
this.price = price;
}
@Override
public int compareTo(MobliePhone s) {
return this.price - s.price;
}
public String getType() {
return type;
}
public int getPrice() {
return price;
}
@Override
public String toString() {
return "型号:" + this.type + ",价格:" + this.price;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<MobliePhone> phone = new ArrayList<>();
int i;
for (i = 0; i < 3; i++) {
String type1 = sc.next();
int price1 = sc.nextInt();
phone.add(new MobliePhone(type1, price1));
}
String type2 = sc.next();
int price2 = sc.nextInt();
MobliePhone lastphone = new MobliePhone(type2, price2);
System.out.println("排序前,链表中的数据:");
for (MobliePhone m1 : phone) {
System.out.println(m1.toString());
}
Collections.sort(phone);
System.out.println("排序后,链表中的数据:");
for (MobliePhone m2 : phone) {
System.out.println(m2.toString());
}
int flag = 0;
for (MobliePhone m3 : phone) {
if (m3.getPrice() == lastphone.getPrice()) {
System.out.println(lastphone.getType() + "与链表中的" + m3.getType() + "价格相同");
flag = 1;
}
}
if (flag == 0) {
System.out.println("链表中的对象,没有一个与" + lastphone.getType() + "价格相同的");
}
}
}
第二次大作业总结:
第二次大作业的难度对我来说是剧增的,相比第一次大作业增加了试卷类以及对试卷分数的判断和不确定的题目个数与试卷张数。
相比而言第一次大作业的题目无疑是简单,呆板的。但也无疑是不符合实际的。
再解决不定的试题时,我想到了java语言中的列表,它即可以存储多种信息也可以动态的增长(拥有这些功能的还LinkedList,HashMap等)我在处理分数不足时也单独写了一个方法来处理,当然还有乱序输入,答案缺失等情况我也单独处理了。经过第一次大作业的洗礼我对类的运用越来越好。但在对试卷类的信息处理中却犯了难,因为类与类之间并不是独立的,我认为在此题中的试卷包括了问题。最后我想到了用在试卷类中创立一个与问题同名的ArrayList数组在用set方法就将问题存入了试卷中。但这次的代码的风格我认为不尽人意。因为Main类太过臃肿,不像是面向对象的程序风格。在上一次的题目基础上却没有改变。
但对正则表达式的运用更加熟练,HashMap的第一次运用。但是无效试卷的判定在类属性的设计的失误下变得无法进行。这也让我体会到了编写程序前的设计的重要性,毕竟java语言强调的本就是一个合理的设计。
下面是代码:
点击查看代码
import java.util.*;
import java.util.stream.Collectors;
class Question {
String content;
String answer;
public Question(String content, String answer) {
this.content = content;
this.answer = answer;
}
}
class TestPaper {
Map<Integer, Integer> questions = new LinkedHashMap<>(); // 题目编号-分值
int totalScore = 0;
public void addQuestion(int questionNumber, int score) {
questions.put(questionNumber, score);
totalScore += score;
}
}
class Submission {
int testPaperNumber;
List<String> answers;
public Submission(int testPaperNumber, List<String> answers) {
this.testPaperNumber = testPaperNumber;
this.answers = answers;
}
}
public class Main {
private static final Map<Integer, Question> questionMap = new HashMap<>();
private static final Map<Integer, TestPaper> testPaperMap = new HashMap<>();
private static final List<Submission> submissions = new ArrayList<>();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if ("end".equals(line)) {
break;
}
processInput(line);
}
judgeAndPrintResults();
}
private static void processInput(String line) {
if (line.startsWith("#N:")) {
processQuestion(line);
} else if (line.startsWith("#T:")) {
processTestPaper(line);
} else if (line.startsWith("#S:")) {
processSubmission(line);
}
}
private static void processQuestion(String line) {
String[] parts = line.split(" ");
int number = Integer.parseInt(parts[0].substring(3));
String content = parts[1].substring(3);
String answer = parts[2].substring(3);
questionMap.put(number, new Question(content, answer));
}
private static void processTestPaper(String line) {
String[] parts = line.split(" ");
int testPaperNumber = Integer.parseInt(parts[0].substring(3));
TestPaper testPaper = new TestPaper();
for (int i = 1; i < parts.length; i++) {
String[] questionInfo = parts[i].split("-");
int questionNumber = Integer.parseInt(questionInfo[0]);
int score = Integer.parseInt(questionInfo[1]);
testPaper.addQuestion(questionNumber, score);
}
testPaperMap.put(testPaperNumber, testPaper);
}
private static void processSubmission(String line) {
String[] parts = line.split(" ");
int testPaperNumber = Integer.parseInt(parts[0].substring(3));
List<String> answers = new ArrayList<>();
for (int i = 1; i < parts.length; i++) {
answers.add(parts[i].substring(3));
}
submissions.add(new Submission(testPaperNumber, answers));
}
private static void judgeAndPrintResults() {
checkTestPapersTotalScore(); // 在评分开始前检查每份试卷的总分
for (Submission submission : submissions) {
TestPaper testPaper = testPaperMap.get(submission.testPaperNumber);
if (testPaper == null) {
System.out.println("The test paper number does not exist");
continue;
}
int totalScore = 0;
List<Integer> scores = new ArrayList<>();
int index = 0;
for (Map.Entry<Integer, Integer> entry : testPaper.questions.entrySet()) {
Question question = questionMap.get(entry.getKey());
// 修正索引对应的答案
String submittedAnswer = index < submission.answers.size() ? submission.answers.get(index) : "";
boolean isCorrect = submittedAnswer.equals(question.answer);
System.out.println(question.content + "~" + submittedAnswer + "~" + isCorrect);
int score = isCorrect ? entry.getValue() : 0;
scores.add(score);
totalScore += score;
index++;
}
System.out.println(scores.stream().map(Object::toString).collect(Collectors.joining(" ")) + "~" + totalScore);
}
}
private static void checkTestPapersTotalScore() {
// 检查每份试卷的总分是否为100分
for (Map.Entry<Integer, TestPaper> entry : testPaperMap.entrySet()) {
TestPaper testPaper = entry.getValue();
if (testPaper.totalScore != 100) {
System.out.println("alert: full score of test paper" + entry.getKey() + " is not 100 points");
}
}
}
}
UML类图:
方法:
这次大作业类与类之间的关系更加紧密,用各种数据结构来串联各个类中的属性。但每种不足的是数据的操作基本在Main进行所以在圈复杂度中Main类的复杂度最高的也几乎集中在那。这对程序的可扩展性是非常不友好的。所以,下次我一定会改变的。
这次设计存在偏差在下一次的作业中也会解决
再次总结
第二次作业的融合性与综合型更强,对我的编程能力要求更高,在编写过程中的问题主要是不定的数据数量,在解析数据时选择了split(),line.startsWith(""),replaceAll()的方法,尝试用另一种分割的方式写题。其中:
1.了解了接口这一概念,Comparable<>以及重写方法的排序;
2.意识到了类的设计对代码的扩展性的影响。
3.学习了LinkedList,HashMap,ArrayList等数据结构的运用。
第三次作业总结
一周期的作业的难度都是慢慢的提升的,这次难度明显比第二次要难,我明显感到了吃力,这也是写过最张时间的编程作业了。
虽然只有三道题,但所含的知识与新东西是之前的完全无法比较的。简单来说就是痛苦并快乐着。
在第二题中出现了对时间的格式处理是之前没有遇到过的,它涉及了java内置处理时间的方法import java.time.LocalDate;
import java.time.Period;可以用来直接判断YY-MM-dd的时间格式,极大的简化了代码与操作的复杂度,这让我想到了java语言的强大活力,其中的格式错误的判断以及多种错误的判断与前面的题目一脉相承但我在这里发现了一个前面本应该发现的问题:
sc.nextInt();接受信息时会默认多出一个空格,如果在用输出,sc.nextLine()接受下一行信息时sc.nextLine()会接受那个空格使得程序异常非零返回,最常见的方法是用sc.next()来接受空格,以保证程序的正常接受。
第三次大作业总结:
这次的大作业相比上次的增加了学生信息,题目引用错误,题目的删除,无效试卷,无效学号,信息可打乱顺序输入:序号不是按大小排列,各类信息交错输入。各种情况的处理要求,几乎是一个完整的简易的判分小程序。在这里我发现了正则表达式的普适性。于是我又用回了正则表达式来完成对输入信息的解析,这次我优化了代码的设计,专门编写了一个tool类来应对各种信息的处理。而main方法则是专门调用其他方法来完成题目要求,但在这里由于答卷与问卷的对应关系,问题的删除,答案的判定间的关系没有清楚,使得调用时混 乱。在用加强for循环时未考虑ArraryList动态数组的长度问题,导致程序异常抛出,还有的问题是正则表达式的运用不大行,在写代码时经历了许多次调试才确定了最终的正则表达式: "#N:\s(\d+)\s#Q:\s([^#]+)\s#A:\s(\S+)",
"#T:\s(\d+)\s((\d+)-(\S+))\s",
"#X:\s(\d+)\s((\S+)-(\d+))\s(\S+)",
"#S:(\d+)\s(\d+)\s(#A:(\d+)-(\S+))\s",
"#D:\s((\S)-(\d+))+"
其中因为输入有格式错误的情况才要用第二次正则表达式来统一收集信息,
另外也用上了split(),replaceAll()等方法,算是对输入信息的解析的综合运用的练习。
但是就是这些看似复杂的数据其实也是有序的联系的:问卷中蕴含了问题及答案,答卷蕴含了答题卡吗,学号,而学号有对应了学生的姓名,而我在做题时就是利用了这以联系而创造自己的类。
下面是部分代码:
筛选有效格式的信息的代码
点击查看代码
public static String inputN(String sen,ArrayList<Integer>count) {
String []patterns=
{
"#N:\\s*(\\d+)\\s*#Q:\\s*([^#]+)\\s*#A:\\s*(\\S+)",
"#T:\\s*(\\d+)\\s*((\\d+)-(\\S+))*\\s*",
"#X:\\s*(\\d+)\\s*((\\S+)-(\\d+))*\\s*(\\S+)",
"#S:(\\d+)\\s*(\\d+)\\s*(#A:(\\d+)-(\\S+))*\\s*",
"#D:\\s*((\\S)-(\\d+))+"
};
String patterns1= "#N:(.*$)";
Pattern pattern1=Pattern.compile(patterns1);
Matcher matcher1=pattern1.matcher(sen);
{
if(matcher1.find())
{
count.add(0,0);
}
}
for(String patternStr:patterns)
{
Pattern pattern =Pattern.compile(patternStr);
Matcher matcher=pattern.matcher(sen);
if(matcher.find())
{
return sen;
}
}
点击查看代码
public static void inputdelete(String sen,ArrayList<delete>deletes)
{
Pattern pattern=Pattern.compile("\\s*N-(\\d+)");
Matcher matcher= pattern.matcher(sen);
while(matcher.find())
{
deletes.add( new delete(Integer.parseInt(matcher.group(1))));
}
}
public static test getrealtest(int num,ArrayList<test>tests)
{
for(test test:tests)
{
if(test.getTestnum()==num)
{
return test;
}
}
return null ;
}
public static void judgment (ArrayList<Antest> antests,ArrayList<test> tests,ArrayList<delete>deletes,ArrayList<Student>students,ArrayList<Integer>count)
{
for(Antest antest:antests)
{
if(getrealtest(antest.getAtestnum(),tests)==null)
{
System.out.println("The test paper number does not exist");
}
else
{
ArrayList<Question>questions= realdetele(getrealtest(antest.getAtestnum(),tests).getTquesion(),deletes);
if(questions.isEmpty())
{
System.out.println("non-existent question~0");
}
if(antest.getAnswertests().isEmpty())
{
System.out.println("answer is null");
}
if(antest.getAnswertests().size()!=count.size()) {
int a=0;
for (answertest answertest : antest.getAnswertests()) {
for (Question question:questions)
{
if(answertest.getAquestionnum()==question.getQuestionnum())
{
a++;
}
}
if(a==0)
{
System.out.println("answer is null");
}
}
}
realjudgment(questions,antest.getAnswertests(),antest.getAnstudentID(),students,count,deletes);
}
}
}
public static void realjudgment (ArrayList<Question>questions,ArrayList<answertest>answertests,int StudentID,ArrayList<Student>students,ArrayList<Integer>count,ArrayList<delete>deletes)
{
if(!questions.isEmpty()) {
for (Question question : questions) {
for (answertest answertest : answertests) {
if (question.getQuestionnum() == answertest.getAquestionnum()) {
if (question.getStandardanswer().equals(answertest.getAnswer())) {
System.out.println(question.getQuestion() + "~" + answertest.getAnswer() + "~ture");
count.set(question.getQuestionnum()-1, question.getSorce());
} else {
System.out.println(question.getQuestion() + "~" + answertest.getAnswer() + "~false");
}
}
}
}
}
String studenta = null;
for(Student student:students)
{
if(StudentID==student.getStudentID())
{
studenta=student.getName();
}
}
if(answertests.size()==count.size()&&!answertests.isEmpty())
{
if(!deletes.isEmpty())
{
for(delete delete:deletes)
{
System.out.println("the question "+delete.getDeletenum()+" invalid~0");
}
}
}
int m=0;
if(studenta==null)
{
System.out.print(StudentID+" not found");
}
else
{
System.out.print(StudentID+" "+studenta+":");
for (Integer integer : count) {
System.out.print(" " + integer);
m = m + integer;
}
System.out.println("~"+m);
}
}
public static ArrayList<Question> realdetele(ArrayList<Question>questions,ArrayList<delete>deletes)
{
if(!deletes.isEmpty())
{
for(Question question:questions)
{
for(delete delete:deletes)
{
if(question.getQuestionnum()==delete.getDeletenum())
{
questions.remove(question);
}
}
if(questions.isEmpty())
{
break;
}
}
}
return questions;
}
}
UML类图:
方法:
这次的UML类图更加复杂但由于tool类中的方法是程序中的主要处理的地方所以类与类之间的联系主要始于tool但是圈复杂的tool有几个方法的太复杂了,应当进一步改进。
再次总结
1.综合性的运用处理信息的方法;
2.理清条件之间的关系
心得体会
本轮作业,我个人进步最大的地方是学习了几个设计模式来辅助自己设计,这让我代码整体结构比较好,思路清晰,逻辑严谨。
对正则表达式的理解加深。
对ArraysLink,HashMap等运用更加娴熟。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~