- 一 、前言:
- 總結三次題目集的知識點、題量、難度等情況
- 知識點
- 題目及題量、難度
nchu-software-oop-2024-上-1:- nchu-software-oop-2024-上-2:
- nchu-software-oop-2024-上-3:
- 知識點
- 總結三次題目集的知識點、題量、難度等情況
- 二、第一次的答題判題程式分析
- 設計與分析
- 原始碼如下->
- 第一次的答題判題程式類圖以及SourceMontor的生成報表內容:
- 原始碼如下->
- 踩坑心得
- 改進建議
- 設計與分析
- 三、第二次答題判題程式分析
- 設計與分析
- 原始碼如下->
- 第二次的答題判題程式類圖以及SourceMontor的生成報表內容:
- 原始碼如下->
- 踩坑心得
- 改進建議
- 設計與分析
- 四、第三次答題判題程式分析
- 設計與分析
- 原始碼如下->
- 第三次的答題判題程式類圖以及SourceMontor的生成報表內容:
- 原始碼如下->
- 踩坑心得
- 改進建議
- 設計與分析
- 五、總結:
一 、前言:
總結三次題目集的知識點、題量、難度等情況
知識點
第一次題目集主要考察了輸入輸出處理,字串處理,正規表示式,型別轉換,類與陣列的基本使用,類與物件,關聯類等知識點。
第二次題目集主要考察了資料的查詢、排序,字串處理,正規表示式,型別轉換,類與物件、方法的使用,方法的呼叫與返回,多個類的關係與使用、連結串列LinkedList等知識點。
第三次題目集主要考察了物件導向的封裝性,java中日期類的使用,正規表示式等知識點。
三次題目集都體現了物件導向的設計思想。
題目及題量、難度
nchu-software-oop-2024-上-1:
7-1設計一個風扇Fan類
7-2類和物件的使用
7-3成績計算-1-類、陣列的基本運用
7-4成績計算-2-關聯類
7-5答題判題程式-1
共五道題,難度不高,感覺是之前課前題目集系列的過渡,為了我們熟悉類的使用,並且考察我們c語言的基礎。其中前四題花費一天,最後一題即這次大作業的核心作業花費一天。第一次的答題判題程式較為簡單,但也是第一次接觸利用java語言進行多類設計。
nchu-software-oop-2024-上-2:
7-1手機按價格排序、查詢
7-2sdut-oop-4-求圓的面積(類與物件)
7-3Java類與物件-汽車類
7-4答題判題程式-2
共四道題,難度較上次有提高。與上一次相比,答題程式的功能增加給這道題增加了不少難度,多種資訊的輸入以及輸出都很複雜。其中前三題花費一天,最後一題即這次上次的答題判題程式的功能增加花費兩天。
nchu-software-oop-2024-上-3:
7-1物件導向程式設計(封裝性)
7-2jmu-java-日期類的基本使用
7-3答題判題程式-3
共三道題,難度較上次大大提高。第二題中日期類的使用利用java庫中自帶的日期類。在寫第二題時對日期類學習到很多java自帶的日期類函式的使用。一開始沒有想到java有自帶的日期類,犯了蠢自己寫了個日期類。最後一題的難度更是飆升了好多:格式的更嚴格判斷、空試卷的輸出、空字元
二、第一次的答題判題程式分析
設計與分析
原始碼如下->
點選檢視程式碼
import java.util.Scanner;
import java.text.DecimalFormat;
class Topic{
int no;
String cotent;
String standaraAnswer;
public Topic()
{}
public Topic(int no,String cotent,String standaraAnswer)
{
this.no=no;
this.cotent=cotent;
this.standaraAnswer=standaraAnswer;
}
// public Topic set()
// {
// }
public String get()
{
String str="#N:"+no+" #Q:"+cotent+" #A:"+standaraAnswer;
return str;
}
public boolean answer(String s)
{
if(s.equals(this.standaraAnswer))
return true;
else
return false;
}
}
class Test{
int num;//題目數量
static Topic[] tt=new Topic[100];
public Test(){}
public Test(int n){
num=n;
}
public boolean answer(int n,String a)
{
return tt[n].answer(a);
}
public void get(int n,String q,String a)
{
tt[n]=new Topic(n,q,a);
}
}
class Answer{
static Test t;//試卷
int n;
String[] answer=new String[100];//答案列表
boolean[] a=new boolean[100];//判題列表
public Answer(){}
public Answer(int num)
{
n=num;
}
public void q(int n)//判題
{
a[n]=Test.tt[n].answer(answer[n]);
}
public void p(int n)//輸出
{
String str=Test.tt[n].cotent+"~"+answer[n];
System.out.println(str);
}
public void a(int n,String s)//儲存答案
{
answer[n]=s;
}
}
public class Main{
public static void main(String[] args)
{
Scanner input=new Scanner(System.in);
int num=input.nextInt();
Answer a1=new Answer(num);
a1.t=new Test(num);
String w=input.nextLine();
for(int i=0;i<num;i++)
{
String s=input.nextLine();
// System.out.printf("%s",s);
String[] s1=s.split(" #");
String[] s3=new String[3];
for(int j=0;j<3;j++)
{
String[] s2=s1[j].split(":");
s3[j]=s2[1].trim();
// System.out.println(s2[1]);
}
// // int n=0;
// String[] s3=new String[3];
// for(int j=0;j<3;j++)
// {
// String s1=input.next();
// String[] s2=s1.split(":");
// // if(j==0)
// // {
// //
// // }
// // else
// s3[j]=s2[1];
// }
int n = Integer.parseInt(s3[0]);
a1.t.get(n,s3[1],s3[2]);
// System.out.println(a1.t.tt[n].get());
}
// for(int i=1;i<=num;i++)
// System.out.println(a1.t.tt[i].get());
for(int i=1;i<=num;i++)
{
String s1=input.next();
if(s1.equals("end"))
System.exit(0);
String[] s2=s1.split(":");
a1.a(i,s2[1]);
// System.out.println(a1.answer[i]);
a1.q(i);
a1.p(i);
//System.out.println(a1.a[i]);
}
for(int i=1;i<=num;i++)
{
System.out.print(""+a1.a[i]);
if(i!=num)
System.out.printf(" ");
}
}
}
第一次的答題判題程式類圖以及SourceMontor的生成報表內容:
在這次題目中我設計了Topic,Answer,Test,Main四個類。就是按照老師給的建議類設計而設計的。第一次的程式根據老師給的建議設計很快就寫出程式碼了,還是很簡單的。
- Topic類:用於表示題目,包括題號(no)、題目內容(content)和標準答案(standardAnswer)。包含了一個無參構造方法和一個有參構造方法,用於初始化題目物件。
提供了get方法,返回題目的字串表示形式。
提供了answer方法,用於判斷給定答案是否與標準答案一致。 - Answer類:用於表示答題情況,包括答題數量(n)、答案列表(answer[])和判題列表(a[])。
包含了一個無參構造方法和一個有參構造方法,用於初始化答題物件。
提供了q方法,用於判斷指定題目的答案是否正確。
提供了p方法,用於輸出指定題目的內容和答案。
提供了a方法,用於儲存答案到答案列表中。 - Test類:用於表示一張試卷,包含題目數量(num)和題目類陣列(Topic[])。
包含了一個無參構造方法和一個有參構造方法,用於初始化試卷物件。
提供了answer方法,用於判斷指定題目的答案是否正確。
提供了get方法,用於新增題目到試卷中。 - Main類:包含了主程式,用於輸入試題資訊、學生答題資訊和判題結果輸出。
輸入題目數量,建立Answer物件和Test物件,迴圈輸入題目資訊並新增到試卷中,迴圈輸入學生答題資訊並判題並輸出結果。
踩坑心得
- 設計題目類時誤以為題目只為數字,沒有考慮到題目內容中可能包含特殊字元或格式不規範的情況導致輸入字串時存不進去。
- 題號的輸入順序與題號無關,剛開始時忽略了這一點導致亂序輸入時程式碼非零返回。
- 答卷中答案數量、順序應與試卷的題目數量、順序都一致,沒注意這一點也導致了出現答案順序對不上、答案資料不夠時出現非零返回。
- 對格式處理不夠嚴格,輸入題目時忘記對無效空格的刪除,導致輸出的題目格式錯誤。
這次的程式碼總共寫了133行,運用了四個類,學會了類與陣列的使用,可以建立類陣列,學會了關聯類,對類間關係有了更好的認識。
改進建議
- 輸入時資料時對字串進行更加嚴格的格式判斷。確保輸入的內容符合預期格式,避免因輸入內容格式錯誤導致的異常或錯誤情況的發生。
- 對題目內容的分析、獲取進行最佳化,考慮更多的特殊情況和格式,確保能夠正確解析各種格式的題目內容。
三、第二次答題判題程式分析
設計與分析
原始碼如下->
點選檢視程式碼
import java.util.Scanner;
import java.text.DecimalFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Topic{//題目
private int no;
private String cotent;
private String standaraAnswer;
public Topic()
{}
public Topic(int no,String cotent,String standaraAnswer)
{
this.no=no;
this.cotent=cotent;
this.standaraAnswer=standaraAnswer;
}
public String get()//獲得題目資訊
{
String str=cotent+"~"+standaraAnswer;
return str;
}
public boolean answer(String s)//判題
{
if(s.equals(this.standaraAnswer))
return true;
else
return false;
}
public String getC()
{
return cotent;
}
public String getS()
{
return standaraAnswer;
}
public int getN()
{
return no;
}
}
class Test{//試卷
int num=-1;//試卷編號
int tN;//試卷題目數量
int fen;
Topic[] tt=new Topic[100];//題目
Sort[] ss=new Sort[100];//題目對應分數
public Test(){}
public Test(int n){
num=n;
}
public void tNo(int n)
{
tN=n;
}
public void F(int f)
{
fen=f;
}
public boolean answer(int n,String a)//判題
{
return tt[n].answer(a);
}
public void get(int n,String q,String a)//建立題目
{
tt[n]=new Topic(n,q,a);
tN=n;
}
public void getS(int n,int f)//建立分
{
ss[n]=new Sort(n,f);
}
public int getN()
{
return num;
}
// public int gets(int n)
// {
// return ss[n].getF();
// }
}
class Answer{//答卷
int n;//答卷的試卷編號
int num;
String[] answer=new String[100];//答案列表
boolean[] a=new boolean[100];//判題列表
int[] fen1=new int[100];//每一題的得分
int fen;//總分
public Answer(){}
public Answer(int n)
{
this.n=n;
}
public void q(int n,boolean b)//判題
{
a[n]=b;
}
public void nu(int n)
{
num=n;
}
public String p(int n)//輸出
{
return answer[n];
}
public void a(int n,String s)//儲存答案
{
answer[n]=s;
}
public void f(int n,int f)
{
fen1[n]=f;
}
public void P()
{
int sum=0;
for(int i=0;i<num;i++)
{
System.out.printf("%d",fen1[i]);
sum+=fen1[i];
if(i!=num-1)
System.out.printf(" ");
else
System.out.printf("~");
}
System.out.println(sum);
}
public int F()
{
for(int i=0;i<num;i++)
fen+=fen1[n];
return fen;
}
public int getN()
{
return n;
}
}
class Sort{//分值
private int num;
private int fen;
public Sort(){}
public Sort(int n,int f)
{
num=n;
fen=f;
}
public int getF()//獲得分資訊
{
return fen;
}
public int getN()//獲得編號資訊
{
return num;
}
}
public class Main{
public static void main(String[] args)
{
Scanner input=new Scanner(System.in);
// int num=input.nextInt();
Answer[] a1=new Answer[100];
Test[] t1=new Test[100];
Topic[] tt=new Topic[100];
Pattern nqa=Pattern.compile("#N:(.+) #Q:(.+) #A:(.+)");
Pattern t=Pattern.compile("#T:(.+) (.+)");
Pattern S=Pattern.compile("#S:.+ (.+)");
String s=input.nextLine();int an=0,sj=0,n0=0,t0=0;int numSJ=0;
while(s.equals("end")==false)
{
Matcher m1=nqa.matcher(s);
Matcher m2=t.matcher(s);
Matcher m3=S.matcher(s);
while(m1.find()){//存入題目
String[] s1=s.split(" #");
String[] s3=new String[3];
for(int j=0;j<3;j++)
{
String[] s2=s1[j].split(":");
s3[j]=s2[1].trim();
//System.out.println(s2[1]);
}
int n = Integer.parseInt(s3[0]);
tt[n]=new Topic(n,s3[1],s3[2]);
//System.out.println(tt[n].get());
}
while(m2.find()){//試卷資訊
Pattern p1=Pattern.compile("[0-9]+");
Matcher p11=p1.matcher(s);
int flag=0,j=0,f2=0;
while(p11.find())
{
t0=Integer.parseInt(p11.group());
if(flag==0)
{
n0=t0;
flag++;
//System.out.println("試卷"+t0);
t1[n0]=new Test(t0);
numSJ++;
continue;
}
if(flag%2==1)
{
for(int i=0;i<100;i++)
{
if(t0==i)
{
t1[n0].tt[j]=new Topic(j,tt[i].getC(),tt[i].getS());
break;
}
}
// System.out.println(t1[n0].tt[j].get());
flag++;
continue;
}
if(flag%2==0&&flag!=0)
{
f2+=t0;
t1[n0].getS(j,t0);
//System.out.println("題號"+t1[n0].ss[j].getN()+" 分"+t1[n0].ss[j].getF());
j++;
flag++;
continue;
}
// System.out.println(p11.group());
}
t1[n0].tNo(j);
//System.out.println(t1[n0].num);
t1[n0].F(f2);
if(f2!=100)
System.out.println("alert: full score of test paper"+n0+" is not 100 points");
}
while(m3.find()){//答卷資訊
Pattern p1=Pattern.compile("[0-9]+");
Matcher p11=p1.matcher(s);
int flag=0,j=0;
while(p11.find())
{
t0=Integer.parseInt(p11.group());
if(flag==0)
{
a1[an]=new Answer(t0);
sj=t0;
flag++;
//System.out.println("答卷"+an+"試卷"+sj);
continue;
}
a1[an].a(j,p11.group());
//System.out.println("答案"+a1[an].p(j));
j++;
}
an++;
//System.out.println(sj);
// for(int i=0;i<t1[sj].tN;i++)
// {
// if(a1[an].p(i)==null)
// System.out.println("answer is null");
// else
// {
// System.out.println(t1[sj].tt[i].getC()+"~"+a1[an].p(i)+"~"+t1[sj].answer(i,a1[an].p(i)));
// }
// }
//System.out.println(s);
}
s=input.nextLine();
}
int fg=1;
for(int k=0;k<an;k++)
{
//System.out.println(a1[k].n);
for(int l=1;l<=numSJ;l++)
{
//System.out.println(t1[l].num);
if(a1[k].n==t1[l].num)
{
fg=0;
//System.out.println("The test paper number does not exist");
// System.out.println(t1[l].num+" "+a1[k].n);
break;
}
else
{fg=1;continue;}
}
if(fg==1)
{
System.out.println("The test paper number does not exist");
continue;
}
int sj0=a1[k].n;
a1[k].nu(t1[sj0].tN);
// System.out.println(a1[k].num);
//System.out.println(sj0);
for(int i=0;i<t1[sj0].tN;i++)
{
if(a1[k].p(i)==null)
System.out.println("answer is null");
else
{
System.out.println(t1[sj0].tt[i].getC()+"~"+a1[k].p(i)+"~"+t1[sj0].answer(i,a1[k].p(i)));
a1[k].q(i,t1[sj0].answer(i,a1[k].p(i)));
if(t1[sj0].answer(i,a1[k].p(i)))
{
a1[k].f(i,t1[sj0].ss[i].getF());
}
else
a1[k].f(i,0);
}
}
a1[k].P();
}
}
}
第二次的答題判題程式類圖以及SourceMontor的生成報表內容:
第二次的迭代程式我增加了一個分數類來存放各題的分數。總共設計了五個類。根據功能的增加改變了上次的四個類。
- Topic類:用於表示題目,包括題號(no)、題目內容(content)和標準答案(standardAnswer)。包含了一個無參構造方法和一個有參構造方法,用於初始化題目物件。
提供了get方法,返回題目的字串表示形式。
提供了answer方法,用於判斷給定答案是否與標準答案一致。
較上次增加了getC(),getS(),getN()三個方法來獲取題號、題目內容和標準答案。 - Test類:用於表示一張試卷,包含試卷編號(num)、題目數量(tN)、總分(fen)、題目類陣列(Topic[])、和分數類陣列(Sort[])。
包含了一個無參構造方法和一個有參構造方法,用於初始化試卷物件。
提供了answer方法,用於判斷指定題目的答案是否正確。
提供了get方法,用於新增題目到試卷中。
較上次增加了:
tNo方法:用於輸入試卷編號。
F方法:用於輸入試卷總分。
get方法:用於獲取題目資訊。getS方法 :用於獲取分資訊。
getN方法:用於獲取試卷編號。 - Answer類:用於表示答題情況,包括答卷的試卷編號(n)、答題數量(num)、答案列表(answer[])、判題列表(a[])、分數列表(fen1[])和總得分(fen)。
包含了一個無參構造方法和一個有參構造方法,用於初始化答題物件。
提供了q方法,用於儲存判斷指定題目的答案是否正確的結果。
提供了p方法,用於返回答案字串。
提供了a方法,用於儲存答案到答案列表中。
較上次增加了:
nu方法:用於儲存答題數量
f方法:用於儲存每一題的得分。
P方法:用於輸出得分情況。
F方法:用於計算總得分。
getN()方法:用於獲取試卷編號。 - Sort類:用於表示一張試卷的題目各分數,包含題目編號(num)和題目滿分(fen)。
包含了一個無參構造方法和一個有參構造方法,用於初始化分值物件。
提供了getF方法,用於獲取分資訊。
提供了getN方法,用於獲取題目編號資訊。 - Main類:包含了主程式,用於輸入試題資訊、學生答題資訊和判題結果輸出。
輸入題目數量,建立Answer物件、Test物件和Topic物件,迴圈輸入題目資訊並新增到試卷中,迴圈輸入學生答題資訊並判題並輸出結果。
踩坑心得
- 兩試卷單答卷,亂序,有缺失的題號:忽略了試卷資訊可能出現題號題目缺失的情況。
- 2試卷2答卷 滿分不是100 答案有缺失 答卷試卷號不匹配 :沒有計算試卷總分以及判斷試卷是否滿分為100分。
沒有考慮答卷中可能出現未輸入答案的情況、輸入試卷編號不存在的情況。
由於沒有對試卷編號進行查詢後再判斷和對答案數量進行判斷,導致出現非零返回。
這次的程式碼總共寫了344行,運用了五個類,在上一次的基礎上增加了分數類,增加試卷分值統計及答卷得分統計功能,修改了題目類、答卷類等,對上一次的答題判題程式進行了內容與功能的完善。
改進建議
- 輸入試卷資訊時先對所含題目編號進行查詢判斷,沒有時輸出題目不存在資訊。然後對總分進行判斷並輸出相應資訊
- 輸入答卷資訊時先對所輸入的試卷編號進行查詢判斷,如果存在該試卷再進行後續操作。
- 判題時判斷答案總數量是否符合試卷題目數量要求,未達到要求輸入答案不存在資訊。
四、第三次答題判題程式分析
設計與分析
原始碼如下->
點選檢視程式碼
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Topic{//題目
private int no;
private String cotent;
private String standaraAnswer;
int y=0;//1題目不存在 2答案不存在
public Topic()
{}
public Topic(int no,String cotent,String standaraAnswer)
{
this.no=no;
this.cotent=cotent;
this.standaraAnswer=standaraAnswer;
}
public boolean answer(String s)//判題
{
if(standaraAnswer==null)
return false;
if(s.equals(this.standaraAnswer))
return true;
else
return false;
}
public String getC()
{return cotent;}
public String getS()
{return standaraAnswer;}
public int getN()
{return no;}
public void setC()
{cotent="shanchu";standaraAnswer="shanchu";}
public void setY(int n)
{y=n;}
}
class Test{//試卷
int num=-1;//試卷編號
int tN;//試卷題目數量
int fen;
Topic[] tt=new Topic[100];//題目
Sort[] ss=new Sort[100];//題目對應分數
public Test(){}
public Test(int n)
{num=n;}
public void tNo(int n)
{tN=n;}
public void F(int f)
{fen=f;}
public boolean answer(int n,String a)//判題
{return tt[n].answer(a);}
public void get(int n,String q,String a)//建立題目
{tt[n]=new Topic(n,q,a);tN=n;}
public void getS(int n,int f)//建立分
{ss[n]=new Sort(n,f);}
public int getN()
{return num;}
}
class Student{
private String num;
private String name;
Student(){}
Student(String num,String name)
{
this.num=num;
this.name=name;
}
public void print()
{System.out.println(num+"-"+name);}
public String getNum()
{return num;}
public String getName()
{return name;}
public String getS()
{return num+" "+name;}
}
class Answer{//答卷
int n;//答卷的試卷編號
String id;//學生學號
int num;
String name;
String[] answer=new String[100];//答案列表
boolean[] a=new boolean[100];//判題列表
boolean[] b=new boolean[100];
int[] fen1=new int[100];//每一題的得分
int fen;//總分
public Answer(){}
public Answer(int n)
{this.n=n;}
public void q(int n,boolean b)//儲存判題結果
{a[n]=b;}
public void nu(int n)
{num=n;}
public void id(String n)
{id=n;}
public void name(String n)
{name=n;}
public String p(int n)//輸出
{return answer[n];}
public void a(int n,String s)//儲存答案
{answer[n]=s;b[n]=true;}
public void f(int n,int f)
{fen1[n]=f;}
public void P()
{
System.out.printf(id+" "+name+": ");
int sum=0;
for(int i=0;i<num;i++)
{
System.out.printf("%d",fen1[i]);
sum+=fen1[i];
if(i!=num-1)
System.out.printf(" ");
else
System.out.printf("~");
}
System.out.println(sum);
}
public int getN()
{return n;}
public String getid()
{return id;}
}
class Sort{//分值
private int num;
private int fen;
public Sort(){}
public Sort(int n,int f)
{
num=n;
fen=f;
}
public int getF()//獲得分資訊
{return fen;}
public int getN()//獲得編號資訊
{return num;}
}
public class Main{
public static Answer[] a1=new Answer[100];
public static Test[] t1=new Test[100];
public static Topic[] tt=new Topic[100];
public static Student[] ss=new Student[100];
public static int numSJ=0,numStu=0,an=0,sj=0,tihao=1;
public static void main(String[] args)
{
Scanner input=new Scanner(System.in);
Pattern NQA=Pattern.compile("#N:[0-9]+\\s+#Q:.+\\s+#A:.+");//題目 1
Pattern T=Pattern.compile("#T:[0-9]+(\\s+[0-9]+-[0-9]+)*");//試卷 2
Pattern S=Pattern.compile("#S:[0-9]+\\s+[0-9]+(\\s+#A:[0-9]+-.*)*");//答卷 4
Pattern X=Pattern.compile("#X:([0-9]+\\s+\\w+-)*([0-9]+\\s+\\w+)");//學生 3
Pattern DN=Pattern.compile("#D:N-(.+)");//刪除 5
String s=input.nextLine();
while(s.equals("end")==false)
{
Matcher m1=NQA.matcher(s);
Matcher m2=T.matcher(s);
Matcher m4=S.matcher(s);
Matcher m3=X.matcher(s);
Matcher m5=DN.matcher(s);
if(m1.matches())
{ setTimu(s);}
else if(m2.matches())
{ setShijuan(s);}
else if(m3.matches())
{ setXuesheng(s);}
else if(m4.matches())
{setDajuan(s);}
else if(m5.matches())
{ Shanchu(s);}
else
{System.out.println("wrong format:"+s); }
s=input.nextLine();
}
p();
}
public static void answer(int x)
{
if(x==1)
System.out.println("non-existent question~0");
if(x==2)
System.out.println("answer is null");
}
public static void Tihao1(int[] x,int n)
{
for(int i=0;i<n;i++)
System.out.println("the question "+x[i]+" invalid~0");
}
public static void setTimu(String s)
{
//存入題目
String[] s1=s.split(" #");
String[] s3=new String[3];
for(int j=0;j<2;j++)
{
String[] s2=s1[j].split(":");
s3[j]=s2[1].trim();
//System.out.println(s3[j]);
}
String[] s2=s1[2].split(":");
if(s2.length>1)
{
s3[2]=s2[1].trim();
}
else
s3[2]=null;
tt[Integer.parseInt(s3[0])]=new Topic(Integer.parseInt(s3[0]),s3[1],s3[2]);
//System.out.println(tt[n].get());
}
public static void setShijuan(String s)
{
Pattern p1=Pattern.compile("[0-9]+");
Matcher p11=p1.matcher(s);
int flag=0,j=0,f2=0;int ti=0,t0=0,n0=0;
while (p11.find())
{
t0=Integer.parseInt(p11.group());
if(flag==0)
{
n0=t0;
flag++;
t1[n0]=new Test(t0);
numSJ++;
continue;
}
if(flag%2==1)
{
for(int i=0;i<100;i++)
{
if(tt[i]==null)
continue;
if(t0==tt[i].getN())
{
t1[n0].tt[j]=new Topic(tt[i].getN(),tt[i].getC(),tt[i].getS());
ti=1;break;
}
else
ti=0;
}
if(ti==0)
{
t1[n0].tt[j]=new Topic(j,"cuo","cuo");
tihao=ti;
t1[n0].tt[j].setY(1);
}
flag++;
continue;
}
if(flag%2==0&&flag!=0)
{
f2+=t0;
t1[n0].getS(j,t0);
j++;
flag++;
}
}
t1[n0].tNo(j);
t1[n0].F(f2);
if(f2!=100)
System.out.println("alert: full score of test paper"+n0+" is not 100 points");
}
public static void setXuesheng(String s)
{
Pattern p1=Pattern.compile("\\w+");
Matcher p11=p1.matcher(s);
int flag=0;int i=0;
String[] stu=new String[2];
while(p11.find())
{
//System.out.println(p11.group());
if(flag==0){flag++;continue;}
else if(flag%2==1)
{
stu[flag%2]=p11.group();
flag++;
continue;
}
else if(flag%2==0)
{
stu[flag%2]=p11.group();
ss[i]=new Student(stu[1],stu[0]);
numStu++;
i++;
flag++;
}
}
}
public static void setDajuan(String s)
{
int t0=0,n0=0;
Pattern p1=Pattern.compile("[0-9]+");
Matcher p11=p1.matcher(s);
Pattern p2=Pattern.compile("#A:(.+)");
Matcher p22=p2.matcher(s);
int j=0,i=0;
while(p11.find()&&i<2)
{
t0=Integer.parseInt(p11.group());
if(i==0)
{
a1[an]=new Answer(t0);
sj=t0;
i++;
}
else if(i==1)
{
a1[an].id(p11.group());
i++;
}
}
while(p22.find())
{
String s0=p22.group();
String[] s1=s.split(" #A:");
for(int k=1;k<s1.length;k++)
{
String[] s2=s1[k].split("-");
if(s2.length==1)
{
int l=Integer.parseInt(s2[0]);
a1[an].a(l-1,null);
}
else if(s2.length==2)
{
int l=Integer.parseInt(s2[0]);
a1[an].a(l-1,s2[1]);
}
}
}
an++;
}
public static void Shanchu(String s)
{
Pattern p1=Pattern.compile("[0-9]+");
Matcher p11=p1.matcher(s);
while(p11.find()){
int t0=Integer.parseInt(p11.group());
//System.out.println(t0);
for(int i=1;i<=numSJ;i++)
{
for(int j=0;j<t1[i].tN;j++)
{
//System.out.println(j);
if(t1[i].tt[j].getN()==t0)
{
t1[i].tt[j].setC();
}
}
}
}
}
public static void p()
{
int fg=1;
for(int k=0;k<an;k++)
{
int[] tihao1=new int[100];
int tihao2=0;
int ans=2;
int fg2=0;
//System.out.println(a1[k].n);
for(int l=1;l<=numSJ;l++)
{
if(a1[k].n==t1[l].num)
{
fg=0;
break;
}
else
{fg=1;continue;}
}
if(fg==1)
{
System.out.println("The test paper number does not exist");
continue;
}
int sj0=a1[k].n;
a1[k].nu(t1[sj0].tN);
for(int i=0;i<t1[sj0].tN;i++)
{
if(a1[k].p(i)==null)
{
if(a1[k].b[i])
{
a1[k].q(i,false);
a1[k].f(i,0);
System.out.println(t1[sj0].tt[i].getC()+"~~"+"false");
}
else
t1[sj0].tt[i].setY(2);
}
else
{
if(t1[sj0].tt[i].getS()==null)
{
System.out.println(t1[sj0].tt[i].getC()+"~"+a1[k].p(i)+"~"+t1[sj0].answer(i,a1[k].p(i)));
a1[k].q(i,false);
a1[k].f(i,0);
}
if(t1[sj0].tt[i].getS().equals("cuo"))
{
a1[k].q(i,false);
a1[k].f(i,0);
}
else if(t1[sj0].tt[i].getS().equals("cuoti"))
{
tihao=0;
}
else if(t1[sj0].tt[i].getC().equals("shanchu"))
{
tihao1[tihao2]=t1[sj0].tt[i].getN();
tihao2++;
}
else
{
System.out.println(t1[sj0].tt[i].getC()+"~"+a1[k].p(i)+"~"+t1[sj0].answer(i,a1[k].p(i)));
a1[k].q(i,t1[sj0].answer(i,a1[k].p(i)));
if(t1[sj0].answer(i,a1[k].p(i)))
{
a1[k].f(i,t1[sj0].ss[i].getF());
}
else
a1[k].f(i,0);
}
}
answer(t1[sj0].tt[i].y);
}
for(int i=0;i<numStu;i++)
{
if(a1[k].getid().equals(ss[i].getNum()))
{
a1[k].name(ss[i].getName());
fg2=1;
break;
}
else
fg2=0;
}
if(fg2==0)
{
System.out.println(a1[k].getid()+" not found");
continue;
}
Tihao1(tihao1,tihao2);
a1[k].P();
}
}
}
第三次的答題判題程式類圖以及SourceMontor的生成報表內容:
第三次的迭代程式中多了學生和刪除。我增加了一個Student類,共有六個類,其他類只是根據功能的增加而增加了各個類中的方法,並且將每種資訊的解析單獨建立方法,最佳化程式碼。
- Topic類:用於表示題目,包括題號(no)、題目內容(content)、標準答案(standardAnswer)和存在資訊(y)。包含了一個無參構造方法和一個有參構造方法,用於初始化題目物件。
提供了answer方法,getC(),getS(),getN()。
較上次增加了:
setC方法:用於標記刪除的題目。
setY方法:用於標記題目不存在或答案不存在的情況。 - Test類:用於表示一張試卷,包含試卷編號(num)、題目數量(tN)、總分(fen)、題目類陣列(Topic[])、和分數類陣列(Sort[])。
包含了一個無參構造方法和一個有參構造方法,用於初始化試卷物件。
提供了answer方法,get方法、tNo方法、F方法、get方法、getS方法 、getN方法。
與上次程式中的試卷類一樣,沒有做改變。 - Student類:用於表示學生資訊,包括學生的學號(num)和姓名(name)。
包含了一個無參構造方法和一個有參構造方法,用於初始化學生物件。
提供了print方法,用於輸出學號、姓名。
提供了getNum方法,用於返回學號字串。
提供了getName方法,用於返回姓名字串。
提供了getS方法,用於返回學號和姓名共同組成的字串。 - Answer:用於表示答題情況,包括答卷的試卷編號(n)、答題數量(num)、答題者學號(id)、答題者姓名(name)、答案列表(answer[])、判題列表(a[])、分數列表(fen1[])和總得分(fen)。
包含了一個無參構造方法和一個有參構造方法,用於初始化答題物件。
提供了q方法,p方法,a方法,
nu方法,f方法,P方法,F方法,getN()方法。
較上次增加了:
id方法:用於儲存答題者的學號。
name方法:用於儲存答題者的姓名。
getid方法:用於獲取答題者的學號。 - Sort類:用於表示一張試卷的題目各分數,包含題目編號(num)和題目滿分(fen)。
包含了一個無參構造方法和一個有參構造方法,用於初始化分值物件。
提供了getF方法,getN方法。
與上次程式中的分數類一樣,沒有做改變。 - Main類:包含了主程式,用於輸入試題資訊、學生資訊、學生答題資訊和判題結果輸出。
建立Answer物件、Test物件、Topic物件和Student物件,迴圈輸入資訊根據輸入格式分別存入不同的物件。
增加了解析方法等:
main方法:主程式
answer方法:用於輸出不合法的答案資訊。
Tihao1方法:用於輸出不合法的題目資訊。
setTimu方法:用於解析題目資訊。
setShijuan方法:用於解析試卷資訊。
setXuesheng方法:用於解析學生資訊。
setDajuan方法:用於解析答卷資訊。
Shanchu方法:用於刪除題目。
p方法:用於輸出答題資訊。
踩坑心得
這次的第三次的大作業讓我卡了很久,卡了很多的測試點。
- 這次的大作業對輸入資訊的格式要求十分嚴格
改了很久的正規表示式才改出來。
學習了很久正規表示式。這次的每一條資訊都要嚴格按照題目中提到的格式,不符合時要輸出“wrong format+輸入資訊”。 - 這次的作業增加了一個重要的刪除功能,一開始想簡單的令原題目為空,但是刪除題目應是讓所有試卷中也有的題目同時都刪除,令題目為空需要大量的迴圈巢狀,而且在查詢題目時易出現忽略有題目為空的情況而導致非零返回。所以我在題目類增加了一個y標記題目和答案的存在資訊。
- 巨大的坑~空字元!
首先是空白卷和答案為空的區別:空白卷是答題時只輸入了試卷資訊和答題人的資訊,沒有輸題號也沒有輸答案,這時會輸入“answer is null”,而答案為空則是當答題時輸入題號卻沒有輸入答案會認為時正常的答卷,此時輸出“題目+++false”。這兩者非常不一樣,卡在這裡卡了很久。 - 亂序輸入的問題:這次的答卷中答題的順序可以打亂,但判題仍是按照試卷中的題目順序,這個在最後判題並輸出時需要注意順序問題。
這次的程式碼總共寫了454行,運用了六個類,在上一次的基礎上增加了學生類,主要增加了刪除功能,修改了答卷類、主類和各種資訊的解析等。
改進建議
- 努力學習正規表示式,嚴格按照大作業題目中的各資訊格式要求更改上次程式碼中的正規表示式。
- 便於刪除功能的實現,我在題目類增加了一個y作為標記,刪除時便是題目不存在,答題時為作答也可以標記為答案不存在,還解決了優先順序的功能,一舉三得。
- 解析答卷資訊時,加入標記每一道題目的答案情況,分為答案不存在、答案為空的情況,即上一條裡的y,並根據大作業題目給出的輸入資訊優先順序輸出對應資訊。
五、總結:
在這三次大作業中第二次體驗一個程式的多次迭代,上一次還是C語言的課設。在每一次的迭代中學到了更多java語言的知識和麵向物件的設計思想。
從第一次的簡單的處理輸入資訊的分析和解析,到後面越來越複雜的資訊處理,越來越複雜的格式要求,在這個過程中學到了正規表示式的多種用法、字串的多種處理方法、字串與其他型別比如整型的相互轉換。
處理資訊時還要考慮錯誤資訊的處理,避免出現越界訪問、非零返回等錯誤。
每一次的資訊種類增加和功能增加都需要我再次對自己設計的類進行分析,在這個過程我慢慢發現java語言與c語言的區別,慢慢領悟物件導向設計的思想有何作用,也慢慢理解為什麼要學習這門課程。
在這三週中,老師也經常在上課時點撥我們在類上的設計,指導我們完成這幾次的大作業。在這些點撥過程中我也發現自己還有很多知識並不瞭解,甚至有些知識是自以為是的瞭解,使用中依然一頭霧水。
我覺得在我完成的這三次大作業中我的答題判題程式還有很多可以改進的地方:沒有很好的實現函式單一職責,有些函式的功能比較複雜;函式模組化不夠;封裝性不夠,有一些的類沒有做到所有資料的私有化,導致程式碼的安全性、靈活性都不高;沒有嘗試用HashMap,查詢速度、插入刪除操作、記憶體空間都還有很大可改進空間。
最後希望下一次的大作業能做到更好,嘗試用一些靈活性更好的資料結構。