1.前言:
前三次作业主要都是写答题判断程序,由于这学期才接触java,所以一开始对于怎么写,以及java语法有点不太适应。后来学习到“类”这个强大的工具和正则表达式,但因为并不熟练,所以写起来十分艰难。这三次题目难度逐级提升,都在原本的基础上添加了新的内容与知识点。类和对象的使用,关联,排序与查找,封装,正则表达式等,后来还加入了HashMap等知识。
2.设计与分析:
第一次:
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三部分:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、题目内容
一行为一道题,可以输入多行数据。
格式:"#N:"+题号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
样例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
3、答题信息
答题信息按行输入,每一行为一组答案,每组答案包含第2部分所有题目的解题答案,答案的顺序号与题目题号相对应。
格式:"#A:"+答案内容
格式约束:答案数量与第2部分题目的数量相同,答案之间以英文空格分隔。
样例:#A:2 #A:78
2是题号为1的题目的答案
78是题号为2的题目的答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、答题信息
一行为一道题的答题信息,根据题目的数量输出多行数据。
格式:题目内容+" ~"+答案
样例:1+1=~2
2+2= ~4
3、判题信息
判题信息为一行数据,一条答题记录每个答案的判断结果,答案的先后顺序与题目题号相对应。
格式:判题结果+" "+判题结果
格式约束:
1、判题结果输出只能是true或者false,
2、判题信息的顺序与输入答题信息中的顺序相同
样例:true false true
源码:
import java.util.Scanner;
class Question{
private int num;
void setNum(int x){
this.num = x;
}
int getNum(){
return this.num;
}
private String que;
void setQue(String x){
this.que = x;
}
String getQue(){
return this.que;
}
private String ans1;
void setAns(String x){
this.ans1 = x;
}
String getAns(){
return this.ans1;
}
Question(){}
Question(int num,String que,String ans){
this.num=num;
this.que=que;
this.ans1=ans;
}
String Ans(String ans){
if(ans1.compareTo(ans)==0)
return "true";
else
return "false";
}
void end(){
System.out.print(que+"~");
}
}
public class Main{
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int sum=sc.nextInt();
String t= sc.nextLine();
Question []que=new Question[sum];
int n;
for(int i=0;i<sum;i++){
String str=sc.nextLine();
String []str1=str.split("#N:| #Q:| #A:");
n=Integer.parseInt(str1[1].trim());
que[n-1]=new Question(n,str1[2].trim(),str1[3].trim());
}
String ans=sc.nextLine();
String []Ans=ans.split("#A:| ");
String []Ans1=new String[sum];
for(int i=0;i<sum;i++)
{
Ans1[i]=que[i].Ans(Ans[2*i+1]);
}
String over=sc.next();
if(over.compareTo("end")==0){
for (int i=0;i<sum;i++) {
que[i].end();
System.out.println(Ans[2*i+1]);
}
for(int i=0;i<sum;i++){
if(i==sum-1)
System.out.print(Ans1[i]);
else
System.out.print(Ans1[i]+" ");
}
}
}
}
见下图代码分析:
从图中可更直观的看见,代码只有78行,较为简易,说明题目难度并不算高,这也是对对象和类的使用的初步了解。第一次作业虽然相对简单,但是对第二和第三次作业具有很大意义。又由于第一次只使用了一个类以及正则表达式相关知识的不了解为我后面两次作业的艰难铺垫。
第二次:
要求输入题目信息、试卷信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三种,三种信息可能会打乱顺序混合输入:
1、题目信息
一行为一道题,可输入多行数据(多道题)。
格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:
1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
2、试卷信息
一行为一张试卷,可输入多行数据(多张卷)。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值
题目编号应与题目信息中的编号对应。
一行信息中可有多项题目编号与分值。
样例:#T:1 3-5 4-8 5-2
3、答卷信息
答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序与试卷信息中的题目顺序相对应。
格式:"#S:"+试卷号+" "+"#A:"+答案内容
格式约束:答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
样例:#S:1 #A:5 #A:22
1是试卷号
5是1号试卷的顺序第1题的题目答案
22是1号试卷的顺序第2题的题目答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、试卷总分警示
该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100分,该部分忽略,不输出。
格式:"alert: full score of test paper"+试卷号+" is not 100 points"
样例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。
格式:题目内容+""+答案++""+判题结果(true/false)
约束:如果输入的答案信息少于试卷的题目数量,答案的题目要输"answer is null"
样例:3+2=5true
4+6=~22~false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:5 8 0~13
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、提示错误的试卷号
如果答案信息中试卷的编号找不到,则输出”the test paper number does not exist”
源码:
import java.util.*;
class Question{
private int num;
void setNum(int x){
this.num = x;
}
int getNum(){
return this.num;
}
private String que;
void setQue(String x){
this.que = x;
}
String getQue(){
return this.que;
}
private String ans1;
void setAns(String x){
this.ans1 = x;
}
String getAns(){
return this.ans1;
}
Question(){}
Question(int num,String que,String ans){
this.num=num;
this.que=que;
this.ans1=ans;
}
String Ans(String ans){
if(ans1.compareTo(ans)==0)
return "true";
else
return "false";
}
void end(){
System.out.print(que+"~");
}
}
public class Main{
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Scanner sc=new Scanner(System.in);
// String str=sc.nextLine();
while(sc.hasNext())
{
String str=sc.nextLine();
if ("end".equalsIgnoreCase(str)) {
break;
}
list.add(str);
}
sc.close();
int size=list.size();
Question []que=new Question[list.size()];
int n;
int t=0;
for(int i=0;i<size;i++)
{
if(list.get(i).startsWith("#N"))
{
t++;
String []str1=list.get(i).split("#N:| #Q:| #A:");
n=Integer.parseInt(str1[1].trim());
que[n-1]=new Question(n,str1[2].trim(),str1[3].trim());
}
}
int a1,a2,total=0;
for(int i=0;i<size;i++)
{
if(list.get(i).startsWith("#T"))
{
String []str2=list.get(i).split("#T:| 1-| 2-");
a1=Integer.parseInt(str2[2].trim());
a2=Integer.parseInt(str2[3].trim());
total=a1+a2;
}
}
if(total<100)
System.out.println("alert: full score of test paper1 is not 100 points");
int b1=0,b2=0,to=0;
for(int i=0;i<size;i++)
{
if(list.get(i).startsWith("#S"))
{
String []Ans=list.get(i).split("#S:| #A:");
String []Ans1=new String[t];
for(i=0;i<t;i++)
{
Ans1[i]=que[i].Ans(Ans[i+2]);
// if(Ans1[0].compareTo("false")==0)
// {
// b1=0;
// }
//if(Ans1[0].compareTo("true")==0)
//{
//b1=Integer.parseInt(Ans[2].trim());
//}
//if(Ans1[1].compareTo("false")==0)
//{
// b2=0;
// }
//if(Ans1[1].compareTo("true")==0)
//{
//b2=Integer.parseInt(Ans[3].trim());
//}
//to=b1+b1;
}
for (i=0;i<t;i++)
{
que[i].end();
System.out.print(Ans[i+2]+"~");
System.out.println(Ans1[i]);
}
break;
}
}
}
}
见下图代码分析:
相较于第一次,第二次增加了答题类,类的内容以及类之间的关联自行设计,要求上则增添了题目,答卷等相关数量与顺序的输入,以及一些输入错误的处理方法,有一定程度上的复杂度,对于类以及正则表达式相关知识运用要求更高。因对题目要求未理清及基础知识掌握不足而导致代码的不完善。
第三次:
要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分五种,信息可能会打乱顺序混合输入。
1、题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。
格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:
1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
2、试卷信息
试卷信息为独行输入,一行为一张试卷,多张卷可分多行输入数据。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值+" "+题目编号+"-"+题目分值+...
格式约束:
题目编号应与题目信息中的编号对应。
一行信息中可有多项题目编号与分值。
样例:#T:1 3-5 4-8 5-2
3、学生信息
学生信息只输入一行,一行中包括所有学生的信息,每个学生的信息包括学号和姓名,格式如下。
格式:"#X:"+学号+" "+姓名+"-"+学号+" "+姓名....+"-"+学号+" "+姓名
格式约束:
答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
样例:
#S:1 #A:5 #A:22
1是试卷号
5是1号试卷的顺序第1题的题目答案
4、答卷信息
答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序号与试 卷信息中的题目顺序相对应。答卷中:
格式:"#S:"+试卷号+" "+学号+" "+"#A:"+试卷题目的顺序号+"-"+答案内容+...
格式约束:
答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
答案内容可以为空,即””。
答案内容中如果首尾有多余的空格,应去除后再进行判断。
样例:
#T:1 1-5 3-2 2-5 6-9 4-10 7-3
#S:1 20201103 #A:2-5 #A:6-4
1是试卷号
20201103是学号
2-5中的2是试卷中顺序号,5是试卷第2题的答案,即T中3-2的答案
6-4中的6是试卷中顺序号,4是试卷第6题的答案,即T中7-3的答案
注意:不要混淆顺序号与题号
5、删除题目信息
删除题目信息为独行输入,每一行为一条删除信息,多条删除信息可分多行输入。该信息用于删除一道题目信息,题目被删除之后,引用该题目的试卷依然有效,但被删除的题目将以0分计,同时在输出答案时,题目内容与答案改为一条失效提示,例如:”the question 2 invalid~0”
格式:"#D:N-"+题目号
格式约束:
题目号与第一项”题目信息”中的题号相对应,不是试卷中的题目顺序号。
本题暂不考虑删除的题号不存在的情况。
样例:
N:1 #Q:1+1= #A:2
N:2 #Q:2+2= #A:4
T:1 1-5 2-8
X:20201103 Tom-20201104 Jack
S:1 20201103 #A:1-5 #A:2-4
D:N-2
end
输出
alert: full score of test paper1 is not 100 points
1+1=5false
the question 2 invalid~0
20201103 Tom: 0 0~0
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、试卷总分警示
该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100 分,该部分忽略,不输出。
格式:"alert: full score of test paper"+试卷号+" is not 100 points"
样例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。
格式:题目内容+""+答案++""+判题结果(true/false)
约束:如果输入的答案信息少于试卷的题目数量,每一个缺失答案的题目都要输出"answer is null" 。
样例:
3+2=5true
4+6=22false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:**学号+" "+姓名+": "**+题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目、被删除的题目、答案错误的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:20201103 Tom: 0 0~0
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、被删除的题目提示信息
当某题目被试卷引用,同时被删除时,答案中输出提示信息。样例见第5种输入信息“删除题目信息”。
5、题目引用错误提示信息
试卷错误地引用了一道不存在题号的试题,在输出学生答案时,提示”non-existent question~”加答案。例如:
输入:
N:1 #Q:1+1= #A:2
T:1 3-8
X:20201103 Tom-20201104 Jack-20201105 Www
S:1 20201103 #A:1-4
end
输出:
alert: full score of test paper1 is not 100 points
non-existent question~0
20201103 Tom: 0~0
如果答案输出时,一道题目同时出现答案不存在、引用错误题号、题目被删除,只提示一种信息,答案不存在的优先级最高,例如:
输入:
N:1 #Q:1+1= #A:2
T:1 3-8
X:20201103 Tom-20201104 Jack-20201105 Www
S:1 20201103
end
输出:
alert: full score of test paper1 is not 100 points
answer is null
20201103 Tom: 0~0
6、格式错误提示信息
输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。
例如:wrong format:2 #Q:2+2= #4
7、试卷号引用错误提示输出
如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”,答卷中的答案不用输出,参见样例8。
8、学号引用错误提示信息
如果答卷中的学号信息不在学生列表中,答案照常输出,判分时提示错误。
本题暂不考虑出现多张答卷的信息的情况。
源码:
import java.util.*;
class Question{
private int num;
void setNum(int x){
this.num = x;
}
int getNum(){
return this.num;
}
private String que;
void setQue(String x){
this.que = x;
}
String getQue(){
return this.que;
}
private String ans1;
void setAns(String x){
this.ans1 = x;
}
String getAns(){
return this.ans1;
}
Question(){}
Question(int num,String que,String ans){
this.num=num;
this.que=que;
this.ans1=ans;
}
String Ans(String ans){
if(ans1.compareTo(ans)==0)
return "true";
else
return "false";
}
void end(){
System.out.print(que+"~");
}
}
public class Main{
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Scanner sc=new Scanner(System.in);
// String str=sc.nextLine();
while(sc.hasNext())
{
String str=sc.nextLine();
if ("end".equalsIgnoreCase(str)) {
break;
}
list.add(str);
}
sc.close();
int size=list.size();
Question []que=new Question[list.size()];
int n;
int t=0;
boolean qu1=true;
boolean qu2=true;
for(int i=0;i<size;i++)
{
if(list.get(i).startsWith("#N"))
{
t++;
qu1=list.get(0).contains("#Q");
qu2=list.get(1).contains("#Q");
if(list.get(i).contains("#Q")) {
String[] str1 = list.get(i).split("#N:| #Q:| #A:");
n = Integer.parseInt(str1[1].trim());
que[n - 1] = new Question(n, str1[2].trim(), str1[3].trim());
// System.out.println(str1.length);
}
else
System.out.println("wrong format:"+list.get(i));
}
}
int a1=0,a2=0,total=0;
int q1=0,q2=0;
int text0=0;
for(int i=0;i<size;i++)
{
if(list.get(i).startsWith("#T"))
{
String []str2=list.get(i).split("#T:| |-");
text0=Integer.parseInt(str2[1].trim());
q1=Integer.parseInt(str2[2].trim());
a1=Integer.parseInt(str2[3].trim());
if(str2.length==6){
a2=Integer.parseInt(str2[5].trim());
q2=Integer.parseInt(str2[4].trim());
}
total=a1+a2;
}
}
boolean t1=true;
boolean t2=true;
int ji1=0,ji2=0;
for(int i=1;i<=t;i++)
{
if(q1==i)
ji1++;
if(q2==i)
ji2++;
}
if(a1==0)
ji1++;
if(a2==0)
ji2++;
if(ji1==0)
t1=false;
if(ji2==0)
t2=false;
if(total<100)
System.out.println("alert: full score of test paper1 is not 100 points");
int del=-1;
for(int i=0;i<size;i++)
{
if(list.get(i).startsWith("#D"))
{
String []str4=list.get(i).split("#D:N-");
del=Integer.parseInt(str4[1].trim());
}
}
boolean te=true;
int b1=0,b2=0,to=0;
int text=0;
int id1=0;
for(int i=0;i<size;i++)
{
if(list.get(i).startsWith("#S"))
{
String []Ans=list.get(i).split("#S:| |#A:1-|#A:2-");
text=Integer.parseInt(Ans[1].trim());
id1=Integer.parseInt(Ans[2].trim());
if(text!=text0)
te=false;
String []Ans1=new String[t];
for(i=0;i<t;i++)
{
if(qu1==false)
i++;
Ans1[i]=que[i].Ans(Ans[2*i+4]);
if(qu1==true)
{
if (Ans1[0].compareTo("false") == 0) {
b1 = 0;
}
if (Ans1[0].compareTo("true") == 0) {
b1 = a1;
}
}
if(a2!=0&&i==1)
{
if(Ans1[1].compareTo("false")==0)
{
b2=0;
}
if(Ans1[1].compareTo("true")==0)
{
b2=a2;
}
}
to=b1+b2;
}
for (i=0;i<t;i++)
{
if(qu1==false) {
i++;
}
if(del==1||t1==false)
{
i=1;
b1=0;
to=b2;
}
if(te==true)
{
if(t1==true&&qu1==true&&del!=1) {
que[i].end();
System.out.print(Ans[2 * i + 4] + "~");
System.out.println(Ans1[i]);
}
if(t2==true&&qu2==true&&del!=2) {
que[i].end();
System.out.print(Ans[2 * i + 4] + "~");
System.out.println(Ans1[i]);
}
}
if(del==2||t2==false)
{
b2=0;
to=b1;
break;
}
}
if(qu1==false)
System.out.println("non-existent question~0");
break;
}
}
// if(t1==false)
// System.out.println("non-existent question~0");
if(del!=-1&&t1==true&&t2==true)
{
System.out.println("the question "+del+" invalid~0");
}
if(t2==false)
System.out.println("non-existent question~0");
// if(t1==false||t2==false)
// {
// System.out.println("non-existent question~0");
// }
int id2=0;
boolean idtext=true;
for(int i=0;i<size;i++)
{
if(list.get(i).startsWith("#X"))
{
String []str3=list.get(i).split("#X:| |-");
id2=Integer.parseInt(str3[1].trim());
if(id1!=id2)
idtext=false;
if(te==true&&idtext==true)
{
if(a2!=0)
{
System.out.print(str3[1] + " " + str3[2] + ": " + b1 +" "+b2+ "~" + to);
}
if(a2==0)
{
System.out.print(str3[1] + " " + str3[2] + ": " + b1 + "~" + to);
}
}
}
}
if(te==false)
System.out.println("The test paper number does not exist");
if(idtext==false)
System.out.println(id1+" not found");
for(int i=0;i<size;i++)
{
if(!(list.get(i).startsWith("#N")||list.get(i).startsWith("#X")||list.get(i).startsWith("#T")||list.get(i).startsWith("#S")||list.get(i).startsWith("#D")))
{
System.out.println("wrong format:"+list.get(i));
}
}
}
}
见下图代码分析:
如图,与第二次相比代码行数成倍数增长,函数复杂度也增加不少。同样,题目又增加了学生与答卷之类的相关信息,对于输入的各种格式也有一定变化,更是增加了信息的删除,题目测试点增添许多,这对我们运用相关知识的能力要求更加严格。除了与前两题标准的正则表达式运用之外,还可以添加HashMap的运用使题目更加简单,代码简易。
3.踩坑心得:
测试不充分,在测试样例时只测试了部分情况,导致在提交时部分测试点未通过。
粗心大意导致代码逻辑错误或者遗漏。在读题时未仔细阅读题目要求,导致后续代码书写困难,甚至未完成,例如题目要求分多个类,而我只用了一个类,导致代码复杂,推进困难。对正则表达式的不熟悉,与对HashMap的不了解,致使后面题目难度提升时思路不畅,不知从哪里下手。
4.改进建议:
合理使用正则表达式替换main中主体结构,再加入HashMap的运用,优化整体。运用多个类合理将各种数据封装使用,减少main中繁杂函数的使用。
5.总结:
在本阶段 Java 类和对象题目集的学习中,我学到了很多重要的知识和技能。
我明白了类和对象的概念及其相互关系,学会了如何定义和使用类,以及如何通过对象来操作数据。同时,我也更加熟悉了 Java 的数据类型、方法、构造函数等基本元素。
然而,我也意识到还有一些地方需要进一步学习和研究。比如,对于面向对象编程的高级特性,如继承、多态、接口等,还需要更深入地理解和掌握。此外,在处理复杂问题时,如何更好地设计类的结构和方法,以提高代码的可读性和可维护性,也是我需要不断学习和提升的方面。同时对于正则表达式和HashMap的使用,我也需要进一步学习,做到能合理使用它们。
标签:题目,String,试卷,信息,PTA,答案,三次,格式 From: https://www.cnblogs.com/xiao-03-02-ye-xiao/p/18149513