關於nchu的pta作業集1-3的總結
一、前言
關於pta的三次作業,出最後一題外都為基礎題,檢驗基本的Java編寫能力,最後一題為主要考察的內容,所佔分數比例也大都在四分之三以上,並且在每一次的題集更新中最後一題都會在上一次的最後一題中新增新的需求並要求我們實現。在最後一題,建議使用正規表示式、Hasmap以及ArrayList,這可以幫助我們更好地的提取關鍵資訊以及儲存關鍵資訊,極大的減少我們的程式碼使用量。
二、內容
- [題目[1]](##第三次題目(簡略版))
- [程式碼[2]](##我的程式碼)
- [設計與分析[3]](##設計與分析)
- [踩坑心得[4]](##踩坑心得)
- [改進建議[5]](##改進建議)
第三次題目(簡略版)
設計實現答題程式,模擬一個小型的測試,以下粗體字顯示的是在答題判題程式-2基礎上增補或者修改的內容,要求輸入題目資訊、試卷資訊、答題資訊、學生資訊、刪除題目資訊,根據輸入題目資訊中的標準答案判斷答題的結果。
輸入格式:
程式輸入資訊分五種,資訊可能會打亂順序混合輸入。
1、題目資訊
2、試卷資訊
3、學生資訊
4、答卷資訊
5、刪除題目資訊
輸出格式:
1、試卷總分警示
該部分僅當一張試卷的總分分值不等於100分時作提示之用,試卷依然屬於正常試卷,可用於後面的答題。如果總分等於100 分,該部分忽略,不輸出。
2、答卷資訊
一行為一道題的答題資訊,根據試卷的題目的數量輸出多行資料。
3、判分資訊
判分資訊為一行資料,是一條答題記錄所對應試卷的每道小題的計分以及總分,計分輸出的先後順序與題目題號相對應。
4、被刪除的題目提示資訊
當某題目被試卷引用,同時被刪除時,答案中輸出提示資訊。樣例見第5種輸入資訊“刪除題目資訊”。
5、題目引用錯誤提示資訊
試卷錯誤地引用了一道不存在題號的試題,在輸出學生答案時,提示”non-existent question~”加答案。
6、格式錯誤提示資訊
輸入資訊只要不符合格式要求,均輸出”wrong format:”+資訊內容。
7、試卷號引用錯誤提示輸出
如果答卷資訊中試卷的編號找不到,則輸出”the test paper number does not exist”,答卷中的答案不用輸出。
8、學號引用錯誤提示資訊
如果答卷中的學號資訊不在學生列表中,答案照常輸出,判分時提示錯誤。
本題暫不考慮出現多張答卷的資訊的情況。
我的程式碼
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static Scanner input=new Scanner(System.in);
public static void main(String[] args) {
String strreg1="#N:(\\d*) #Q:(\\S*) #A:(\\d*)";
Pattern pattern1=Pattern.compile(strreg1);
Map<String, Question> questions=new HashMap<String, Question>();
ArrayList<Paper> papers=new ArrayList<Paper>();
ArrayList<Student> students=new ArrayList<Student>();
ArrayList<StudentAnswer> studentAnswers=new ArrayList<StudentAnswer>();//學生答卷
ArrayList<Delete> deletion=new ArrayList<Delete>();
//讀取內容資訊*****
String str=new String();
str=input.nextLine();
while(!str.contains("end")) {
if(Pattern.matches("#N:\\d* #Q:\\S* #A:\\d*",str)) {
Matcher matcher1=pattern1.matcher(str);
if(matcher1.find()) {
Question q=new Question(matcher1.group(1),matcher1.group(2),matcher1.group(3));
questions.put(matcher1.group(1), q);
}
}else if(Pattern.matches("#T:\\d*( \\d*-\\d*)+",str)) {
Paper p=new Paper();
String strreg_2="#T:(\\d*)";
Pattern pattern_2=Pattern.compile(strreg_2);
Matcher matcher_2=pattern_2.matcher(str);
if(matcher_2.find()) {
p.setPaperId(matcher_2.group(1));
}
String strreg2="(\\d*)-(\\d*)";
Pattern pattern2=Pattern.compile(strreg2);
Matcher matcher2=pattern2.matcher(str);
while(matcher2.find()) {
p.addQuestionIds(matcher2.group(1));
p.putQuestionScores(matcher2.group(1), matcher2.group(2));
}
papers.add(p);
}else if(Pattern.matches("#X:\\d* \\S[^-]*(-\\d* \\S[^-]*)*",str)) {
Student s=new Student();
String strreg3="(\\d*) (\\S[^-]*)";
Pattern pattern3=Pattern.compile(strreg3);
Matcher matcher3=pattern3.matcher(str);
if(matcher3.find()) {
s.setId(matcher3.group(1));
s.setName(matcher3.group(2));
students.add(s);
}
}else if(Pattern.matches("#S:\\d* \\d*( #A:\\d*-\\d*)+",str)) {
StudentAnswer sw=new StudentAnswer();
Pattern pattern4=Pattern.compile("#S:(\\d*) (\\d*)");
Pattern pattern5=Pattern.compile("#A:(\\d*)-(\\d*)");
Matcher matcher4=pattern4.matcher(str);
if(matcher4.find()) {
sw.setId(matcher4.group(1));
sw.setStudentId(matcher4.group(2));
}
Matcher matcher5=pattern5.matcher(str);
while(matcher5.find()) {
sw.putAnswers(matcher5.group(1), matcher5.group(2));
}
studentAnswers.add(sw);
}else if(Pattern.matches("#D:N-(\\d*)",str)) {
Delete de=new Delete();
Pattern pattern6=Pattern.compile("#D:N-(\\d*)");
Matcher matcher6=pattern6.matcher(str);
if(matcher6.find()) {
de.setQuestionId(matcher6.group(1));
}
deletion.add(de);
}else {
System.out.println("wrong format:"+str);
}
str=input.nextLine();
}
//刪除題目資訊******
for(int i=0;i<deletion.size();i++) {
for(int j=0;j<papers.size();j++) {
papers.get(j).deleteQuestion(deletion.get(i).getQuestionId());
}
}
//判斷試卷分值是否大於等於100*****
for(int i=0;i<papers.size();i++) {
if(papers.get(i).getAllScore()<100) {
System.out.println("alert: full score of test paper"+papers.get(i).getPaperId()+" is not 100 points");
}
}
//答卷資訊***************************
for(int i=0;i<studentAnswers.size();i++) {
for(int pn=0;pn<papers.size();pn++) {//遍歷答卷,找到與學生答卷一樣id的答卷
Set<String> saKey=studentAnswers.get(i).getAnswers().keySet();
for(String key:saKey){//遍歷學生答卷題目及答案
for(String j:questions.keySet()) {//遍歷問題找到對應題目,並匹配答案
if(key.equals(questions.get(j).getId())) {
if(studentAnswers.get(i).getAnswers(key).equals(questions.get(j).getAnwser())) {//判斷答案正確
studentAnswers.get(i).putPoints(key, papers.get(pn).getSingleScore(key));//答案正確賦值
}else {
studentAnswers.get(i).putPoints(key, "0");//答案錯誤,0分
}
}
}
}
}
}
////////題目引用錯誤提示資訊*******************
for(int i=0;i<studentAnswers.size();i++) {
int flag=-1;
for(int j=0;j<papers.size();j++) {
if(studentAnswers.get(i).getId().equals(papers.get(j).getPaperId())) {
flag=j;
}
}
if(flag!=-1) {
studentAnswers.get(i).printEachAnswer(questions,papers.get(flag));
for(int j=0;j<students.size();j++) {
if(studentAnswers.get(i).getStudentId().equals(students.get(j).getId())) {
studentAnswers.get(i).printPoints(students.get(j).getName());
}
}
}else {
System.out.println("The test paper number does not exist");
}
}
}
}
class StudentAnswer {
private String id;
private String studentId;
private Map<String, String> answers=new HashMap<String, String>();
private Map<String, String> points=new HashMap<String, String>();
public StudentAnswer() {
super();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getStudentId() {
return studentId;
}
public void setStudentId(String studentId) {
this.studentId = studentId;
}
public void putAnswers(String id,String as) {
answers.put(id,as);
}
public Map<String, String> getAnswers() {
return answers;
}
public String getAnswers(String id) {
return answers.get(id);
}
public void putPoints(String qId,String point) {
points.put(qId, point);
}
public int getfinalScore() {
int score=0;
for(String key:points.keySet()) {
Integer num=Integer.valueOf(points.get(key));
score+=num;
}
return score;
}
public void printPoints(String name) {
Map<String, String> pstree=new TreeMap<String, String>(points);
System.out.printf("%s %s:",studentId,name);
for(String key:pstree.keySet()) {
System.out.printf(" %s",pstree.get(key));
}
System.out.printf("~%d\n",getfinalScore());
}
public void printEachAnswer(Map<String, Question> questions,Paper ThisPaper) {
Map<String, String> pstree=new TreeMap<String, String>(points);
for(String key:pstree.keySet()) {
if(ThisPaper.getSingleScore(key).equals("0")) {
System.out.println("the question "+key+" invalid~0");
}else {
if(points.get(key).equals("0")) {
System.out.println(questions.get(key).getTitle()+"~"+answers.get(key)+"~false");
}else {
System.out.println(questions.get(key).getTitle()+"~"+answers.get(key)+"~true");
}
}
}
}
}
class Student {
private String id;
private String name;
public Student() {
}
public Student(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Question {
private String id;
private String title;
private String answer;
public Question() {
super();
}
public Question(String id, String title, String anwser) {
super();
this.id = id;
this.title = title;
this.answer = anwser;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAnwser() {
return answer;
}
public void setAnwser(String anwser) {
this.answer = anwser;
}
}
class Paper {
private String paperId;
private ArrayList<String> questionIds=new ArrayList<String>();
private Map<String, String> questionScores=new HashMap<String, String>();
public Paper() {
super();
}
public String getPaperId() {
return paperId;
}
public void setPaperId(String paperId) {
this.paperId = paperId;
}
public ArrayList<String> getQuestionIds() {
return questionIds;
}
public void setQuestionIds(ArrayList<String> questionIds) {
this.questionIds = questionIds;
}
public void addQuestionIds(String id) {
questionIds.add(id);
}
public void putQuestionScores(String id,String score) {
questionScores.put(id, score);
}
public Map<String,String> getQuestionScores(){
return questionScores;
}
public int getAllScore() {
int score=0;
Set<String> keys=questionScores.keySet();
for(String key:keys) {
Integer num=Integer.valueOf(questionScores.get(key));
score+=num;
}
return score;
}
public String getSingleScore(String qId) {
return questionScores.get(qId);
}
public void deleteQuestion(String qId) {
if(questionScores.containsKey(qId)) {
questionScores.put(qId, "0");
}
}
}
class Delete {
private String questionId;
public Delete() {
}
public Delete(String questionId) {
super();
this.questionId = questionId;
}
public String getQuestionId() {
return questionId;
}
public void setQuestionId(String questionId) {
this.questionId = questionId;
}
}
設計與分析
根據題目需求,我設計了五個基本類用於儲存、修改和輸出答卷資訊。
問題類(Question)
id、tittle、answer為問題類的基本資訊。
試卷類(Paper)
paperId、questionIds、questionScores、為試卷類的基本資訊。getAllScore():int是用來判斷試卷是否滿足不低於100分條件的。deleteQuestion(String);void是用來刪除試卷內題目資訊的。
學生類(Student)
id、name為學生類的基本資訊。
答卷類(StudentAnswer)
answers記錄答卷答案,points記錄答卷得分細則。透過printPoints(String,paper):void可以輸出答題得分情況,printEachPoints(Map<String,Question>,Paper):void可以列印出每一題的答題正確與否。
刪除類(Delete)
記錄所要刪除的題目,並對含有該題目的試卷進行處理。
踩坑心得
在寫此次作業的過程中,也是初學習正規表示式的時候,對於正則表達的使用並不是很熟練,使得無法正常從題目中獲取關鍵資訊,這也導致在過許多錯誤格式測試點時無法透過。
同時,初學習得還有Map介面類,在使用其時遍歷是個最主要得問題,因為其不像是使用陣列時或使用連結串列時得遍歷,它是透過鍵值來便利的(鍵值對的遍歷對於初學者來說比較難)。不過,這樣也使得尋找所需要的資訊更加簡單,可以透過試卷id,學生id,問題id直接找到尋找的內容。
ArrayList在初使用時我經常會搞混遍歷時使用的i,j,k等記錄序號的符號,導致陣列越界程式報錯無法正常進行,不過這種錯誤還是易於發現並及時修正的。
此外,我總是不能有效的實現題目需求,如細節把控問題,當程式碼量到達一定程度時,就很容易出現很簡單的問題,但往往這類問題是最難解決的,所以此時精簡程式碼以及為程式碼註釋就很有必要了,我這三次的程式碼量都不是很精簡,重複使用了很多程式碼,並且註釋不夠詳細,回頭看時也常常出現自己無法立馬想起這一部分程式碼作用。
改進建議
這三次的題目中多次使用了問題類以及幾乎在每一個類中都有“id”這一屬性,在沒有使用繼承和多型時這增加了程式碼的重複性,使程式碼幾乎不具有簡潔性,在下一次題目中將使用使用繼承減少問題類的使用,使程式碼的複用性提高。還有,在這三次的作業中我後兩次都沒有過最後一題的絕大多數測試點,這是我程式設計程式碼的問題,我未能考慮題目刪除、題目未答、題目不存在答案,或題目不存在等問題,在下一次的pta作業中我將在試卷類中新增一個屬性代表問題的這些狀態,這樣1可以使我在輸出時更加方便簡單。除此之外,在提取題目關鍵資訊時我未能處理所有情況,如題目內容中有空格,題目兩端空格未自動刪去,在下一次題目中我將會一一改進。除此之外,最好試著使用介面類以及抽象類,這可以方便我對每一次題目改進時用簡單的方法解決問題。
三、總結
在這三次的pta中,我充分的使用了我所學以及我自學的知識,這在聽講學習後是一個很好的實踐專案,這讓我所學的知識不僅是停留於紙張和大腦二是可以實際運用,這是靈活的學習而不是死讀書。當然我也有不足的地方,在前三次作業中我並沒有花很多時間以及精力去學習,這導致我被其他認真學習的人拉開了極大的差距,在後續的學習中我將改變之前的學習方式,將更多的時間用在專業相關的知識上。算然自學了ArrayList,Map和正規表示式,但都只是淺淺的學習,並未真正能夠充分使用它們的便利和好處,在後續的學習中我將進一步學習他們的原理並使用在作業中。
“日新自強,知行合一”。
題目 ↩︎
程式碼 ↩︎
設計與分析 ↩︎
踩坑心得 ↩︎
改進建議 ↩︎