oop第一次博客作業(yè)
前言
這學(xué)期剛剛接觸面向?qū)ο蟪绦蛟O(shè)計(jì),使用的是java語(yǔ)言。在此之前只接觸過(guò)c語(yǔ)言。以我目前的學(xué)習(xí)進(jìn)程來(lái)看二者的差別更多體現(xiàn)在面向?qū)ο蟮钠渲幸粋€(gè)基本特性上,即封裝性。在c語(yǔ)言中幾乎所有內(nèi)容都是公開(kāi)的,java可以有效得規(guī)避這點(diǎn)。
學(xué)習(xí)的知識(shí)點(diǎn)
1.知道了類(lèi)間關(guān)系。面向?qū)ο蟪绦蛟O(shè)計(jì)中要根據(jù)實(shí)際情況合理使用繼承,關(guān)聯(lián),聚合,組合,依賴等五類(lèi)類(lèi)間關(guān)系。選擇合適的類(lèi)間關(guān)系有利于代碼的維護(hù)和使用。
2.知道了類(lèi)的使用。類(lèi)可以包含屬性和方法。這使得類(lèi)可以實(shí)現(xiàn)單一職責(zé)原則。這項(xiàng)原則在程序設(shè)計(jì)中尤為重要。另外的,設(shè)計(jì)類(lèi)時(shí)也要注意封裝性,不能盲目得使用public。同時(shí),部分類(lèi)需要通過(guò)實(shí)例調(diào)用。
3.學(xué)習(xí)了java包中的部分方法,知道了導(dǎo)包。為了完成PTA作業(yè),學(xué)習(xí)了regex,Math等包中的方法,便于處理部分問(wèn)題。
4.學(xué)會(huì)了管理數(shù)據(jù)。學(xué)習(xí)了ArrayList,LinkedList和HashMap的原理和使用。
自我改進(jìn)的方面
- 增強(qiáng)程序設(shè)計(jì)的“全局觀念”。設(shè)計(jì)程序考慮后續(xù)的拓展與維護(hù)。
- 拓寬學(xué)習(xí)方法。對(duì)于面向?qū)ο蟮膶W(xué)習(xí)不能僅局限于學(xué)校的學(xué)習(xí)體系,學(xué)習(xí)網(wǎng)站和AI大模型也是較好的學(xué)習(xí)途徑。
三次PTA的難度逐步加大的同時(shí)也根據(jù)實(shí)際情況增加了越來(lái)越多的限制,對(duì)學(xué)生的應(yīng)變能力與自學(xué)能力有較大要求。
設(shè)計(jì)分析
第一次PTA大作業(yè):
1)題目要求
7-5 答題判題程序-1
分?jǐn)?shù) 74
困難
作者 蔡軻
單位 南昌航空大學(xué)
設(shè)計(jì)實(shí)現(xiàn)答題程序,模擬一個(gè)小型的測(cè)試,要求輸入題目信息和答題信息,根據(jù)輸入題目信息中的標(biāo)準(zhǔn)答案判斷答題的結(jié)果。
輸入格式:
程序輸入信息分三部分:
1、題目數(shù)量
格式:整數(shù)數(shù)值,若超過(guò)1位最高位不能為0,
樣例:34
2、題目?jī)?nèi)容
一行為一道題,可以輸入多行數(shù)據(jù)。
格式:"#N:"+題號(hào)+" "+"#Q:"+題目?jī)?nèi)容+" "#A:"+標(biāo)準(zhǔn)答案
格式約束:題目的輸入順序與題號(hào)不相關(guān),不一定按題號(hào)順序從小到大輸入。
樣例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
3、答題信息
答題信息按行輸入,每一行為一組答案,每組答案包含第2部分所有題目的解題答案,答案的順序號(hào)與題目題號(hào)相對(duì)應(yīng)。
格式:"#A:"+答案內(nèi)容
格式約束:答案數(shù)量與第2部分題目的數(shù)量相同,答案之間以英文空格分隔。
樣例:#A:2 #A:78
2是題號(hào)為1的題目的答案
78是題號(hào)為2的題目的答案
答題信息以一行"end"標(biāo)記結(jié)束,"end"之后的信息忽略。
輸出格式:
1、題目數(shù)量
格式:整數(shù)數(shù)值,若超過(guò)1位最高位不能為0,
樣例:34
2、答題信息
一行為一道題的答題信息,根據(jù)題目的數(shù)量輸出多行數(shù)據(jù)。
格式:題目?jī)?nèi)容+" ~"+答案
樣例:1+1=~2
2+2= ~4
3、判題信息
判題信息為一行數(shù)據(jù),一條答題記錄每個(gè)答案的判斷結(jié)果,答案的先后順序與題目題號(hào)相對(duì)應(yīng)。
格式:判題結(jié)果+" "+判題結(jié)果
格式約束:
1、判題結(jié)果輸出只能是true或者false,
2、判題信息的順序與輸入答題信息中的順序相同
樣例:true false true
設(shè)計(jì)建議:
以下是針對(duì)以上題目要求的設(shè)計(jì)建議,其中的屬性、方法為最小集,實(shí)現(xiàn)代碼中可根據(jù)情況添加所需的內(nèi)容:
題目類(lèi)(用于封裝單個(gè)題目的信息):
屬性:題目編號(hào)、題目?jī)?nèi)容、標(biāo)準(zhǔn)答案-standardAnswer
方法:數(shù)據(jù)讀寫(xiě)set\get方法、
判題方法(答案-answer):判斷答案-answer是否符合標(biāo)準(zhǔn)答案-standardAnswer
試卷類(lèi)(用于封裝整套題目的信息)
屬性:題目列表(題目類(lèi)的對(duì)象集合)、題目數(shù)量
方法:判題方法(題號(hào)-num、答案-answer):判斷答案-answer是否符合對(duì)應(yīng)題號(hào)的題目標(biāo)準(zhǔn)答案-standardAnswer
保存題目(題號(hào)-num、題目-question):將題目保存到題目列表中,保存位置與num要能對(duì)應(yīng)
答卷類(lèi)(用于封裝答題信息)
屬性:試卷(試卷類(lèi)的對(duì)象)、答案列表(保存每一題的答案)、判題列表(保存每一題的判題結(jié)果true/false)
方法:判題方法(題號(hào)-num):判斷答案列表中第num題的結(jié)果是否符合試卷中對(duì)應(yīng)題號(hào)的題目標(biāo)準(zhǔn)答案
輸出方法(題號(hào)-num):按照題目的格式要求,輸出題號(hào)為num的題目的內(nèi)容和答題結(jié)果。
保存一個(gè)答案(題號(hào)-num,答案-answer):保存題號(hào)為num的題目的答題結(jié)果answer。
2)個(gè)人設(shè)計(jì)
由于第一次作業(yè)給出了設(shè)計(jì)建議,本次作業(yè)按照建議進(jìn)行設(shè)計(jì)。
針對(duì)題目信息設(shè)計(jì)了exercise類(lèi),其中包含了題號(hào),題目?jī)?nèi)容和正確答案三個(gè)屬性。除構(gòu)造方法等存取類(lèi)方法外,還設(shè)計(jì)了一個(gè)根據(jù)輸入的答案判斷答案對(duì)錯(cuò)的方法。
`class exercise{
private int NO = 0;//題號(hào)
private String Content = "";//題目?jī)?nèi)容
private String standardAnswer = "";//正確答案
public int getNO() {
return NO;
}
public void setNO(int NO) {
this.NO = NO;
}
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
public boolean judge(String answer){//判斷對(duì)錯(cuò)
return answer.equals(this.standardAnswer);
}
}`
針對(duì)試卷信息設(shè)計(jì)了paper類(lèi),其中包含了總題數(shù)和題目類(lèi)數(shù)組兩個(gè)屬性。除構(gòu)造方法等存取類(lèi)方法外,還設(shè)計(jì)了一個(gè)根據(jù)題目順序和答案判斷對(duì)應(yīng)題目的答案的對(duì)錯(cuò)的方法。
`class paper {
public int sum;//總題數(shù)
public exercise[] exe;//題目數(shù)組
public boolean Judge(int num, String answer) {
return exe[num].judge(answer);
}
public void save(int num, String question) {
exe[num].setNO(num);
exe[num].setContent(question);
}
public int getSum() {
return sum;
}
public void setSum(int sum) {
this.sum = sum;
exe = new exercise[sum + 1];
}
}`
針對(duì)答卷信息設(shè)計(jì)了AnswerPaper類(lèi),其中包含了試卷,答案列表和判斷列表三個(gè)屬性。只有存取類(lèi)方法。
`class AnswerPaper {
public paper Paper;//試卷
private String[] answer;//答案列表
private boolean[] judge;//判斷列表
public AnswerPaper(int sum) {
this.answer = new String[sum + 1];
this.judge = new boolean[sum + 1];
}
public void judge(int num) {
this.judge[num] = Paper.exe[num].judge(answer[num]);
}
public void saveAnswer(int num, String answer) {
this.answer[num] = answer;
}
public void setPaper(paper paper) {
Paper = paper;
}
public void setAnswer(String[] answer) {
this.answer = answer;
}
public void setJudge(boolean[] judge) {
this.judge = judge;
}
public String[] getAnswer() {
return answer;
}
public boolean[] getJudge() {
return judge;
}
}`

3)設(shè)計(jì)分析:
由于本次作業(yè)是第一次大作業(yè),本人對(duì)于程序設(shè)計(jì)經(jīng)驗(yàn)欠缺,造成了較大的設(shè)計(jì)缺陷:
- 設(shè)計(jì)的類(lèi)中部分屬性為public,這不符合面向?qū)ο蟮姆庋b性。
- 沒(méi)有考慮程序的后續(xù)迭代,部分類(lèi)設(shè)計(jì)僅適用于當(dāng)前作業(yè),而在后續(xù)作業(yè)無(wú)法繼續(xù)使用。如因?yàn)楸绢}給出了總題數(shù),在paper類(lèi)設(shè)計(jì)中就簡(jiǎn)單得將題目存在以總題數(shù)為長(zhǎng)度的數(shù)組中,沒(méi)有考慮到后續(xù)題目數(shù)量的確定和試卷中題目的順序。
第二次PTA大作業(yè)
1)題目要求
7-4 答題判題程序-2
分?jǐn)?shù) 73
困難
作者 蔡軻
單位 南昌航空大學(xué)
設(shè)計(jì)實(shí)現(xiàn)答題程序,模擬一個(gè)小型的測(cè)試,以下粗體字顯示的是在答題判題程序-1基礎(chǔ)上增補(bǔ)或者修改的內(nèi)容。
要求輸入題目信息、試卷信息和答題信息,根據(jù)輸入題目信息中的標(biāo)準(zhǔn)答案判斷答題的結(jié)果。
輸入格式:
程序輸入信息分三種,三種信息可能會(huì)打亂順序混合輸入:
1、題目信息
一行為一道題,可輸入多行數(shù)據(jù)(多道題)。
格式:"#N:"+題目編號(hào)+" "+"#Q:"+題目?jī)?nèi)容+" "#A:"+標(biāo)準(zhǔn)答案
格式約束:
1、題目的輸入順序與題號(hào)不相關(guān),不一定按題號(hào)順序從小到大輸入。
2、允許題目編號(hào)有缺失,例如:所有輸入的題號(hào)為1、2、5,缺少其中的3號(hào)題。此種情況視為正常。
樣例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
2、試卷信息
一行為一張?jiān)嚲恚奢斎攵嘈袛?shù)據(jù)(多張卷)。
格式:"#T:"+試卷號(hào)+" "+題目編號(hào)+"-"+題目分值
題目編號(hào)應(yīng)與題目信息中的編號(hào)對(duì)應(yīng)。
一行信息中可有多項(xiàng)題目編號(hào)與分值。
樣例:#T:1 3-5 4-8 5-2
3、答卷信息
答卷信息按行輸入,每一行為一張答卷的答案,每組答案包含某個(gè)試卷信息中的題目的解題答案,答案的順序與試卷信息中的題目順序相對(duì)應(yīng)。
格式:"#S:"+試卷號(hào)+" "+"#A:"+答案內(nèi)容
格式約束:答案數(shù)量可以不等于試卷信息中題目的數(shù)量,沒(méi)有答案的題目計(jì)0分,多余的答案直接忽略,答案之間以英文空格分隔。
樣例:#S:1 #A:5 #A:22
1是試卷號(hào)
5是1號(hào)試卷的順序第1題的題目答案
22是1號(hào)試卷的順序第2題的題目答案
答題信息以一行"end"標(biāo)記結(jié)束,"end"之后的信息忽略。
輸出格式:
1、試卷總分警示
該部分僅當(dāng)一張?jiān)嚲淼目偡址种挡坏扔?00分時(shí)作提示之用,試卷依然屬于正常試卷,可用于后面的答題。如果總分等于100分,該部分忽略,不輸出。
格式:"alert: full score of test paper"+試卷號(hào)+" is not 100 points"
樣例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行為一道題的答題信息,根據(jù)試卷的題目的數(shù)量輸出多行數(shù)據(jù)。
格式:題目?jī)?nèi)容+""+答案++""+判題結(jié)果(true/false)
約束:如果輸入的答案信息少于試卷的題目數(shù)量,答案的題目要輸"answer is null"
樣例:3+2=5true
4+6=~22~false.
answer is null
3、判分信息
判分信息為一行數(shù)據(jù),是一條答題記錄所對(duì)應(yīng)試卷的每道小題的計(jì)分以及總分,計(jì)分輸出的先后順序與題目題號(hào)相對(duì)應(yīng)。
格式:題目得分+" "+....+題目得分+"~"+總分
``
格式約束:
1、沒(méi)有輸入答案的題目計(jì)0分
2、判題信息的順序與輸入答題信息中的順序相同
樣例:5 8 0~13
根據(jù)輸入的答卷的數(shù)量以上2、3項(xiàng)答卷信息與判分信息將重復(fù)輸出。
4、提示錯(cuò)誤的試卷號(hào)
如果答案信息中試卷的編號(hào)找不到,則輸出”the test paper number does not exist”,參見(jiàn)樣例9。
設(shè)計(jì)建議:
參考答題判題程序-1,建議增加答題類(lèi),類(lèi)的內(nèi)容以及類(lèi)之間的關(guān)聯(lián)自行設(shè)計(jì)。
題目相當(dāng)于第一次作業(yè)更加復(fù)雜:
- 輸入的三種信息可以亂序混合輸入
- 由一張?jiān)嚲硌葑兂闪硕鄰堅(jiān)嚲恚繌堅(jiān)嚲硇畔⒍夹枰鎯?chǔ)
- 存在答卷沒(méi)有答案或多余答案的情況
- 新增試卷總分預(yù)警
- 空答案的答卷有單獨(dú)的輸出情況
- 新增了判分信息的輸出
2)個(gè)人設(shè)計(jì)
針對(duì)題目類(lèi),本次作業(yè)整體延用了上次作業(yè)的exercise類(lèi)
`class exercise{
private int NO;//題目編號(hào)
private String Content;//題目?jī)?nèi)容
private String standardAnswer;//正確答案
public exercise(int NO, String content, String standardAnswer) {
this.NO = NO;
Content = content;
this.standardAnswer = standardAnswer;
}
public int getNO() {
return NO;
}
public void setNO(int NO) {
this.NO = NO;
}
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
public boolean judge(String answer){//判斷對(duì)錯(cuò)
return answer.equals(this.standardAnswer);
}
}`
針對(duì)試卷類(lèi),本次作業(yè)與上次相比變化較大。有試卷編號(hào),題目號(hào)與分值組成的HashMap,試卷總分和存儲(chǔ)試卷號(hào)順序的ArrayList。使用HashMap是為了將題目編號(hào)與題目分值相關(guān)聯(lián);使用ArrayList是因?yàn)楸敬巫鳂I(yè)未給出試卷的題目總數(shù);試卷總分是為了實(shí)現(xiàn)試卷總分預(yù)警。
`class paper {
private static int NoPaper;//試卷編號(hào)
private HashMap<Integer, Integer> ExerciseAndGrade;// key為題目編號(hào),value為題目分值
private int SumGrade = 0;
private ArrayList
public paper(int noPaper) {
NoPaper = noPaper;
ExerciseAndGrade = new HashMap<>(); // 初始化ExerciseAndGrade
}
public void setExerciseAndGrade(int NOEXE, int Grade) {
ExerciseAndGrade.put(NOEXE, Grade);
SumGrade = SumGrade + Grade;
}
public ArrayList<Integer> getEXES() {
return EXES;
}
public void addEXES(int NO) {
EXES.add(NO);
}
public int getSumGrade() {
return SumGrade;
}
public HashMap<Integer, Integer> getExerciseAndGrade() {
return ExerciseAndGrade;
}
}`
針對(duì)答卷類(lèi),本次作業(yè)對(duì)其進(jìn)行了重新設(shè)計(jì)。設(shè)計(jì)了答卷編號(hào)和存儲(chǔ)答案的ArrayList兩個(gè)屬性。使用ArrayList是因?yàn)楸敬巫鳂I(yè)未給出試卷的總題目數(shù)。
`class AnswerPaper {
private int _NoPaper;//答卷編號(hào)
private ArrayList
public AnswerPaper(int _NoPaper) {
this._NoPaper = _NoPaper;
Answers = new ArrayList<>(); // 初始化Answers
}
public void setAnswer(String Answer) {
Answers.add(Answer);
}
public int get_NoPaper() {
return _NoPaper;
}
public void set_NoPaper(int _NoPaper) {
this._NoPaper = _NoPaper;
}
public ArrayList<String> getAnswers() {
return Answers;
}
public void setAnswers(String answers) {
Answers.add(answers);
}
}`
在Main類(lèi)中定義了存儲(chǔ)題號(hào)和題目實(shí)例的exerciseMap,為HashMap;存儲(chǔ)試卷編號(hào)與試卷實(shí)例的PaperMap,為HashMap;存儲(chǔ)試卷編號(hào)的PaperSum,為ArrayList;存儲(chǔ)答卷實(shí)例的answerPaper,為ArrayList。
//題目類(lèi) static HashMap<Integer,exercise> exerciseMap=new HashMap<>();//key題號(hào),value題目 //試卷類(lèi) static HashMap<Integer,paper> PaperMap=new HashMap<>(); //key編號(hào) value試卷 static ArrayList<Integer> PaperSum = new ArrayList<>();//存試卷編號(hào) //答卷類(lèi) static ArrayList<AnswerPaper> answerPaper=new ArrayList<>();//答卷的數(shù)組
在main方法中對(duì)于輸入數(shù)據(jù)的處理與上次作業(yè)有較大不同。
由于輸入格式的改變,輸入時(shí)先對(duì)輸入數(shù)據(jù)關(guān)鍵字進(jìn)行匹配與分類(lèi),根據(jù)不同的類(lèi)別處理信息。
`String Str = "";
while (sc.hasNextLine()) {
Str = sc.nextLine();
if(Str.equals("end")) {
break;
}
if(Str.contains("#N")){
String[] parts = Str.split("#N:| #Q:| #A:");
exercise EXE = new exercise(Integer.parseInt(parts[1]),parts[2],parts[3]);
exerciseMap.put(Integer.parseInt(parts[1]),EXE);
} else if (Str.contains(("#T"))) {
String[] parts = Str.split("#T:|-| ");
paper PAPER = new paper(Integer.parseInt(parts[1]));
for(int i = 2;i < parts.length;i = i + 2) {
PAPER.setExerciseAndGrade(Integer.parseInt(parts[i]),Integer.parseInt(parts[i + 1]));
PAPER.getEXES().add(Integer.parseInt(parts[i]));
}
PaperMap.put(Integer.parseInt(parts[1]),PAPER);
if(!PaperSum.contains(Integer.parseInt(parts[1]))) {
PaperSum.add(Integer.parseInt(parts[1]));
}
} else if(Str.contains("#S")){
String[] parts = Str.split("#S:| #A:");
AnswerPaper Anpaper = new AnswerPaper(Integer.parseInt(parts[1]));
for(int i = 2; i <= parts.length - 1;i ++){
Anpaper.setAnswer(parts[i]);
}
answerPaper.add(Anpaper);
}
}`

3)設(shè)計(jì)分析
- 吸取上次作業(yè)的教訓(xùn),本次作業(yè)對(duì)所有屬性都進(jìn)行了封裝。
- 由于不知道各類(lèi)信息的具體數(shù)量,本次作業(yè)靈活使用ArrayList處理數(shù)據(jù)。同時(shí),對(duì)于部分有聯(lián)系的信息采用了HashMap進(jìn)行存儲(chǔ)。
- 各類(lèi)基本實(shí)現(xiàn)了單一職責(zé)。
- 對(duì)于上次作業(yè)的結(jié)構(gòu)進(jìn)行了較大改變,使其符合題目要求的同時(shí)更好得進(jìn)行拓展。
第三次PTA大作業(yè)
1)題目要求
7-3 答題判題程序-3
分?jǐn)?shù) 84
困難
作者 蔡軻
單位 南昌航空大學(xué)
設(shè)計(jì)實(shí)現(xiàn)答題程序,模擬一個(gè)小型的測(cè)試,以下粗體字顯示的是在答題判題程序-2基礎(chǔ)上增補(bǔ)或者修改的內(nèi)容,要求輸入題目信息、試卷信息、答題信息、學(xué)生信息、刪除題目信息,根據(jù)輸入題目信息中的標(biāo)準(zhǔn)答案判斷答題的結(jié)果。
輸入格式:
程序輸入信息分五種,信息可能會(huì)打亂順序混合輸入。
1、題目信息
題目信息為獨(dú)行輸入,一行為一道題,多道題可分多行輸入。
格式:"#N:"+題目編號(hào)+" "+"#Q:"+題目?jī)?nèi)容+" "#A:"+標(biāo)準(zhǔn)答案
格式約束:
1、題目的輸入順序與題號(hào)不相關(guān),不一定按題號(hào)順序從小到大輸入。
2、允許題目編號(hào)有缺失,例如:所有輸入的題號(hào)為1、2、5,缺少其中的3號(hào)題。此種情況視為正常。
樣例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
2、試卷信息
試卷信息為獨(dú)行輸入,一行為一張?jiān)嚲恚鄰埦砜煞侄嘈休斎霐?shù)據(jù)。
格式:"#T:"+試卷號(hào)+" "+題目編號(hào)+"-"+題目分值+" "+題目編號(hào)+"-"+題目分值+...
格式約束:
題目編號(hào)應(yīng)與題目信息中的編號(hào)對(duì)應(yīng)。
一行信息中可有多項(xiàng)題目編號(hào)與分值。
樣例:#T:1 3-5 4-8 5-2
3、學(xué)生信息
學(xué)生信息只輸入一行,一行中包括所有學(xué)生的信息,每個(gè)學(xué)生的信息包括學(xué)號(hào)和姓名,格式如下。
格式:"#X:"+學(xué)號(hào)+" "+姓名+"-"+學(xué)號(hào)+" "+姓名....+"-"+學(xué)號(hào)+" "+姓名
格式約束:
答案數(shù)量可以不等于試卷信息中題目的數(shù)量,沒(méi)有答案的題目計(jì)0分,多余的答案直接忽略,答案之間以英文空格分隔。
樣例:
#S:1 #A:5 #A:22
1是試卷號(hào)
5是1號(hào)試卷的順序第1題的題目答案
4、答卷信息
答卷信息按行輸入,每一行為一張答卷的答案,每組答案包含某個(gè)試卷信息中的題目的解題答案,答案的順序號(hào)與試 卷信息中的題目順序相對(duì)應(yīng)。答卷中:
格式:"#S:"+試卷號(hào)+" "+學(xué)號(hào)+" "+"#A:"+試卷題目的順序號(hào)+"-"+答案內(nèi)容+...
格式約束:
答案數(shù)量可以不等于試卷信息中題目的數(shù)量,沒(méi)有答案的題目計(jì)0分,多余的答案直接忽略,答案之間以英文空格分隔。
答案內(nèi)容可以為空,即””。
答案內(nèi)容中如果首尾有多余的空格,應(yīng)去除后再進(jìn)行判斷。
樣例:
#T:1 1-5 3-2 2-5 6-9 4-10 7-3
#S:1 20201103 #A:2-5 #A:6-4
1是試卷號(hào)
20201103是學(xué)號(hào)
2-5中的2是試卷中順序號(hào),5是試卷第2題的答案,即T中3-2的答案
6-4中的6是試卷中順序號(hào),4是試卷第6題的答案,即T中7-3的答案
注意:不要混淆順序號(hào)與題號(hào)
5、刪除題目信息
刪除題目信息為獨(dú)行輸入,每一行為一條刪除信息,多條刪除信息可分多行輸入。該信息用于刪除一道題目信息,題目被刪除之后,引用該題目的試卷依然有效,但被刪除的題目將以0分計(jì),同時(shí)在輸出答案時(shí),題目?jī)?nèi)容與答案改為一條失效提示,例如:”the question 2 invalid~0”
格式:"#D:N-"+題目號(hào)
格式約束:
題目號(hào)與第一項(xiàng)”題目信息”中的題號(hào)相對(duì)應(yīng),不是試卷中的題目順序號(hào)。
本題暫不考慮刪除的題號(hào)不存在的情況。
樣例:
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"標(biāo)記結(jié)束,"end"之后的信息忽略。
輸出格式:
1、試卷總分警示
該部分僅當(dāng)一張?jiān)嚲淼目偡址种挡坏扔?00分時(shí)作提示之用,試卷依然屬于正常試卷,可用于后面的答題。如果總分等于100 分,該部分忽略,不輸出。
格式:"alert: full score of test paper"+試卷號(hào)+" is not 100 points"
樣例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行為一道題的答題信息,根據(jù)試卷的題目的數(shù)量輸出多行數(shù)據(jù)。
格式:題目?jī)?nèi)容+""+答案++""+判題結(jié)果(true/false)
約束:如果輸入的答案信息少于試卷的題目數(shù)量,答案的題目要輸"answer is null"
樣例:
3+2=5true
4+6=22false.
answer is null
3、判分信息
判分信息為一行數(shù)據(jù),是一條答題記錄所對(duì)應(yīng)試卷的每道小題的計(jì)分以及總分,計(jì)分輸出的先后順序與題目題號(hào)相對(duì)應(yīng)。
格式:**學(xué)號(hào)+" "+姓名+": "**+題目得分+" "+....+題目得分+"~"+總分
格式約束:
1、沒(méi)有輸入答案的題目、被刪除的題目、答案錯(cuò)誤的題目計(jì)0分
2、判題信息的順序與輸入答題信息中的順序相同
樣例:20201103 Tom: 0 0~0
根據(jù)輸入的答卷的數(shù)量以上2、3項(xiàng)答卷信息與判分信息將重復(fù)輸出。
4、被刪除的題目提示信息
當(dāng)某題目被試卷引用,同時(shí)被刪除時(shí),答案中輸出提示信息。樣例見(jiàn)第5種輸入信息“刪除題目信息”。
5、題目引用錯(cuò)誤提示信息
試卷錯(cuò)誤地引用了一道不存在題號(hào)的試題,在輸出學(xué)生答案時(shí),提示”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
如果答案輸出時(shí),一道題目同時(shí)出現(xiàn)答案不存在、引用錯(cuò)誤題號(hào)、題目被刪除,只提示一種信息,答案不存在的優(yōu)先級(jí)最高,例如:
輸入:
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、格式錯(cuò)誤提示信息
輸入信息只要不符合格式要求,均輸出”wrong format:”+信息內(nèi)容。
例如:wrong format:2 #Q:2+2= #4
7、試卷號(hào)引用錯(cuò)誤提示輸出
如果答卷信息中試卷的編號(hào)找不到,則輸出”the test paper number does not exist”,答卷中的答案不用輸出,參見(jiàn)樣例8。
8、學(xué)號(hào)引用錯(cuò)誤提示信息
如果答卷中的學(xué)號(hào)信息不在學(xué)生列表中,答案照常輸出,判分時(shí)提示錯(cuò)誤。參見(jiàn)樣例9。
本題暫不考慮出現(xiàn)多張答卷的信息的情況。
題目在上次作業(yè)的基礎(chǔ)上進(jìn)行迭代:
- 新增了刪除題目信息。被刪除的題目有單獨(dú)的輸出方法。
- 新增了學(xué)生信息,需要單獨(dú)存儲(chǔ)。
- 答卷信息中新增了學(xué)生學(xué)號(hào)的屬性。
- 存在題目引用錯(cuò)誤的情況。
- 答卷的題目與試卷題目順序相對(duì)應(yīng)。
2)個(gè)人設(shè)計(jì)
題目類(lèi)與上次作業(yè)相比變化不大
`class exercise{
private int NO;//題目編號(hào)
private String Content;//題目?jī)?nèi)容
private String standardAnswer;//正確答案
public exercise(int NO, String content, String standardAnswer) {
this.NO = NO;
Content = content;
this.standardAnswer = standardAnswer;
}
public int getNO() {
return NO;
}
public void setNO(int NO) {
this.NO = NO;
}
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
public boolean judge(String answer){//判斷對(duì)錯(cuò)
return answer.equals(this.standardAnswer);
}
}`
試卷類(lèi)與上次作業(yè)相比變化不大
`class paper {
private static int NoPaper;//試卷編號(hào)
private HashMap<Integer, Integer> ExerciseAndGrade;// key為題目編號(hào),value為題目分值
private int SumGrade = 0;
private ArrayList
public paper(int noPaper) {
NoPaper = noPaper;
ExerciseAndGrade = new HashMap<>(); // 初始化ExerciseAndGrade
}
public void setExerciseAndGrade(int NOEXE, int Grade) {
ExerciseAndGrade.put(NOEXE, Grade);
SumGrade = SumGrade + Grade;
}
public ArrayList<Integer> getEXES() {
return EXES;
}
public void addEXES(int NO) {
EXES.add(NO);
}
public int getSumGrade() {
return SumGrade;
}
public HashMap<Integer, Integer> getExerciseAndGrade() {
return ExerciseAndGrade;
}
}`
答卷類(lèi)與上次作業(yè)相比變化較大。增加了學(xué)生學(xué)號(hào)與答案順序的屬性,答案順序?yàn)锳rrayList。答案順序?qū)傩允菫榱诉m應(yīng)改變的要求。
`class AnswerPaper {
private int _NoPaper;//答卷編號(hào)
private HashMap<Integer,String> Answers;//key為答卷的試卷題目順序號(hào),value為答案 // 答案的數(shù)組
private int AnswerStuID;
private ArrayList
public AnswerPaper(int _NoPaper) {
this._NoPaper = _NoPaper;
Answers = new HashMap<>(); // 初始化Answers
AnswerOrder = new ArrayList<>();
}
public void setAnswer(int NO,String Answer) {
Answers.put(NO,Answer);
}
public int get_NoPaper() {
return _NoPaper;
}
public void set_NoPaper(int _NoPaper) {
this._NoPaper = _NoPaper;
}
public HashMap<Integer, String> getAnswers() {
return Answers;
}
public void setAnswers(int NO,String answers) {
Answers.put(NO,answers);
}
public int getAnswerStuID() {
return AnswerStuID;
}
public void setAnswerStuID(int answerStuID) {
AnswerStuID = answerStuID;
}
public ArrayList<Integer> getAnswerOrder() {
return AnswerOrder;
}
public void AnswerOrderAdd(int NO) {
AnswerOrder.add(NO);
}
}`
針對(duì)學(xué)生信息,新增學(xué)生類(lèi)。包含學(xué)生學(xué)號(hào)與學(xué)生姓名兩個(gè)屬性。只有基本的存取方法。
`class student {
private int studentID;
private String name;
public student(int studentID, String name) {
this.studentID = studentID;
this.name = name;
}
public student() {
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}`
針對(duì)刪除題目信息,新增刪除題目類(lèi)。因?yàn)楸粍h除題目在后續(xù)也需要輸出相關(guān)的題目信息,不能直接將其刪除,使用新增類(lèi)來(lái)存儲(chǔ)信息。刪除題目信息類(lèi)只包含被刪除題目的題號(hào)一個(gè)屬性和基本的存取方法。
`class exerciseBeDeleted {
int delNO;
public exerciseBeDeleted(int delNO) {
this.delNO = delNO;
}
public int getDelNO() {
return delNO;
}
public void setDelNO(int delNO) {
this.delNO = delNO;
}
}`
考慮到題目需要判斷輸入信息是否有效,新增判斷信息是否有效類(lèi)。包含所需判斷的信息一個(gè)屬性和各種輸入方法有效性判斷的方法。
`class judgevalid {
private String input;
public judgevalid(String input) {
this.input = input;
}
public String getInput() {
return input;
}
public boolean exerciseValid() {
String regex = "^#N:\\d+ #Q:.* #A:.*$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
return matcher.matches();
}
public boolean paperValid() {
String regex = "^#T:\\d+(( \\d+-\\d+)+)$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
return matcher.matches();
}
public boolean studentValid() {
String regex = "^#X:((\\d+) ((\\w+)-(\\d+))+ (\\w+))";//-(\\\\d+) (\\\\w+)(?:-\\\\d+ \\\\w+)*";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
return true;
//return matcher.matches();
}
public boolean answerPaperValid() {
String regex = "^#S:\\d+ \\d+( #A:\\d*-[^\\s]*)*";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
return matcher.matches();
}
public boolean delExeValid() {
String regex = "#D:N-\\d+$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
return matcher.matches();
}
}`
為了符合題目要求,在Main方法中增加以下方法
- 判斷題目是否被刪除的方法。
public static boolean ExeBeDel(int EXENO) { for(int i = 0;i < delEXE.size();i ++) { if(delEXE.get(i).getDelNO() == EXENO) { return true; } } return false; }
- 精確獲得學(xué)生信息在數(shù)組中位置的方法。
public static int AnStuID(int ID,ArrayList<student> Stu) { for(int i = 0;i < Stu.size();i ++) { if(Stu.get(i).getStudentID() == ID) { return i; } } return -1; }
在Main方法中增加了存儲(chǔ)學(xué)生實(shí)例的studentList,為ArrayList和存儲(chǔ)刪除題目實(shí)例的delEXE,為ArrayList
//學(xué)生數(shù)組 static ArrayList<student>studentList = new ArrayList<>(); //刪除的題目類(lèi) static ArrayList<exerciseBeDeleted> delEXE = new ArrayList<>();//被刪除的題目的數(shù)組

3)設(shè)計(jì)分析
- 本次作業(yè)在上次作業(yè)延用的基礎(chǔ)上再拓展。
- 在Main類(lèi)里設(shè)計(jì)方法,使邏輯更清晰。
踩坑心得
- 在第一次作業(yè)中,程序的結(jié)構(gòu)設(shè)計(jì)較差,程序只適用于當(dāng)前作業(yè),導(dǎo)致后續(xù)作業(yè)需要重新設(shè)計(jì),造成巨大麻煩。日后的程序設(shè)計(jì)需要先設(shè)計(jì)好結(jié)構(gòu)。
- 在第一次作業(yè)中沒(méi)有對(duì)類(lèi)的屬性進(jìn)行封裝。日后程序設(shè)計(jì)要考慮封裝性。
- 在第二次和第三次作業(yè)中數(shù)據(jù)的獲取調(diào)用太多方法,顯得過(guò)于冗長(zhǎng)難以辨別。日后可以通過(guò)設(shè)計(jì)方法來(lái)統(tǒng)一進(jìn)行部分?jǐn)?shù)據(jù)的獲取。
for(int j = 0; j < PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().size(); j ++) { //j小于對(duì)應(yīng)答卷的題目數(shù)時(shí) if(answerPaper.get(i).getAnswers().size() < j + 1) { System.out.println("answer is null"); } else { System.out.printf("%s~%s~%s\n",exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(j)).getContent(),answerPaper.get(i).getAnswers().get(j),exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(j)).judge(answerPaper.get(i).getAnswers().get(j))); } }//答卷的試卷號(hào)匹配題目號(hào),題目號(hào)匹配題目和答案
改進(jìn)建議
1. 部分重復(fù)冗長(zhǎng)的方法調(diào)用,嘗試編寫(xiě)方法解決。
如以下部分可以設(shè)計(jì)方法獲取需要的值
for(int j = 0; j < PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().size(); j ++) { //j小于對(duì)應(yīng)答卷的題目數(shù)時(shí) if(answerPaper.get(i).getAnswers().size() < j + 1) { System.out.println("answer is null"); } else { System.out.printf("%s~%s~%s\n",exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(j)).getContent(),answerPaper.get(i).getAnswers().get(j),exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(j)).judge(answerPaper.get(i).getAnswers().get(j))); } }//答卷的試卷號(hào)匹配題目號(hào),題目號(hào)匹配題目和答案
2. 將部分內(nèi)容寫(xiě)成方法避面主函數(shù)過(guò)于臃腫。
如main里的輸入存儲(chǔ)可以單獨(dú)寫(xiě)成方法。
`String Str = "";
while (sc.hasNextLine()) {
Str = sc.nextLine();
if(Str.equals("end")) {
break;
}
//題目信息的輸入
if(Str.contains("#N")){
judgevalid Judge = new judgevalid(Str);
if(Judge.exerciseValid()) {
String[] parts = Str.split("#N:| #Q:| #A:");
exercise EXE = new exercise(Integer.parseInt(parts[1]), parts[2], parts[3]);
exerciseMap.put(Integer.parseInt(parts[1]), EXE);
} else {
System.out.printf("wrong format:%s\n",Str);
}
//試卷信息的輸入
} else if (Str.contains(("#T"))) {
judgevalid Judge = new judgevalid(Str);
if(Judge.paperValid()) {
String[] parts = Str.split("#T:|-| ");
paper PAPER = new paper(Integer.parseInt(parts[1]));
for (int i = 2; i < parts.length; i = i + 2) {
PAPER.setExerciseAndGrade(Integer.parseInt(parts[i]), Integer.parseInt(parts[i + 1]));
PAPER.getEXES().add(Integer.parseInt(parts[i]));
}
PaperMap.put(Integer.parseInt(parts[1]), PAPER);
if (!PaperSum.contains(Integer.parseInt(parts[1]))) {
PaperSum.add(Integer.parseInt(parts[1]));
}
} else {
System.out.printf("wrong format:%s\n",Str);
}
//答卷信息的輸入
} else if(Str.contains("#S")) {
judgevalid Judge = new judgevalid(Str);
if(Judge.answerPaperValid()) {
String[] parts = Str.split("#S:| #A:| |-");
AnswerPaper Anpaper = new AnswerPaper(Integer.parseInt(parts[1]));
Anpaper.setAnswerStuID(Integer.parseInt(parts[2]));
for (int i = 3; i < parts.length - 1; i = i + 2) {
Anpaper.setAnswer(Integer.parseInt(parts[i]),parts[i + 1]);
Anpaper.AnswerOrderAdd(Integer.parseInt(parts[i]));
}
answerPaper.add(Anpaper);
} else {
System.out.printf("wrong format:%s\n",Str);
}
//學(xué)生信息的輸入
} else if (Str.contains("#X")) {
judgevalid Judge = new judgevalid(Str);
if(Judge.studentValid()) {
String[] parts = Str.split("#X:| |-");
for(int i = 1;i < parts.length - 1;i = i + 2) {
student newStudnt = new student(Integer.parseInt(parts[i]),parts[i + 1]);
studentList.add(newStudnt);
}
} else {
System.out.printf("wrong format:%s\n",Str);
}
//刪除題目信息的輸入
} else if (Str.contains("#D")) {
judgevalid Judge = new judgevalid(Str);
if(Judge.delExeValid()) {
//String[]
String[] parts = Str.split("-");
exerciseBeDeleted delexe = new exerciseBeDeleted(Integer.parseInt(parts[1]));
delEXE.add(delexe);
}
}
}`
3. 保證完成題目要求的同時(shí)避免重復(fù)代碼。
如輸出時(shí)為了保證輸出次序而使用了重復(fù)代碼
for(int j = 0; j < PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().size(); j ++) { //j小于對(duì)應(yīng)答卷的題目數(shù)時(shí) if (answerPaper.get(i).getAnswers().size() < j + 1) { System.out.println("answer is null"); } else if (!exerciseMap.containsKey(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(j))) { System.out.printf("non-existent question~0\n"); } else if (ExeBeDel(exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(answerPaper.get(i).getAnswerOrder().get(j) - 1)).getNO())) { //System.out.printf("the question %d invalid~0\n",exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(answerPaper.get(i).getAnswerOrder().get(j) - 1)).getNO()); } else { String exeToprint = exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(answerPaper.get(i).getAnswerOrder().get(j) - 1)).getContent(); String answerToprint = answerPaper.get(i).getAnswers().get(answerPaper.get(i).getAnswerOrder().get(j)); boolean judgeToprint = exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(answerPaper.get(i).getAnswerOrder().get(j) - 1)).judge(answerPaper.get(i).getAnswers().get(answerPaper.get(i).getAnswerOrder().get(j))); System.out.printf("%s~%s~%s\n",exeToprint,answerToprint,judgeToprint); } } for(int j = 0; j < PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().size(); j ++) { if (answerPaper.get(i).getAnswers().size() < j + 1) { //System.out.println("answer is null"); } else if (!exerciseMap.containsKey(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(j))) { //System.out.printf("non-existent question~0\n"); } else if (ExeBeDel(exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(answerPaper.get(i).getAnswerOrder().get(j) - 1)).getNO())) { System.out.printf("the question %d invalid~0\n",exerciseMap.get(PaperMap.get(answerPaper.get(i).get_NoPaper()).getEXES().get(answerPaper.get(i).getAnswerOrder().get(j) - 1)).getNO()); } }
浙公網(wǎng)安備 33010602011771號(hào)