JAVA第一次博客

目录:
一.前言
二.设计与分析
三.踩坑心得
四.改进建议
五.总结

一.前言:
一开始接触的就是C语言,而后是Java。两者有相通的也有不同的,C语言面向过程,而JAVA则是面向对象。感觉JAVA的面向对象和struct有点像。
第一次作业偏简单,重点在与正则表达式;第二次作业输出的形式更复杂了;第三次作业增加了一个类并且测试点也更多了,难度逐步递增,代码的长度也逐步递增;
通过前三次的作业,对JAVA也有了表层的理解。而这三次大作业我觉得最难的就是正则表达式的使用,怎么在一串信息中提取出自己想要的,其次是怎么设计好类,类的属性方法和类和类的关系。最后也就是在设计,书写程序是要想到的特殊情况即bug,感觉是要把客户当成小孩,哪怕他们乱输一通,也要给出相应的提示即解决方法

二.设计与分析:
(因第三次大作业是在第一二次的基础上增加难度,所以我这里就设计第三次大作业的类)
题目要求:

可知题目类中包括属性:题号和题目内容和标准答案,行为:判断对错;
class Topic //题目
{
int topicnum;//题号
String topiccontent;//题目内容
String standardanswer;//题目标准答案

public Topic(int topicnum,String topiccontent,String standardanswer)
{
    this.topicnum=topicnum;
    this.topiccontent=topiccontent;
    this.standardanswer=standardanswer;
}

int ifright(String answer)//判断正误
{
    if(this.standardanswer.equals(answer))
        return 1;
    else
        return 0;
}

}

试卷中有多个题目以及各个题目的分值(注意:不要混淆顺序号与题号,题号不一定完整且连续)所以我设计了两个属性,一个是题号集合,一个是分值集合,两两对应,属性还包括试卷号,题目集合,试卷的满分和试卷上删除的题号(题目中有删除题号的寻求),行为则是判断正误,匹配题目和计算试卷满分。(这里在设计题目类和试卷类有个不妥当的地方,在后面的改进建议中会提到)
class Paper //试卷
{
int papernum;//试卷号
int papertopicsum;//试卷中题目的数目
Topic[] topic=new Topic[100];//试卷上的题目
int[] questionnum=new int[100];//记录的题号
int[] questionscore=new int[100];//记录的题目分数
int papertopicsumscore=0;//试卷的满分
int deletetopic;//试卷上删除的题号

public Paper(int papernum,int papersum)
{
	this.papertopicsum=papersum;
    this.papernum=papernum;
}

void matchquestion(int i,int questionnum,int quetionscore)
{
    this.questionnum[i]=questionnum;
    this.questionscore[i]=quetionscore;
}

int ifcorrect(int num,String answer)//num表示题号//判断num题是否正确
{
    int i;
    int n=this.topic.length;
    for(i=0;i<n;i++)
    {
        if(topic[i].topicnum==num)
        {
            return topic[i].ifright(answer);
        }
    }
    return -1;
}
int calculatescoresum()//计算这张试卷的总分
{
    int i;
    for(i=0;i<papertopicsum;i++)
    {
        if(this.topic[i].topicnum>0)
            papertopicsumscore+=questionscore[i];
    }
    return papertopicsumscore;
}

}

一张答卷对应一张试卷(注意后面也要判断是否有这么一张试卷能和答卷匹配的上)那么答卷类和试卷类是有联系的,答案类中存考生的答案要与试卷中的标准答案对照判断正误。
class Answerpaper //答卷
{
int answerpapernum;//答卷的编号
Paper paper;//答卷对应的试卷
String answerstudentid;
int answersum;//回答的题目数目
int[] answernum=new int[100];//回答的题目题号
String[] answer=new String[100];//回答的答案
int getscore=0;
boolean[] result=new boolean[100];//题目顺序是试卷的顺序

public Answerpaper(int answerpapernum,String answerstudentid)
{
    this.answerpapernum=answerpapernum;
    this.answerstudentid=answerstudentid;
}

void matchpaper(Paper paper)
{
	this.paper=paper;
}
void matchanswernum(int answersum)
{
    this.answersum=answersum;
}
int matchstudent(Student[] student)//判断答卷上的学号是否存在
{
    int i;
    int n=student.length;
    for(i=0;i<n;i++)
    {
        if(student[i].studentid.equals(this.answerstudentid))
            return 1;
    }
    return 0;
}
void matchanswer(int i,int questionnum,String answer)
{
    this.answernum[i]=questionnum;
    this.answer[i]=answer;
}
void scoreget()//判断答卷上的回答是否正确
{
    int i,j;
    int flag=0;//判断答卷中是否没有试卷中的题目
    //System.out.printf("试卷中的题目数目:%d-答卷中的题目数目:%d\n",this.paper.papertopicsum,this.answersum);
    for(i=0;i<this.paper.papertopicsum;i++)
    {
        flag=0;
        for(j=0;j<this.answersum;j++)
        {
            if(this.answernum[j]==this.paper.topic[i].topicnum)
            {
                flag=1;
                if(paper.ifcorrect(paper.topic[i].topicnum,answer[j])==1&&!this.paper.topic[i].topiccontent.equals("-1"))
                {
                    result[i]=true;
                }
                else
                {
                    result[i]=false;
                }
            }
        }
        if(flag==0)
        {
            result[i]=false;
        }
    }
}

}
三.踩坑心得:
也就是我在前言中提到的,在设计好类和类的关系后,重要的是理清题目中的bug。我在这三次大作业中耗时最长的就是修bug,在开始写代码的时候就自以为是的开始,甚至没看完整题目要求,而要求的改变很可以会产生后面一系列代码的修改。例如第三次作业里,题目,试卷,答卷,和学生的信息是可以打乱的(而我一开始就以样例为默认,试卷的输入是在题目输完以后,而前两次的输入顺序是固定的,就使得第三次的惯性思维),如果试卷的输入是在题目输完以后的,那便可获取到试卷信息的时候就开始匹配相应的题目,而要是乱序的话,就只能用ArrayList将题目,试卷,答卷全部集合好后再一一匹配好。
int x=0;
for(i=1;i<papern;i=i+2)//匹配各个题的分值
{
questionnum[x]=Integer.parseInt(output[i]);
score[x]=Integer.parseInt(output[i+1]);
paper[papersum].matchquestion(x,questionnum[x],score[x]);
x++;
}
那么paper[papersum].matchquestion(x,questionnum[x],score[x]);就应该放在信息全部提取完后。而这种修改让我头痛的就是i的范围。因为直接在
while(true)
{
input[n]=scanner.nextLine();
if(input[n].equals("end"))
{
break;
}
else
{
//提取信息;
}
}
提取信息里匹配的话i的范围就会用到while里的数据,而要在while后匹配,i的范围要重新设置。
开头没开好,没看准需求,最后就只能在一个个测试点上反复折腾

四.改进建议
对我在三次大作业的代码,我觉得有三点是要改进的:
一. 考虑到降低类和类的耦合性,减少类和类的关系(类和类的关系处理不当)。
我一开始的代码是
class Topic//题目
{
int topicnum;
String topiccontent;
String standardanswer;

public Topic(int topicnum,String topiccontent,String standardanswer)
{
    this.topicnum=topicnum;
    this.topiccontent=topiccontent;
    this.standardanswer=standardanswer;
}

}
class Paper//试卷
{
int papernum;
int papertopicsum;//试卷中题目的数目
ArrayList topic=new ArrayList<>();//试卷上的题目
ArrayList quesionnum=new ArrayList<>();//记录的题号
ArrayList quesionscore=new ArrayList<>();//记录的题目分数
int papertopicsumscore=0;//试卷的满分
int deletetopic;//试卷上删除的题号

public Paper(int papernum,int papersum)
{
	this.papertopicsum=papersum;
    this.papernum=papernum;
}

}
在Paper类中的属性包含了Topic类,未降低耦合性可以再设计一个类来将两类联系起来;
class Topic//题目
{
int topicnum;
String topiccontent;
String standardanswer;

public Topic(int topicnum,String topiccontent,String standardanswer)
{
    this.topicnum=topicnum;
    this.topiccontent=topiccontent;
    this.standardanswer=standardanswer;
}

}
class Paper//试卷
{
int papernum;
int papertopicsum;//试卷中题目的数目
ArrayList quesionnum=new ArrayList<>();//记录的题号
ArrayList quesionscore=new ArrayList<>();//记录的题目分数
int papertopicsumscore=0;//试卷的满分
int deletetopic;//试卷上删除的题号

public Paper(int papernum,int papersum)
{
	this.papertopicsum=papersum;
    this.papernum=papernum;
}

}

class Connect
{
ArrayList topic=new ArrayList<>();
Paper paper;

二.正如设计和分析模块上说的,我把题目的分值放在了试卷类里,这点是错误的,分值是属于题目的应该放在题目类中,一个类对应一个类的职责(类设计不得当)
三.在上面的代码可以看出我在集合中还是习惯性的用数组,而这对后续的使用会很麻烦(依赖数组)
例如:int[] answernum=new int[100];其中真正储存的有用的信息并不是answernum.length(其值为100),而用ArrayList answernum,那答案则有answernum.size();
五.总结:
以下是我在这三次作业中学到的:
第一次作业:
1、使用Pattern和Matcher,正则表达式提取信息;
第二次作业:
1、ArrayList的使用,split的使用;
第三次作业:
1、StringTokenizer的使用;

三次作业中最主要的就是提取信息,以下我总结出三种方法:
方法一.Pattern,Matcher和正则表达式
代码:
package text;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test
{
public static void main(String[] args)
{
String input="#N:3 #Q:3+2= #A:5";
Pattern pattern=Pattern.compile("#N:(.) #Q:(.) #A:(.*)");
Matcher matcher=pattern.matcher(input);
if(matcher.find())
{
System.out.printf("%s\n",matcher.group(0));
System.out.printf("%s\n",matcher.group(1));
System.out.printf("%s\n",matcher.group(2));
System.out.printf("%s\n",matcher.group(3));
}
}
}
运行结果:

N:3 #Q:3+2= #A:5

3
3+2=
5
方法二:spil和正则表达式
代码:
package text;
public class Test
{
public static void main(String[] args)
{
String input="#N:3 #Q:3+2= #A:5";
String[] output=input.split("[#N:]|[#Q:]|[#A:]|[\s:]");
for(int i=0;i<output.length;i++)
{
if(output[i]!="")
System.out.printf("%s\n",output[i]);
}
}
}
运行结果:
3
3+2=
5
方法三:StringTokenizer
代码:
package text;
import java.util.*;
public class Test
{
public static void main(String[] args)
{
String input="#N:3 #Q:3+2= #A:5";
StringTokenizer st=new StringTokenizer(input,"#ANQ: ");//切割字符串
while(st.hasMoreTokens())
{
System.out.printf("%s\n",st.nextToken());
}
}
}
调试结果:
3
3+2=
5

判断输入是否符合标准:
String input=scanner.nextLine();
String regex="//正则表达式";
boolean isValid=Pattern.matches(regex,input);

posted @   喻文轩  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示