- PTA三次大作業
- 前言
- 關於難度和題目量
- 關於知識點
- 設計與分析
- 第一次大作業
- 題目
- 我的程式碼
- 分析報告
- 第二次大作業
- 題目
- 我的程式碼
- 分析報告
- 第三次大作業
- 題目
- 我的程式碼
- 分析報告
- 第一次大作業
- 採坑心得
- 改進建議
- 總結
- 前言
PTA三次大作業
前言
關於難度和題目量
前三次大作業難度屬於偏難水平,題目量也在可承受範圍內
關於知識點
在這三次大作業中主要考查了對Java物件導向程式設計思想建立,還有類的定義——如何去設定一個類的屬性和方法,還有類與類之間的關係,涉及的知識點有ArrayList的基本用法,還有HashMap的基本用法——透過索引快速找到Value,在資料處理方面使用了正規表示式來限制String,以此在這段時間內我去學習了正規表示式的基本用法,還有兩個類——Pattern,Matcher,一個類用來決定匹配字串的格式,一個類用來匹配字串,
設計與分析
第一次大作業
題目
設計實現答題程式,模擬一個小型的測試,要求輸入題目資訊和答題資訊,根據輸入題目資訊中的標準答案判斷答題的結果。
輸入格式:
程式輸入資訊分三部分:
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 String q;
private String N;
private String A;
public Question(String a,String b,String c){
q=b;
N=a;
A=c;
}
boolean isAnswer(String a){
return a.equals(A);
}
String getN() {
return N;
}
String getA() {
return A;
}
String getq(){
return q;
}
}
class Paper{
private int num=0;
private Question[]arr=new Question[100];
ParseInput input=new ParseInput();
void add(String str){
arr[num]=input.questionMatching(str);
num++;
}
Paper getpaper(){
return this;
}
void sort(){
for(int i=0;i< num;i++){
for(int j=0;j< num-1-i;j++){
if(Integer.parseInt(arr[j].getN())>Integer.parseInt(arr[j+1].getN())){
Question temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
Question[] getarr(){
return arr;
}
}
class AnswerPaper{
private Paper paper=new Paper();
private boolean[]is=new boolean[100];
private String []arr=new String[100];
private int num=0;
void Setpaper(Paper a){
this.paper=a;
}
ParseInput input=new ParseInput();
void add(String str){
Question[]arr1= paper.getarr();
arr[num]=input.answerMatching(str);
is[num]=arr[num].equals(arr1[num].getA());
num++;
}
void show(){
Question[]arr1= paper.getarr();
for(int i=0;i<num;i++){
System.out.println(arr1[i].getq()+"~"+arr[i]);
}
for(int i=0;i<num;i++){
System.out.print(is[i]);
if(i!=num-1){
System.out.print(" ");
}
}
}
}
class ParseInput{
Question questionMatching(String s_question){
String regex="#N:|#Q:|#A:";
String []arr=s_question.split(regex);
return new Question(arr[1].trim(),arr[2].trim(),arr[3].trim());
}
String answerMatching(String s_answer){
return s_answer.replaceAll("#A:","");
}
}
class Main{
public static void main(String[]args){
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
scanner.nextLine();
Paper paper=new Paper();
for(int i=0;i<n;i++){
paper.add(scanner.nextLine());
}
paper.sort();
AnswerPaper answerPaper=new AnswerPaper();
answerPaper.Setpaper(paper);
for(int i=0;i<n;i++){
String in=scanner.next();
if(in.equals("end")){
break;
}
answerPaper.add(in);
}
answerPaper.show();
}
}
分析報告
在Pta第一次大作業中我寫了5個類
分別是paper,AnswerPaper,Question,ParseInput,Main
其中ParseInput用來解析輸入的資料,將輸入的資料全部轉換為對應的物件並儲存起來,paper表示的是試卷類
Question表示的是題目類,AnswerPaper表示的是答卷類
第一次題目相對比較容易,輸入格式比較固定
第二次大作業
題目
設計實現答題程式,模擬一個小型的測試,以下粗體字顯示的是在答題判題程式-1基礎上增補或者修改的內容。
要求輸入題目資訊、試卷資訊和答題資訊,根據輸入題目資訊中的標準答案判斷答題的結果。
輸入格式:
程式輸入資訊分三種,三種資訊可能會打亂順序混合輸入:
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”,參見樣例9。
設計建議:
參考答題判題程式-1,建議增加答題類,類的內容以及類之間的關聯自行設計。
我的程式碼
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
class Question implements Comparable<Question>{
private String q;
private int N;
private String A;
private int score;
@Override
public int compareTo(Question o) {
return this.N-o.getN();
}
public Question(int a, String b, String c){
q=b;
N=a;
A=c;
}
boolean isAnswer(String a){
return a.equals(A);
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
int getN() {
return N;
}
String getA() {
return A;
}
String getq(){
return q;
}
}
class Paper implements Comparable<Paper>{
private int N;
private List<Question>arr;
public int compareTo(Paper a){
return this.N-a.getN();
}
public int getN() {
return N;
}
public void setN(int n) {
N = n;
}
public List<Question> getArr() {
return arr;
}
public void setArr(List<Question> arr) {
this.arr = arr;
}
}
class AnswerPaper implements Comparable<AnswerPaper> {
private int N;
private List<Answer>anarr;
public int getN() {
return N;
}
public List<Answer> getAnarr() {
return anarr;
}
public void setAnarr(List<Answer> anarr) {
this.anarr = anarr;
}
public void setN(int n) {
N = n;
}
@Override
public int compareTo(AnswerPaper o) {
return N-o.getN();
}
}
class Answer implements Comparable<Answer>{
private int N;
private String str;
public String getstr() {
return str;
}
public void setstr(String arr) {
this.str = arr;
}
public void setN(int n) {
N = n;
}
int getN(){
return N;
}
@Override
public int compareTo(Answer o) {
return N-o.getN();
}
}
class ParseInput{
Question questionMatching(String s_question){
String regex="#N:|#Q:|#A:";
String []arr=s_question.split(regex);
return new Question(Integer.parseInt(arr[1].trim()),arr[2].trim(),arr[3].trim());
}
Paper paperMatching(String s, List<Question> questionList) {
String str = s.replaceAll("#T:", "");
str = str.replaceAll("-", " ");
String[] arr = str.split(" ");
Paper paper = new Paper();
paper.setN(Integer.parseInt(arr[0]));
List<Question> questionListForPaper = new ArrayList<>();
for (int i = 1; i < arr.length; i += 2) {
int questionN = Integer.parseInt(arr[i]);
int score = Integer.parseInt(arr[i + 1]);
for (Question originalQuestion : questionList) {
if (originalQuestion.getN() == questionN) {
Question questionForPaper = new Question(originalQuestion.getN(), originalQuestion.getq(), originalQuestion.getA());
questionForPaper.setScore(score);
questionListForPaper.add(questionForPaper);
break;
}
}
}
paper.setArr(questionListForPaper);
return paper;
}
AnswerPaper answerMatching(String s_answer,List<Paper>List){
String s=s_answer.replaceAll("#A:|#S:","");
String []strArr=s.split(" ");
AnswerPaper a=new AnswerPaper();
a.setN(Integer.parseInt(strArr[0]));
List<Answer>answerList=new ArrayList<>();
Paper paper = null;
for(Paper aa:List){
if(aa.getN()==a.getN()){
paper=aa;
}
}
if(paper==null){
return null;
}
int i=1;
for(Question question:paper.getArr()){
if(i<strArr.length){
Answer answer=new Answer();
answer.setN(question.getN());
answer.setstr(strArr[i]);
answerList.add(answer);
}
else{
break;
}
i++;
}
a.setAnarr(answerList);
return a;
}
}
class Main{
public static void main(String[]args){
Scanner scanner=new Scanner(System.in);
String str;
List <Question> questionList=new ArrayList<>();
List<Paper>paperList=new ArrayList<>();
List<AnswerPaper>answerPaperList=new ArrayList<>();
ParseInput parse=new ParseInput();
List<String>a=new ArrayList<>();
List<String>b=new ArrayList<>();
List<String>c=new ArrayList<>();
while(true){
str=scanner.nextLine();
if(str.matches("#N:.+#Q:.+#A:.+")){
a.add(str);
}
else if(str.matches("#T:.+\\d+-\\d+.+")){
b.add(str);
}else if(str.matches("#S:.+")){
c.add(str);
}else if(str.equals("end")){
break;
}
}
for(String s:a){
questionList.add(parse.questionMatching(s));
}
for(String s:b){
paperList.add(parse.paperMatching(s,questionList));
}
int i=0;
for(String s:c){
AnswerPaper aa=parse.answerMatching(s,paperList);
answerPaperList.add(aa);
i++;
}
Collections.sort(paperList);
Collections.sort(answerPaperList);
for(Paper paper:paperList){
int sum=0;
for(Question question:paper.getArr()){
sum+=question.getScore();
}
if(sum!=100){
System.out.println("alert: full score of test paper"+paper.getN()+" is not 100 points");
}
}
for(AnswerPaper answerPaper:answerPaperList){
if(answerPaper==null){
System.out.println("The test paper number does not exist");
continue;
}
List<Integer>integerList=new ArrayList<>();
for(Paper paper:paperList){
if(answerPaper.getN()==paper.getN()){
for(Question question:paper.getArr()){
int flag=0;
for(Answer answer:answerPaper.getAnarr()){
if(question.getN()==answer.getN()){
flag=1;
if(question.getA().equals(answer.getstr())){
System.out.println(question.getq()+"~"+answer.getstr()+"~true");
integerList.add(question.getScore());
}else{
System.out.println(question.getq()+"~"+answer.getstr()+"~false");
integerList.add(0);
}
}
}
if(flag==0){
integerList.add(0);
System.out.println("answer is null");
}
}
}
}
show(integerList);
}
}
static void show(List<Integer> arr){
int sum=0;
String str="";
for(int a:arr){
sum+=a;
str=str+a+" ";
}
str=str.replaceAll(" $","");
str=str+"~"+sum;
System.out.println(str);
}
}
分析報告
Metrics Details For File 'ptatwo.java'
--------------------------------------------------------------------------------------------
Parameter Value
========= =====
Project Directory C:\Users\11813\Desktop\java檔案\
Project Name 2
Checkpoint Name Baseline
File Name ptatwo.java
Lines 276
Statements 181
Percent Branch Statements 17.1
Method Call Statements 70
Percent Lines with Comments 0.0
Classes and Interfaces 6
Methods per Class 4.67
Average Statements per Method 4.64
Line Number of Most Complex Method 184
Name of Most Complex Method Main.main()
Maximum Complexity 22
Line Number of Deepest Block 246
Maximum Block Depth 9+
Average Block Depth 2.43
Average Complexity 2.11
--------------------------------------------------------------------------------------------
Most Complex Methods in 6 Class(es): Complexity, Statements, Max Depth, Calls
Answer.compareTo() 1, 1, 2, 1
Answer.getN() 1, 1, 2, 0
Answer.getstr() 1, 1, 2, 0
Answer.setN() 1, 1, 2, 0
Answer.setstr() 1, 1, 2, 0
AnswerPaper.compareTo() 1, 1, 2, 1
AnswerPaper.getAnarr() 1, 1, 2, 0
AnswerPaper.getN() 1, 1, 2, 0
AnswerPaper.setAnarr() 1, 1, 2, 0
AnswerPaper.setN() 1, 1, 2, 0
Main.main() 22, 56, 9, 39
Main.show() 2, 8, 3, 1
Paper.compareTo() 1, 1, 2, 1
Paper.getArr() 1, 1, 2, 0
Paper.getN() 1, 1, 2, 0
Paper.setArr() 1, 1, 2, 0
Paper.setN() 1, 1, 2, 0
ParseInput.answerMatching() 7, 22, 4, 10
ParseInput.paperMatching() 4, 16, 5, 15
ParseInput.questionMatching() 1, 3, 2, 0
Question.compareTo() 1, 1, 2, 1
Question.getA() 1, 1, 2, 0
Question.getN() 1, 1, 2, 0
Question.getq() 1, 1, 2, 0
Question.getScore() 1, 1, 2, 0
Question.isAnswer() 1, 1, 2, 1
Question.Question() 1, 3, 2, 0
Question.setScore() 1, 1, 2, 0
--------------------------------------------------------------------------------------------
Block Depth Statements
0 10
1 41
2 73
3 27
4 13
5 4
6 3
7 3
8 3
9+ 4
--------------------------------------------------------------------------------------------
不難發現這次程式碼中明顯複雜度很高
去程式碼中找原因:在main函式中有一段程式碼:
for(AnswerPaper answerPaper:answerPaperList){
if(answerPaper==null){
System.out.println("The test paper number does not exist");
continue;
}
List<Integer>integerList=new ArrayList<>();
for(Paper paper:paperList){
if(answerPaper.getN()==paper.getN()){
for(Question question:paper.getArr()){
int flag=0;
for(Answer answer:answerPaper.getAnarr()){
if(question.getN()==answer.getN()){
flag=1;
if(question.getA().equals(answer.getstr())){
System.out.println(question.getq()+"~"+answer.getstr()+"~true");
integerList.add(question.getScore());
}else{
System.out.println(question.getq()+"~"+answer.getstr()+"~false");
integerList.add(0);
}
}
}
if(flag==0){
integerList.add(0);
System.out.println("answer is null");
}
}
}
}
show(integerList);
}
}
這段程式碼有4個for迴圈———歸結原因還是因為程式碼中許多資料類性都採用arraylist的結果,導致for—each迴圈過多,這個情況在第三次程式碼中有改良,我採用Hashmap的結構,直接透過索引來找資料,極大的降低了複雜度,具體步驟在第三次分析報告中在講。
第三次大作業
題目
設計實現答題程式,模擬一個小型的測試,以下粗體字顯示的是在答題判題程式-2基礎上增補或者修改的內容,要求輸入題目資訊、試卷資訊、答題資訊、學生資訊、刪除題目資訊,根據輸入題目資訊中的標準答案判斷答題的結果。
輸入格式:
程式輸入資訊分五種,資訊可能會打亂順序混合輸入。
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、學號引用錯誤提示資訊
如果答卷中的學號資訊不在學生列表中,答案照常輸出,判分時提示錯誤。參見樣例9。
本題暫不考慮出現多張答卷的資訊的情況。
我的程式碼
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class QuestionBase{
private String name;//問題庫名稱
private HashMap<Integer,Question>questionHashMap;
public HashMap<Integer, Question> getQuestionHashMap() {
return questionHashMap;
}
public void setQuestionHashMap(HashMap<Integer, Question> questionHashMap) {
this.questionHashMap = questionHashMap;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class Question{
private int num;// 題號
private String content;//題目內容
private String standardAnswer;// 標準答案
boolean matchingStandardAnswers(String answer){
return answer.equals(standardAnswer);
}
private boolean is_delete;
public boolean isIs_delete() {
return is_delete;
}
public void setIs_delete(boolean is_delete) {
this.is_delete = is_delete;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
}
class QuestionInPaper{
private int score;//分數
private Question question;//問題
private int N;//在試卷中的位置
int judge_markAnswer(String answer){
if(question.matchingStandardAnswers(answer)){
return score;
}else{
return 0;
}
}
public int getN() {
return N;
}
public void setN(int n) {
N = n;
}
int getScore() {
return score;
}
void setScore(int score) {
this.score = score;
}
Question getQuestion() {
return question;
}
void setQuestion(Question question) {
this.question = question;
}
}
class TextPaper{
private int N=-1;//試卷編號
private int questionNum;// 題目數量
private ArrayList<QuestionInPaper>questionInPaperArrayList=null;//根據題目的順序構成的list
private int SumScore=0;
void inputQuestion( QuestionInPaper question){
questionInPaperArrayList.add(question);
}
public int getSumScore() {
return SumScore;
}
public void setSumScore(int sumScore) {
SumScore = sumScore;
}
public void AddQuestion(QuestionInPaper question){
this.questionInPaperArrayList.add(question);
this.SumScore+=question.getScore();
}//在原有的基礎上add問題
public ArrayList<QuestionInPaper> getQuestionInPaperArrayList() {
return questionInPaperArrayList;
}
public void setQuestionInPaperArrayList(ArrayList<QuestionInPaper> questionInPaperArrayList) {
this.questionInPaperArrayList = questionInPaperArrayList;
int sum=0;
for(QuestionInPaper question:questionInPaperArrayList){
sum+=question.getScore();
}
this.SumScore=sum;
}
public int getQuestionNum() {
return questionNum;
}
public void setQuestionNum(int questionNum) {
this.questionNum = questionNum;
}
int getN() {
return N;
}
void setN(int n) {
N = n;
}
}
class Answer{
private String answer;
private int N;//在paper中的位置
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public int getN() {
return N;
}
public void setN(int n) {
N = n;
}
}
class AnswerPaper{
private int N;//答卷編號對應試卷編號
private String StudentNumber;//該答卷中的學生學號
private TextPaper textPaper;//答卷由試卷和答案組成
private HashMap<Integer,String>answer;
private ArrayList<Integer>scoreArr;
public ArrayList<Integer> getScoreArr() {
return scoreArr;
}
public void setScoreArr(ArrayList<Integer> scoreArr) {
this.scoreArr = scoreArr;
}
private int score;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public TextPaper getTextPaper() {
return textPaper;
}
public void setTextPaper(TextPaper textPaper) {
this.textPaper = textPaper;
}
public int getN() {
return N;
}
public void setN(int n) {
N = n;
}
public String getStudentNumber() {
return StudentNumber;
}
public void setStudentNumber(String studentNumber) {
StudentNumber = studentNumber;
}
public HashMap<Integer, String> getAnswer() {
return answer;
}
public void setAnswer(HashMap<Integer, String> answer) {
this.answer = answer;
}
}
class Student{
String ID;
String 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 Parse {
HashMap<Integer, Question> Toquestionhashmap(ArrayList<String> stringArrayList) {
HashMap<Integer, Question> questionHashMap = new HashMap<>();
for (String s : stringArrayList) {
if (s.matches("^#N:\\d+\\s#Q:.+\\s#A:.*")) {
Question question = new Question();
Pattern pattern = Pattern.compile("#N:(\\d)+\\s#Q:(.+)\\s#A:(.*)");
Matcher matcher = pattern.matcher(s);
while (matcher.find()) {
String string = matcher.group(1);
question.setNum(Integer.parseInt(string));
question.setIs_delete(false);
question.setContent(matcher.group(2));
question.setStandardAnswer(matcher.group(3));
}
questionHashMap.put(question.getNum(), question);
}
}
return questionHashMap;
}
HashMap<Integer, Question> DeleteQuestion(HashMap<Integer, Question> questionHashMap, ArrayList<String> stringArrayList) {
for (String s : stringArrayList) {
if (s.matches("#D:N-[1-9]\\d*")) {
s = s.replaceAll("#D:N-", "");
Question question = questionHashMap.get(Integer.parseInt(s));
question.setIs_delete(true);
questionHashMap.replace(Integer.parseInt(s), question);
}
}
return questionHashMap;
}
HashMap<Integer, TextPaper> ToHashPaper(ArrayList<String> stringArrayList, HashMap<Integer, Question> questionHashMap) {
HashMap<Integer,TextPaper>textPaperHashMap=new HashMap<>();
for (String s : stringArrayList) {
TextPaper textPaper = new TextPaper();
if (s.matches("^#T:[1-9]\\d*(\\s[1-9]\\d*-[1-9]\\d*)*")) {
ArrayList<QuestionInPaper> questionInPaperArrayList = new ArrayList<>();
Pattern pattern = Pattern.compile("^#T:([1-9])");
Matcher matcher = pattern.matcher(s);
int n=0;
while (matcher.find()) {
n = Integer.parseInt(matcher.group(1));
}
textPaper.setN(n);
Pattern pattern1 = Pattern.compile("([1-9]\\d*)-([1-9]\\d*)");
Matcher matcher1 = pattern1.matcher(s);
int sum = 0;
int i=1;
while (matcher1.find()) {
String str1 = matcher1.group(1);//qusetionId
String str2 = matcher1.group(2);//feshu
QuestionInPaper questionInPaper = new QuestionInPaper();
if(questionHashMap.get(Integer.parseInt(str1))==null){
questionInPaper.setQuestion(null);
}else{
questionInPaper.setQuestion(questionHashMap.get(Integer.parseInt(str1)));
}
questionInPaper.setScore(Integer.parseInt(str2));
sum += Integer.parseInt(str2);
questionInPaper.setN(i);
i++;
questionInPaperArrayList.add(questionInPaper);
}
textPaper.setQuestionInPaperArrayList(questionInPaperArrayList);
textPaper.setSumScore(sum);
textPaper.setQuestionNum(questionInPaperArrayList.size());
textPaperHashMap.put(textPaper.getN(),textPaper);
}
}
return textPaperHashMap;
}
HashMap<String,Student> ToStudentHashmap(ArrayList<String>stringArrayList){
HashMap<String ,Student>stringStudentHashMap=new HashMap<>();
for(String str:stringArrayList){
if(str.matches("^#X:.+")){
Pattern pattern=Pattern.compile("(\\d{8})\\s([^-]+)");
Matcher matcher=pattern.matcher(str);
while(matcher.find()){
Student student=new Student();
student.setID(matcher.group(1));
student.setName(matcher.group(2));
stringStudentHashMap.put(matcher.group(1),student);
}
}
}
return stringStudentHashMap;
}
ArrayList<AnswerPaper> ToAnswerpaperArraylist(ArrayList<String> stringArrayList,HashMap<Integer,TextPaper> textPaperHashMap){
ArrayList<AnswerPaper>answerPaperArrayList=new ArrayList<>();
for(String str:stringArrayList){
if(str.matches("^#S:[1-9]\\d*\\s\\d{8}.*")){
AnswerPaper answerPaper=new AnswerPaper();
Pattern pattern=Pattern.compile("^#S:([1-9]\\d*)\\s(\\d{8}).*");
Matcher matcher=pattern.matcher(str);
while(matcher.find()){
String str1=matcher.group(1);
String str2=matcher.group(2);
answerPaper.setN(Integer.parseInt(str1));
answerPaper.setTextPaper(textPaperHashMap.get(answerPaper.getN()));
answerPaper.setStudentNumber(str2);
}
Pattern pattern1=Pattern.compile("#A:([1-9]\\d*)-(\\d*)");
Matcher matcher1=pattern1.matcher(str);
HashMap<Integer,String>stringHashMap=new HashMap<>();
while(matcher1.find()){
String str1=matcher1.group(1);
String str2=matcher1.group(2);
stringHashMap.put(Integer.parseInt(str1),str2);
}
answerPaper.setAnswer(stringHashMap);
answerPaperArrayList.add(answerPaper);
}
}
return answerPaperArrayList;
}
ArrayList<TextPaper> TotextPaperArrayList(ArrayList<String> stringArrayList, HashMap<Integer, Question> questionHashMap){
ArrayList<TextPaper>textPaperArrayList=new ArrayList<>();
for (String s : stringArrayList) {
if (s.matches("^#T:[1-9]\\d*(\\s[1-9]\\d*-[1-9]\\d*)*")) {
TextPaper textPaper = new TextPaper();
ArrayList<QuestionInPaper> questionInPaperArrayList = new ArrayList<>();
Pattern pattern = Pattern.compile("^#T:([1-9])");
Matcher matcher = pattern.matcher(s);
int n=0;
while (matcher.find()) {
n = Integer.parseInt(matcher.group(1));
}
textPaper.setN(n);
Pattern pattern1 = Pattern.compile("([1-9]\\d*)-([1-9]\\d*)");
Matcher matcher1 = pattern1.matcher(s);
int sum = 0;
ArrayList<Integer> integers = new ArrayList<>();
while (matcher1.find()) {
String str1 = matcher1.group(1);//qusetionId
String str2 = matcher1.group(2);//feshu
QuestionInPaper questionInPaper = new QuestionInPaper();
questionInPaper.setQuestion(questionHashMap.get(Integer.parseInt(str1)));
questionInPaper.setScore(Integer.parseInt(str2));
sum += Integer.parseInt(str2);
questionInPaperArrayList.add(questionInPaper);
}
textPaper.setQuestionInPaperArrayList(questionInPaperArrayList);
textPaper.setSumScore(sum);
textPaper.setQuestionNum(questionInPaperArrayList.size());
textPaperArrayList.add(textPaper);
}
}
return textPaperArrayList;
}
}
class Show{
void ShowWrongFormat(ArrayList<String>arrayList){
for(String string:arrayList){
if(string.matches("^#N:\\d+\\s#Q:.+\\s#A:.*")){
}else if(string.matches("^#T:[1-9]\\d*(\\s[1-9]\\d*-[1-9]\\d*)*")){
}else if(string.matches("^#X:.+")){
}else if(string.matches("^#S:[1-9]\\d*\\s\\d{8}.*")){
}else if(string.matches("#D:N-[1-9]\\d*")){
}else{
System.out.println("wrong format:"+string);
}
}
}
void ShowTextPaperScore(ArrayList<TextPaper>textPaperArrayList){
for(TextPaper textPaper:textPaperArrayList){
if(textPaper.getSumScore()!=100){
System.out.println("alert: full score of test paper"+textPaper.getN()+" is not 100 points");
}
}
}
AnswerPaper show1(AnswerPaper answerPaper){
int sum=0;
TextPaper textPaper=answerPaper.getTextPaper();
if(textPaper==null){
System.out.println("The test paper number does not exist");
return answerPaper;
}
ArrayList<Integer>arrayList=new ArrayList<>();
HashMap<Integer, String> stringHashMap=answerPaper.getAnswer();
for(QuestionInPaper questionInPaper:textPaper.getQuestionInPaperArrayList()){
if(stringHashMap.get(questionInPaper.getN())==null){
System.out.println("answer is null");
arrayList.add(0);
}else if(questionInPaper.getQuestion()==null){
System.out.println("non-existent question~0");
arrayList.add(0);
}else if(questionInPaper.getQuestion().isIs_delete()){
System.out.println("the question "+questionInPaper.getN()+" invalid~0");
arrayList.add(0);
} else if(questionInPaper.getQuestion().matchingStandardAnswers(stringHashMap.get(questionInPaper.getN()))){
System.out.println(questionInPaper.getQuestion().getContent()+"~"+stringHashMap.get(questionInPaper.getN())+"~"+"true");
sum+=questionInPaper.getScore();
arrayList.add(questionInPaper.getScore());
}else{
System.out.println(questionInPaper.getQuestion().getContent()+"~"+stringHashMap.get(questionInPaper.getN())+"~"+"false");
arrayList.add(0);
}
}
answerPaper.setScoreArr(arrayList);
answerPaper.setScore(sum);
return answerPaper;
}
void show2(AnswerPaper answerPaper,HashMap<String,Student>stringStudentHashMap){
if(answerPaper.getScoreArr()==null){
return ;
}
int n=answerPaper.getScoreArr().size();
if(stringStudentHashMap.get(answerPaper.getStudentNumber())==null){
System.out.println(answerPaper.getStudentNumber()+" not found");
return ;
}
int i=0;
System.out.print(answerPaper.getStudentNumber()+" "+stringStudentHashMap.get(answerPaper.getStudentNumber()).getName()+": ");
for(int j:answerPaper.getScoreArr()){
System.out.print(j);
if(i!=n-1){
System.out.print(" ");
}else{
System.out.print("~");
}
i++;
}
System.out.println(answerPaper.getScore());
}
}
class Main{
static ArrayList<String> input(){
Scanner scanner=new Scanner(System.in);
String str4=null;
ArrayList<String>stringArrayList=new ArrayList<>();
while(true){
str4=scanner.nextLine();
if(str4.equals("end")){
break;
}
stringArrayList.add(str4);
}
return stringArrayList;
}
public static void main(String[]args) {
ArrayList<String> stringArrayList = input();//輸入資料用list的方式儲存
HashMap<Integer, Question> questionHashMap = new HashMap<>();//question.N question
Parse parse = new Parse();
questionHashMap = parse.Toquestionhashmap(stringArrayList);
questionHashMap=parse.DeleteQuestion(questionHashMap,stringArrayList);
HashMap<Integer, TextPaper> textPaperHashMap = parse.ToHashPaper(stringArrayList, questionHashMap);
HashMap<String, Student> stringStudentHashMap = parse.ToStudentHashmap(stringArrayList);
ArrayList<AnswerPaper> answerPaperArrayList = parse.ToAnswerpaperArraylist(stringArrayList, textPaperHashMap);
ArrayList<TextPaper> textPaperArrayList = parse.TotextPaperArrayList(stringArrayList, questionHashMap);
Show show = new Show();
show.ShowWrongFormat(stringArrayList);
show.ShowTextPaperScore(textPaperArrayList);
for (AnswerPaper answerPaper : answerPaperArrayList) {
answerPaper=show.show1(answerPaper);
show.show2(answerPaper, stringStudentHashMap);
}
}
}
分析報告
Metrics Details For File 'ptathree.java'
--------------------------------------------------------------------------------------------
Parameter Value
========= =====
Project Directory C:\Users\11813\Desktop\java檔案\
Project Name 2
Checkpoint Name Baseline
File Name ptathree.java
Lines 512
Statements 347
Percent Branch Statements 14.1
Method Call Statements 156
Percent Lines with Comments 3.9
Classes and Interfaces 10
Methods per Class 6.10
Average Statements per Method 5.11
Line Number of Most Complex Method 403
Name of Most Complex Method Show.show1()
Maximum Complexity 8
Line Number of Deepest Block 305
Maximum Block Depth 6
Average Block Depth 2.46
Average Complexity 1.85
--------------------------------------------------------------------------------------------
Most Complex Methods in 9 Class(es): Complexity, Statements, Max Depth, Calls
Answer.getAnswer() 1, 1, 2, 0
Answer.getN() 1, 1, 2, 0
Answer.setAnswer() 1, 1, 2, 0
Answer.setN() 1, 1, 2, 0
AnswerPaper.getAnswer() 1, 1, 2, 0
AnswerPaper.getN() 1, 1, 2, 0
AnswerPaper.getScore() 1, 1, 2, 0
AnswerPaper.getScoreArr() 1, 1, 2, 0
AnswerPaper.getStudentNumber() 1, 1, 2, 0
AnswerPaper.getTextPaper() 1, 1, 2, 0
AnswerPaper.setAnswer() 1, 1, 2, 0
AnswerPaper.setN() 1, 1, 2, 0
AnswerPaper.setScore() 1, 1, 2, 0
AnswerPaper.setScoreArr() 1, 1, 2, 0
AnswerPaper.setStudentNumber() 1, 1, 2, 0
AnswerPaper.setTextPaper() 1, 1, 2, 0
Main.input() 3, 8, 3, 3
Main.main() 2, 14, 3, 9
Parse.DeleteQuestion() 3, 7, 4, 7
Parse.ToAnswerpaperArraylist() 5, 22, 5, 14
Parse.ToHashPaper() 7, 33, 6, 29
Parse.Toquestionhashmap() 4, 14, 5, 14
Parse.ToStudentHashmap() 4, 11, 5, 9
Parse.TotextPaperArrayList() 5, 28, 5, 26
Question.getContent() 1, 1, 2, 0
Question.getNum() 1, 1, 2, 0
Question.getStandardAnswer() 1, 1, 2, 0
Question.isIs_delete() 1, 1, 2, 0
Question.matchingStandardAnswers() 1, 1, 2, 1
Question.setContent() 1, 1, 2, 0
Question.setIs_delete() 1, 1, 2, 0
Question.setNum() 1, 1, 2, 0
Question.setStandardAnswer() 1, 1, 2, 0
QuestionBase.getName() 1, 1, 2, 0
QuestionBase.getQuestionHashMap() 1, 1, 2, 0
QuestionBase.setName() 1, 1, 2, 0
QuestionBase.setQuestionHashMap() 1, 1, 2, 0
Show.show1() 8, 27, 4, 23
Show.show2() 6, 16, 4, 10
Show.ShowTextPaperScore() 3, 3, 4, 2
Show.ShowWrongFormat() 8, 8, 4, 6
Student.getID() 1, 1, 2, 0
Student.getName() 1, 1, 2, 0
Student.setID() 1, 1, 2, 0
Student.setName() 1, 1, 2, 0
TextPaper.AddQuestion() 1, 2, 2, 1
TextPaper.getN() 1, 1, 2, 0
TextPaper.getQuestionInPaperArrayList() 1, 1, 2, 0
TextPaper.getQuestionNum() 1, 1, 2, 0
TextPaper.getSumScore() 1, 1, 2, 0
TextPaper.inputQuestion() 1, 1, 2, 1
TextPaper.setN() 1, 1, 2, 0
TextPaper.setQuestionInPaperArrayList() 2, 5, 3, 0
TextPaper.setQuestionNum() 1, 1, 2, 0
TextPaper.setSumScore() 1, 1, 2, 0
--------------------------------------------------------------------------------------------
Block Depth Statements
0 22
1 84
2 101
3 34
4 68
5 36
6 2
7 0
8 0
9+ 0
--------------------------------------------------------------------------------------------
在這裡我們可以明顯的觀察到程式碼複雜度的下降,在這裡講下我的設計思路
- 問題庫:包括QuestionBase、Question、QuestionInPaper和TextPaper等類。QuestionBase類表示問題庫的基本資訊,Question類表示具體的問題,QuestionInPaper類表示試卷中的問題,TextPaper類表示試卷的基本資訊。
- 答卷:包括Answer、AnswerPaper和Student等類。Answer類表示學生的答案,AnswerPaper類表示學生的答卷,Student類表示學生的基本資訊。
- 解析:包括Parse和Show等類。Parse類用於將輸入的字串解析為試卷、問題和答案等資訊,Show類用於顯示解析結果和學生答卷的得分情況。
- 主函式:在Main類中,透過呼叫Parse類的各種方法,將使用者輸入的字串轉換為系統中的各種物件,並透過Show類顯示最終結果。
輸入:#N:2 #Q:2+2= #A:4
#N:1 #Q:1+1= #A:2
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:2-4 #A:1-5
#D:N-2
end
先儲存在StringArraylist中
在透過questionHashMap=parse.DeleteQuestion(questionHashMap,stringArrayList)
得到questionHashMap
在透過HashMap<Integer, TextPaper> textPaperHashMap = parse.ToHashPaper(stringArrayList, questionHashMap);
得到textPaperHashMap
在透過ArrayList
得到answerPaperArrayList
在透過:ArrayList
得到 textPaperArrayList
到這裡資料處理的差不多了
show.ShowWrongFormat(stringArrayList);
show.ShowTextPaperScore(textPaperArrayList);
for (AnswerPaper answerPaper : answerPaperArrayList) {
answerPaper=show.show1(answerPaper);
show.show2(answerPaper, stringStudentHashMap);
}
接下來就是建立一個類show
並且呼叫show的方法來對資料進行output
在這裡雖然題目中說明了單一試卷,但我卻是用Answerpaperlist來儲存資料
方便以後擴張
採坑心得
在我的程式碼沒有完善前的大多數報錯基本都是空指標造成的
例如這段程式碼
void show2(AnswerPaper answerPaper,HashMap<String,Student>stringStudentHashMap){
if(answerPaper.getScoreArr()==null){
return ;
}
int n=answerPaper.getScoreArr().size();
if(stringStudentHashMap.get(answerPaper.getStudentNumber())==null){
System.out.println(answerPaper.getStudentNumber()+" not found");
return ;
}
int i=0;
System.out.print(answerPaper.getStudentNumber()+" "+stringStudentHashMap.get(answerPaper.getStudentNumber()).getName()+": ");
for(int j:answerPaper.getScoreArr()){
System.out.print(j);
if(i!=n-1){
System.out.print(" ");
}else{
System.out.print("~");
}
i++;
}
System.out.println(answerPaper.getScore());
}
在之前我沒有加這個
if(answerPaper.getScoreArr()==null){
return ;
}
當answerPaper.getScoreArr()==null時
for(int j:answerPaper.getScoreArr())
將會遇到空指標
然後報錯
改進建議
為了方便以後擴張,我們在儲存資料時可以使用arraylist
在以後問題變多了以後,我們可以加一個試題庫
多張試卷多張答卷多次輸出
可以設定多選題
類與類之間的關聯要小,低耦合
總結
學會了ArrayList的基本用法,還有HashMap的基本用法——透過索引快速找到Value,在資料處理方面使用了正規表示式來限制String,以此在這段時間內我去學習了正規表示式的基本用法,還有兩個類——Pattern,Matcher,一個類用來決定匹配字串的格式,一個類用來匹配字串,在此期間我感覺自己對除錯程式碼的能力有顯著的提升。
對應類與類之間的設計可能還是有所欠缺,需要在仔細琢磨琢磨,自己還是太菜了,需要多學習,緊跟課程。