前言
本次博客針對面向對象程序設計的課程所發(fā)的PTA作業(yè)7,8以及期末考試中的面向對象編程題的分析和總結,重點介紹課程成績統(tǒng)計程序系列題目以及期末考試的編程題。
PTA第七次作業(yè)
在這次作業(yè)中7-1、7-2內容和考點相同,在此我分析一下7-2Hashmap的排序這個問題。
輸入多個學生的成績信息,包括:學號、姓名、成績。
學號是每個學生的唯一識別號,互不相同。
姓名可能會存在重復。
要求:使用HashMap存儲學生信息。
輸入格式:
輸入多個學生的成績信息,每個學生的成績信息格式:學號+英文空格+姓名+英文空格+成績
以“end”為輸入結束標志
輸出格式:
按學號從大到小的順序輸出所有學生信息,每個學生信息的輸出格式:學號+英文空格+姓名+英文空格+成績
輸入樣例:
在這里給出一組輸入。例如:
20201124 張少軍 83
20201136 李四 78
20201118 鄭覺先 80
end
輸出樣例:
在這里給出相應的輸出。例如:
20201136 李四 78
20201124 張少軍 83
20201118 鄭覺先 80
這道題目的考點在于Hashmap容器的使用以及排序函數的使用,我的源代碼如下:


import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); HashMap<String,String> hashMap = new HashMap<String,String>(); while(true) { String str = input.nextLine(); if(str.equals("end")) { break; } String str1[] = str.split(" "); String no = str1[0]; String name = str1[1]; String grade = str1[2]; hashMap.put(no,name+" "+grade); } List<String> studentIds = new ArrayList<>(hashMap.keySet()); // 按學號從大到小排序 Collections.sort(studentIds, (s1, s2) -> Integer.parseInt(s2) - Integer.parseInt(s1)); // 輸出學生信息 for (String studentId : studentIds) { String studentInfo = hashMap.get(studentId); System.out.println(studentId + " " + studentInfo); } } }
?
本次的代碼較短且復雜度很低,在此不贅述其類圖以及圈復雜度分析。
這次作業(yè)中難度較大的是課程成績統(tǒng)計程序-2,下面是這道題目的介紹和分析。
課程成績統(tǒng)計程序-2在第一次的基礎上增加了實驗課,以下加粗字體顯示為本次新增的內容。
某高校課程從性質上分為:必修課、選修課、實驗課,從考核方式上分為:考試、考察、實驗。
考試的總成績由平時成績、期末成績分別乘以權重值得出,比如平時成績權重0.3,期末成績權重0.7,總成績=平時成績*0.3+期末成績*0.7。
考察的總成績直接等于期末成績
實驗的總成績等于課程每次實驗成績的平均分
必修課的考核方式必須為考試,選修課可以選擇考試、考察任一考核方式。實驗課的成績必須為實驗。
1、輸入:
包括課程、課程成績兩類信息。
課程信息包括:課程名稱、課程性質、考核方式(可選,如果性質是必修課,考核方式可以沒有)三個數據項。
課程信息格式:課程名稱+英文空格+課程性質+英文空格+考核方式
課程性質輸入項:必修、選修、實驗
考核方式輸入選項:考試、考察、實驗
考試/考查課程成績信息包括:學號、姓名、課程名稱、平時成績(可選)、期末成績
考試/考查課程信息格式:學號+英文空格+姓名+英文空格+課程名稱+英文空格+平時成績+英文空格+期末成績
實驗課程成績信息包括:學號、姓名、課程名稱、實驗次數、每次成績
實驗次數至少4次,不超過9次
實驗課程信息格式:學號+英文空格+姓名+英文空格+課程名稱+英文空格+實驗次數+英文空格+第一次實驗成績+...+英文空格+最后一次實驗成績
以上信息的相關約束:
1)平時成績和期末成績的權重默認為0.3、0.7
2)成績是整數,不包含小數部分,成績的取值范圍是【0,100】
3)學號由8位數字組成
4)姓名不超過10個字符
5)課程名稱不超過10個字符
6)不特別輸入班級信息,班級號是學號的前6位。
2、輸出:
輸出包含三個部分,包括學生所有課程總成績的平均分、單門課程成績平均分、單門課程總成績平均分、班級所有課程總成績平均分。
為避免誤差,平均分的計算方法為累加所有符合條件的單個成績,最后除以總數。
1)學生課程總成績平均分按學號由低到高排序輸出
格式:學號+英文空格+姓名+英文空格+總成績平均分
如果某個學生沒有任何成績信息,輸出:學號+英文空格+姓名+英文空格+"did not take any exams"
2)單門課程成績平均分分為三個分值:平時成績平均分(可選)、期末考試平均分、總成績平均分,按課程名稱的字符順序輸出
考試/考察課程成績格式:課程名稱+英文空格+平時成績平均分+英文空格+期末考試平均分+英文空格+總成績平均分
實驗課成績格式:課程名稱+英文空格+總成績平均分
如果某門課程沒有任何成績信息,輸出:課程名稱+英文空格+"has no grades yet"
3)班級所有課程總成績平均分按班級由低到高排序輸出
格式:班級號+英文空格+總成績平均分
如果某個班級沒有任何成績信息,輸出:班級名稱+英文空格+ "has no grades yet"
異常情況:
1)如果解析某個成績信息時,課程名稱不在已輸入的課程列表中,輸出:學號+英文空格+姓名+英文空格+":"+課程名稱+英文空格+"does not exist"
2)如果解析某個成績信息時,輸入的成績數量和課程的考核方式不匹配,輸出:學號+英文空格+姓名+英文空格+": access mode mismatch"
以上兩種情況如果同時出現,按第一種情況輸出結果。
3)如果解析某個課程信息時,輸入的課程性質和課程的考核方式不匹配,輸出:課程名稱+" : course type & access mode mismatch"
4)格式錯誤以及其他信息異常如成績超出范圍等,均按格式錯誤處理,輸出"wrong format"
5)若出現重復的課程/成績信息,只保留第一個課程信息,忽略后面輸入的。
信息約束:
1)成績平均分只取整數部分,小數部分丟棄
參考類圖(與第一次相同,其余內容自行補充):
?
輸入樣例1:
在這里給出一組輸入。例如:
java 實驗 實驗
20201103 張三 java 4 70 80 90
end
輸出樣例1:
在這里給出相應的輸出。例如:
20201103 張三 : access mode mismatch
20201103 張三 did not take any exams
java has no grades yet
202011 has no grades yet
輸入樣例2:
在這里給出一組輸入。例如:
java 實驗 實驗
20201103 張三 java 3 70 80 90
end
輸出樣例2:
在這里給出相應的輸出。例如:
wrong format
java has no grades yet
輸入樣例3:
在這里給出一組輸入。例如:
java 必修 實驗
20201103 張三 java 3 70 80 90 100
end
輸出樣例3:
在這里給出相應的輸出。例如:
java : course type & access mode mismatch
wrong format
輸入樣例4:
在這里給出一組輸入。例如:
java 必修 實驗
20201103 張三 java 4 70 80 90 105
end
輸出樣例4:
在這里給出相應的輸出。例如:
java : course type & access mode mismatch
wrong format
?
輸入樣例5:
在這里給出一組輸入。例如:
java 選修 考察
C語言 選修 考察
java實驗 實驗 實驗
編譯原理 必修 考試
20201101 王五 C語言 76
20201216 李四 C語言 78
20201307 張少軍 編譯原理 82 84
20201103 張三 java實驗 4 70 80 90 100
20201118 鄭覺先 java 80
20201328 劉和宇 java 77
20201220 朱重九 java實驗 4 60 60 80 80
20201132 王萍 C語言 40
20201302 李夢涵 C語言 68
20201325 崔瑾 編譯原理 80 84
20201213 黃紅 java 82
20201209 趙仙芝 java 76
end
輸出樣例5:
在這里給出相應的輸出。例如:
20201101 王五 76
20201103 張三 85
20201118 鄭覺先 80
20201132 王萍 40
20201209 趙仙芝 76
20201213 黃紅 82
20201216 李四 78
20201220 朱重九 70
20201302 李夢涵 68
20201307 張少軍 83
20201325 崔瑾 82
20201328 劉和宇 77
C語言 65 65
java 78 78
java實驗 77
編譯原理 81 84 82
202011 70
202012 76
202013 77
這個題目是課程成績統(tǒng)計程序-1的升級,添加了實驗課的部分,修改了一部分輸入輸出以及錯誤的輸出,總體來說相比較第一次改動不大,以下是我的代碼:
1 import java.util.*; 2 import java.text.Collator; 3 class Crouse{ 4 String name; 5 String nature; 6 String fangshi; 7 ArrayList<Integer> pgrade = new ArrayList<>(); 8 ArrayList<Integer> qgrade = new ArrayList<>(); 9 ArrayList<Integer> grade = new ArrayList<>(); 10 public Crouse(String name, String nature, String fangshi) { 11 this.name = name; // 將參數賦值給成員變量 12 this.nature = nature; // 將參數賦值給成員變量 13 this.fangshi = fangshi; // 將參數賦值給成員變量 14 } 15 public int average() 16 { 17 int total=0; 18 for (int i:grade) 19 { 20 total+=i; 21 } 22 return total/grade.size(); 23 } 24 public int average1() 25 { 26 int total=0; 27 for (int i:pgrade) 28 { 29 total+=i; 30 } 31 return total/pgrade.size(); 32 } 33 public int average2() 34 { 35 int total=0; 36 for (int i:qgrade) 37 { 38 total+=i; 39 } 40 return total/qgrade.size(); 41 } 42 43 } 44 class Student { 45 String id; 46 String name; 47 HashMap<String,Integer> crouse; 48 public Student(String id, String name) { 49 this.id = id; // 將參數賦值給成員變量 50 this.name = name; // 將參數賦值給成員變量 51 this.crouse = new HashMap<>(); 52 } 53 public int averagegrade() 54 { 55 int total=0; 56 for (Integer grade:crouse.values()) { 57 total += grade; 58 } 59 return total/ crouse.size(); 60 } 61 } 62 class Class{ 63 String cid; 64 ArrayList<Student> students = new ArrayList<>(); 65 public Class(String cid) 66 { 67 this.cid=cid; 68 } 69 public int average() 70 { 71 int total=0; 72 for (Student s:students) 73 { 74 total+=s.averagegrade(); 75 } 76 return total/students.size(); 77 } 78 } 79 class Holder{ 80 ArrayList<Crouse> clist = new ArrayList<>(); 81 ArrayList<Student> slist = new ArrayList<>(); 82 ArrayList<Class> Clist = new ArrayList<>(); 83 84 public Crouse searth(String name) 85 { 86 int falg =0; 87 int i; 88 for ( i = 0; i < clist.size(); i++) { 89 if(clist.get(i).name.equals(name)) 90 { 91 falg++; 92 break; 93 } 94 } 95 if(falg!=0) 96 { 97 return clist.get(i); 98 } 99 else return null; 100 } 101 } 102 public class Main { 103 public static void main(String[] args) { 104 Scanner input = new Scanner(System.in); 105 Holder holder = new Holder(); 106 while (true) { 107 try { 108 String str = input.nextLine(); 109 if (str.equals("end")) { 110 break; 111 } 112 String[] str1 = str.split(" "); 113 if (str1.length == 3) { 114 if (str1[1].equals("必修")) { 115 if (str1[2].equals("考試")) { 116 String name = str1[0]; 117 String nature = str1[1]; 118 String fangshi = str1[2]; 119 Crouse crouse = null; 120 for (Crouse c:holder.clist) 121 { 122 if(c.name.equals(name)) { 123 crouse = c; 124 break; 125 } 126 } 127 if(crouse==null) { 128 crouse = new Crouse(name, nature, fangshi); 129 holder.clist.add(crouse); 130 } 131 } else { 132 System.out.println(str1[0] + " : course type & access mode mismatch"); 133 } 134 } else if (str1[1].equals("選修")) { 135 if (str1[2].equals("考試")) { 136 String name = str1[0]; 137 String nature = str1[1]; 138 String fangshi = str1[2]; 139 Crouse crouse = null; 140 for (Crouse c:holder.clist) 141 { 142 if(c.name.equals(name)) { 143 crouse = c; 144 break; 145 } 146 } 147 if(crouse==null) { 148 crouse = new Crouse(name, nature, fangshi); 149 holder.clist.add(crouse); 150 } 151 } else if (str1[2].equals("考察")) { 152 String name = str1[0]; 153 String nature = str1[1]; 154 String fangshi = str1[2]; 155 Crouse crouse = null; 156 for (Crouse c:holder.clist) 157 { 158 if(c.name.equals(name)) { 159 crouse = c; 160 break; 161 } 162 } 163 if(crouse==null) { 164 crouse = new Crouse(name, nature, fangshi); 165 holder.clist.add(crouse); 166 } 167 } else { 168 System.out.println(str1[0] + " : course type & access mode mismatch"); 169 } 170 } else if (str1[1].equals("實驗")) { 171 if (str1[2].equals("實驗")) { 172 String name = str1[0]; 173 String nature = str1[1]; 174 String fangshi = str1[2]; 175 Crouse crouse = null; 176 for (Crouse c:holder.clist) 177 { 178 if(c.name.equals(name)) { 179 crouse = c; 180 break; 181 } 182 } 183 if(crouse==null) { 184 crouse = new Crouse(name, nature, fangshi); 185 holder.clist.add(crouse); 186 } 187 } else { 188 System.out.println(str1[0] + " : course type & access mode mismatch"); 189 } 190 } 191 } else if (str1.length == 4)//選修,考察 192 { 193 if (Integer.parseInt(str1[3]) > 0 && Integer.parseInt(str1[3]) < 100) { 194 if (holder.searth(str1[2]) != null) { 195 String stuid = str1[0]; 196 String sname = str1[1]; 197 if (holder.searth(str1[2]).nature.equals("選修")) { 198 Student student = null; 199 for (Student s:holder.slist) 200 { 201 if(s.name.equals(sname)) 202 { 203 student = s; 204 break; 205 } 206 } 207 String cid = stuid.substring(0, 6); 208 Class cla = null; 209 for (Class c : holder.Clist) { 210 if (c.cid.equals(cid)) { 211 cla = c; 212 break; 213 } 214 } 215 if (cla == null) { 216 cla = new Class(cid); 217 holder.Clist.add(cla); 218 } 219 if(student==null) { 220 student = new Student(stuid,sname); 221 student.crouse.put(str1[2], Integer.parseInt(str1[3])); 222 cla.students.add(student); 223 holder.slist.add(student); 224 holder.searth(str1[2]).grade.add(Integer.parseInt(str1[3])); 225 } 226 else { 227 student.crouse.put(str1[2], Integer.parseInt(str1[3])); 228 holder.searth(str1[2]).grade.add(Integer.parseInt(str1[3])); 229 } 230 } else 231 System.out.println(stuid + " " + sname + " " + ": access mode mismatch"); 232 } else 233 System.out.println(str1[0] + " " + str1[1] + " " + ":" + str1[2] + " " + "does not exist"); 234 } else System.out.println("wrong format"); 235 } else if (str1.length == 5)//必修或選修考試 236 { 237 if (holder.searth(str1[2]) != null) { 238 String stuid = str1[0]; 239 String sname = str1[1]; 240 int grade = (int) (Integer.parseInt(str1[3]) * 0.3 + Integer.parseInt(str1[4]) * 0.7); 241 Student student = null; 242 for (Student s:holder.slist) 243 { 244 if(s.name.equals(sname)) 245 { 246 student = s; 247 break; 248 } 249 } 250 251 String cid = stuid.substring(0, 6); 252 Class cla = null; 253 for (Class c : holder.Clist) { 254 if (c.cid.equals(cid)) { 255 cla = c; 256 break; 257 } 258 } 259 if (cla == null) { 260 cla = new Class(cid); 261 holder.Clist.add(cla); 262 } 263 if(student==null) { 264 student = new Student(stuid,sname); 265 student.crouse.put(str1[2], grade); 266 cla.students.add(student); 267 holder.slist.add(student); 268 holder.searth(str1[2]).grade.add(grade); 269 holder.searth(str1[2]).pgrade.add(Integer.parseInt(str1[3])); 270 holder.searth(str1[2]).qgrade.add(Integer.parseInt(str1[4])); 271 } 272 else { 273 student.crouse.put(str1[2], grade); 274 holder.searth(str1[2]).grade.add(grade); 275 holder.searth(str1[2]).pgrade.add(Integer.parseInt(str1[3])); 276 holder.searth(str1[2]).qgrade.add(Integer.parseInt(str1[4])); 277 } 278 } else 279 System.out.println(str1[0] + " " + str1[1] + " " + ":" + str1[2] + " " + "does not exist"); 280 } else if (Integer.parseInt(str1[3]) > 3 && Integer.parseInt(str1[3]) < 10)//實驗 281 { 282 int num = Integer.parseInt(str1[3]); 283 int falg = 0; 284 for (int i = 4; i < str1.length; i++) { 285 if (Integer.parseInt(str1[i]) < 0 || Integer.parseInt(str1[i]) > 100) 286 falg++; 287 } 288 if (falg == 0) { 289 if (holder.searth(str1[2]) != null) { 290 String stuid = str1[0]; 291 String sname = str1[1]; 292 int grade = 0; 293 if (str1.length == 4 + num) { 294 for (int i = 4; i < 4 + num; i++) { 295 grade += Integer.parseInt(str1[i]); 296 } 297 grade = grade / 4; 298 Student student = null; 299 for (Student s:holder.slist) 300 { 301 if(s.name.equals(sname)) 302 { 303 student = s; 304 break; 305 } 306 } 307 String cid = stuid.substring(0, 6); 308 Class cla = null; 309 for (Class c : holder.Clist) { 310 if (c.cid.equals(cid)) { 311 cla = c; 312 break; 313 } 314 } 315 if (cla == null) { 316 cla = new Class(cid); 317 holder.Clist.add(cla); 318 } 319 if(student==null) { 320 student = new Student(stuid,sname); 321 student.crouse.put(str1[2], grade); 322 cla.students.add(student); 323 holder.slist.add(student); 324 holder.searth(str1[2]).grade.add(grade); 325 } 326 else { 327 student.crouse.put(str1[2], grade); 328 holder.searth(str1[2]).grade.add(grade); 329 } 330 } else { 331 Student student = new Student(stuid, sname); 332 String cid = stuid.substring(0, 6); 333 Class cla = null; 334 for (Class c : holder.Clist) { 335 if (c.cid.equals(cid)) { 336 cla = c; 337 break; 338 } 339 } 340 if (cla == null) { 341 cla = new Class(cid); 342 holder.Clist.add(cla); 343 } 344 holder.slist.add(student); 345 System.out.println(stuid + " " + sname + " " + ": access mode mismatch"); 346 } 347 } else 348 System.out.println(str1[0] + " " + str1[1] + " " + ":" + str1[2] + " " + "does not exist"); 349 } else System.out.println("wrong format"); 350 } else 351 System.out.println("wrong format"); 352 } 353 catch (NumberFormatException e) 354 { 355 System.out.println("wrong format"); 356 } 357 } 358 359 holder.slist.sort(Comparator.comparing(s -> s.id)); 360 for(Student student:holder.slist) 361 { 362 if(student.crouse.isEmpty()) 363 { 364 System.out.println(student.id+" "+student.name+" "+"did not take any exams"); 365 } 366 else System.out.println(student.id+" "+student.name+" "+student.averagegrade()); 367 } 368 369 Collator collator = Collator.getInstance(); 370 holder.clist.sort(Comparator.comparing(c -> c.name, collator)); 371 for(Crouse crouse:holder.clist) 372 { 373 if(crouse.grade.isEmpty()) 374 { 375 System.out.println(crouse.name+" "+"has no grades yet"); 376 } 377 else if(crouse.nature.equals("選修")&&crouse.fangshi.equals("考察")) 378 System.out.println(crouse.name+" "+crouse.average()+" "+crouse.average()); 379 else if(crouse.nature.equals("選修")&&crouse.fangshi.equals("考試")) 380 System.out.println(crouse.name+" "+crouse.average1()+" "+crouse.average2()+" "+crouse.average()); 381 else if(crouse.nature.equals("必修")) 382 System.out.println(crouse.name+" "+crouse.average1()+" "+crouse.average2()+" "+crouse.average()); 383 else if(crouse.nature.equals("實驗")) 384 System.out.println(crouse.name+" "+crouse.average()); 385 } 386 holder.Clist.sort(Comparator.comparing(c -> c.cid)); 387 for(Class c:holder.Clist) 388 { 389 int falg=0; 390 for (Student s: c.students) 391 { 392 if(s.averagegrade()==0) 393 { 394 falg++; 395 } 396 } 397 if(falg==c.students.size()) 398 { 399 System.out.println(c.cid+" "+ "has no grades yet"); 400 } 401 else 402 System.out.println(c.cid+" "+c.average()); 403 } 404 } 405 }
Crouse
類表示課程,包含課程名稱、課程性質、考核方式以及成績列表。Student
類表示學生,包含學號、姓名和課程成績的映射關系。Class
類表示班級,包含班級號和學生列表。我用了一個holder類儲存課程鏈表、成績鏈表、以及班級鏈表,進而在Main類中通過循環(huán)輸出課程的平均成績、學生的平均成績、班級的平均成績以及對無成績的情況輸出。
該代碼的類圖如下:
?
用source moniter分析圈復雜度情況如下:
從圈復雜度以及代碼深度分析圖可以看出,我的代碼最大復雜性為91,平均復雜度為10.90,根據基維亞特圖可以看出我的代碼復雜度較高,平均運行時間長。
?
PTA第八次作業(yè)
?
課程成績統(tǒng)計程序-3在第二次的基礎上修改了計算總成績的方式,
要求:修改類結構,將成績類的繼承關系改為組合關系,成績信息由課程成績類和分項成績類組成,課程成績類組合分項成績類,分項成績類由成績分值和權重兩個屬性構成。
完成課程成績統(tǒng)計程序-2、3兩次程序后,比較繼承和組合關系的區(qū)別。思考一下哪一種關系運用上更靈活,更能夠適應變更。
題目最后的參考類圖未做修改,大家根據要求自行調整,以下內容加粗字體顯示的內容為本次新增的內容。
某高校課程從性質上分為:必修課、選修課、實驗課,從考核方式上分為:考試、考察、實驗。
考試的總成績由平時成績、期末成績分別乘以權重值得出,比如平時成績權重0.3,期末成績權重0.7,總成績=平時成績*0.3+期末成績*0.7。
考察的總成績直接等于期末成績
實驗的總成績等于課程每次實驗成績乘以權重后累加而得。
課程權重值在錄入課程信息時輸入。(注意:所有分項成績的權重之和應當等于1)
必修課的考核方式必須為考試,選修課可以選擇考試、考察任一考核方式。實驗課的成績必須為實驗。
1、輸入:
包括課程、課程成績兩類信息。
課程信息包括:課程名稱、課程性質、考核方式、分項成績數量、每個分項成績的權重。
考試課信息格式:課程名稱+英文空格+課程性質+英文空格+考核方式+英文空格+平時成績的權重+英文空格+期末成績的權重
考察課信息格式:課程名稱+英文空格+課程性質+英文空格+考核方式
實驗課程信息格式:課程名稱+英文空格+課程性質+英文空格+考核方式+英文空格+分項成績數量n+英文空格+分項成績1的權重+英文空格+。。。+英文空格+分項成績n的權重
實驗次數至少4次,不超過9次
課程性質輸入項:必修、選修、實驗
考核方式輸入選項:考試、考察、實驗
考試/考查課程成績信息包括:學號、姓名、課程名稱、平時成績(可選)、期末成績
考試/考查課程成績信息格式:學號+英文空格+姓名+英文空格+課程名稱+英文空格+平時成績+英文空格+期末成績
實驗課程成績信息包括:學號、姓名、課程名稱、每次成績{在系列-2的基礎上去掉了(實驗次數),實驗次數要和實驗課程信息中輸入的分項成績數量保持一致}
實驗課程信息格式:學號+英文空格+姓名+英文空格+課程名稱+英文空格+第一次實驗成績+...+英文空格+最后一次實驗成績
以上信息的相關約束:
1)成績是整數,不包含小數部分,成績的取值范圍是【0,100】
2)學號由8位數字組成
3)姓名不超過10個字符
4)課程名稱不超過10個字符
5)不特別輸入班級信息,班級號是學號的前6位。
2、輸出:
輸出包含三個部分,包括學生所有課程總成績的平均分、單門課程總成績平均分、班級所有課程總成績平均分。
為避免四舍五入誤差,
計算單個成績時,分項成績乘以權重后要保留小數位,計算總成績時,累加所有分項成績的權重分以后,再去掉小數位。
學生總成績/整個班/課程平均分的計算方法為累加所有符合條件的單個成績,最后除以總數。
1)學生課程總成績平均分按學號由低到高排序輸出
格式:學號+英文空格+姓名+英文空格+總成績平均分
如果某個學生沒有任何成績信息,輸出:學號+英文空格+姓名+英文空格+"did not take any exams"
2)單門課程成績按課程名稱的字符順序輸出
課程成績輸出格式:課程名稱+英文空格+總成績平均分
如果某門課程沒有任何成績信息,輸出:課程名稱+英文空格+"has no grades yet"
3)班級所有課程總成績平均分按班級由低到高排序輸出
格式:班級號+英文空格+總成績平均分
如果某個班級沒有任何成績信息,輸出:班級名稱+英文空格+ "has no grades yet"
異常情況:
1)如果解析某個成績信息時,課程名稱不在已輸入的課程列表中,輸出:學號+英文空格+姓名+英文空格+":"+課程名稱+英文空格+"does not exist"
2)如果解析某個成績信息時,輸入的成績數量和課程的考核方式不匹配,輸出:學號+英文空格+姓名+英文空格+": access mode mismatch"
以上兩種情況如果同時出現,按第一種情況輸出結果。
3)如果解析某個課程信息時,輸入的課程性質和課程的考核方式不匹配,輸出:課程名稱+" : course type & access mode mismatch"
4)格式錯誤以及其他信息異常如成績超出范圍等,均按格式錯誤處理,輸出"wrong format"
5)若出現重復的課程/成績信息,只保留第一個課程信息,忽略后面輸入的。
6)如果解析實驗課程信息時,輸入的分項成績數量值和分項成績權重的個數不匹配,輸出:課程名稱+" : number of scores does not match"
7)如果解析考試課、實驗課時,分項成績權重值的總和不等于1,輸出:課程名稱+" : weight value error"
信息約束:
1)成績平均分只取整數部分,小數部分丟棄
參考類圖(與第一次相同,其余內容自行補充):
輸入樣例1:
在這里給出一組輸入。例如:
java 實驗 實驗 4 0.2 0.3 0.2 0.3
end
輸出樣例1:
在這里給出相應的輸出。例如:
java has no grades yet
輸入樣例2:
在這里給出一組輸入。例如:
java 實驗 實驗 4 0.2 0.3 0.2
end
輸出樣例2:
在這里給出相應的輸出。例如:
java : number of scores does not match
輸入樣例3:
在這里給出一組輸入。例如:
java 實驗 實驗 4 0.2 0.3 0.2 0.1
end
輸出樣例3:
在這里給出相應的輸出。例如:
java : weight value error
輸入樣例4:
在這里給出一組輸入。例如:
java 實驗 實驗 4 0.2 0.3 0.2 0.3
20201116 張三 java 70 80 90 100
end
輸出樣例4:
在這里給出相應的輸出。例如:
20201116 張三 86
java 86
202011 86
輸入樣例5:
在這里給出一組輸入。例如:
java 實驗 實驗 4 0.2 0.3 0.2 0.3
20201116 張三 java 70 80 90 100 80
end
輸出樣例5:
在這里給出相應的輸出。例如:
20201116 張三 : access mode mismatch
20201116 張三 did not take any exams
java has no grades yet
202011 has no grades yet
這道題目是對課程成績統(tǒng)計程序-2的升級,主要添加了實驗課的成績權重部分,將原來的平均模式改為了加權平均算法,并且改成了在課程信息中輸入實驗次數及權重,修改
了一部分輸入輸出以及錯誤的輸出。
我的代碼如下:


1 import java.util.*; 2 import java.text.*; 3 public class Main { 4 public static void main(String[] args) { 5 Scanner scanner = new Scanner(System.in); 6 Input_Format inputFormat = new Input_Format();//輸入 7 Output_Format outputFormat = new Output_Format();//輸出 8 Data_storage data_storage = new Data_storage(); 9 while (inputFormat.isEnd){ 10 String inputLine = scanner.nextLine(); 11 if(inputLine.equals("end")){ 12 inputFormat.isEnd = false; 13 break; 14 } 15 inputFormat.inputProcessing(inputLine,data_storage); 16 } 17 PersonOverride student1 = new PersonOverride(); 18 outputFormat.outputProcessing(data_storage); 19 outputFormat.output_all(data_storage); 20 } 21 } 22 class Calculate_grades { 23 int stu_all_grades(Data_storage data_storage,String num){//單個學生總課程平均分計算 返回一個分數 1) 24 int count =0;//這個學生有幾門課 25 int sum = 0; 26 for (Map.Entry<String, Score> entry : data_storage.stu__st_cour.get(num).gradeMap.entrySet()) { 27 Score value = entry.getValue(); 28 if(Integer.parseInt(value.total_scores)>=0) { 29 count++; 30 sum += Integer.parseInt(value.total_scores); 31 } 32 } 33 if(count!=0) 34 return sum/count; 35 else 36 return -100;//沒有參加任何考試 37 } 38 int[] single_course_grades(Data_storage data_storage,String name){ //2) 課程名 39 int count = 0; 40 int[] aver_grade = new int[3];//0:平時成績 1:期末考試 2:總分平均 41 for (Map.Entry<String, StudentsAll_mes> e : data_storage.stu__st_cour.entrySet()) {//遍歷選課類:num-選課類 42 StudentsAll_mes value = e.getValue(); 43 for (Map.Entry<String, Score> entry : value.gradeMap.entrySet()) {//遍歷選課類:course.name-Score 44 String key1 = entry.getKey(); 45 Score value1 = entry.getValue(); 46 if (key1.equals(name)) { 47 if(Integer.parseInt(value1.total_scores)>=0) {//總分為- 說明算成績無效 48 count++; 49 aver_grade[2] += Integer.parseInt(value1.total_scores); 50 if (value1 instanceof Test_Score) { 51 if (Integer.parseInt(value1.total_scores) >= 0) { 52 aver_grade[0] += Integer.parseInt(((Test_Score) value1).normal_score); 53 aver_grade[1] += Integer.parseInt(((Test_Score) value1).end_score); 54 } 55 } else if (value1 instanceof Inspect_Score){ 56 if (Integer.parseInt(value1.total_scores) >= 0) { 57 aver_grade[0] = -100;//不需要平時成績 58 aver_grade[1] += Integer.parseInt(((Inspect_Score) value1).end_score); 59 } 60 }else if(value1 instanceof Lab_Score){ 61 if(Integer.parseInt(value1.total_scores)>=0){ 62 aver_grade[0] = -100; 63 aver_grade[1] += aver_grade[1] += Integer.parseInt(value1.total_scores); 64 } 65 } 66 } 67 } 68 } 69 } 70 if(count!=0) { 71 for (int i = 0; i < 3; i++) { 72 aver_grade[i] = aver_grade[i] / count; 73 } 74 }else { 75 for (int i = 0; i < 3; i++) { 76 aver_grade[i] = -100; 77 } 78 } 79 return aver_grade; 80 } 81 int Class_grades(Data_storage data_storage,String num){//3) 82 int sum = 0; 83 int count = 0; 84 for (Map.Entry<String, Student> mapEntry : data_storage.classes.get(num).students.entrySet()) {//班級號-Student類 85 Student value = mapEntry.getValue();//遍歷這個班級的所有學生 86 for (Map.Entry<String, StudentsAll_mes> e : data_storage.stu__st_cour.entrySet()) {//stu_num-選課類 87 String key1 = e.getKey();//遍歷學生的選課類 學號 88 StudentsAll_mes value1 = e.getValue(); 89 if (key1.equals(value.num)) {//選課類中 跟輸入的學號一樣 90 for (Map.Entry<String, Score> entry : value1.gradeMap.entrySet()) {//該num所有成績遍歷 91 Score gra = entry.getValue(); 92 if(Integer.parseInt(gra.total_scores)>=0) {//有效才算 93 sum += Integer.parseInt(gra.total_scores); 94 count++; 95 } 96 } 97 } 98 } 99 } 100 if(count!=0) 101 return sum/count; 102 else 103 return -100; 104 } 105 void final_score(Data_storage data_storage,String num){//計算沒門課的成績 學號 106 data_storage.stu__st_cour.get(num).gradeMap.forEach((key,value)->{//學號 成績 107 if(value instanceof Test_Score&&((Test_Score) value).normal_score.matches("\\d+")&&((Test_Score) value).end_score.matches("\\d+")) { 108 double tem = ((Test_Course) data_storage.courses.get(key)).normal_weight*Integer.parseInt(((Test_Score) value).normal_score); 109 double tem1 = ((Test_Course) data_storage.courses.get(key)).end_weight*Integer.parseInt(((Test_Score) value).end_score); 110 value.total_scores = String.valueOf((int)(tem+tem1)); 111 }else if(value instanceof Inspect_Score&&((Inspect_Score) value).end_score.matches("\\d+")){ 112 value.total_scores = ((Inspect_Score) value).end_score; 113 }else if(value instanceof Lab_Score&&((Lab_Score) value).lab_num.matches("\\d+")){ 114 float sum = 0; 115 int i=0; 116 for (Integer score : ((Lab_Score) value).scores) { 117 sum+= score* ((Lab_Course) data_storage.courses.get(key)).weights.get(i); 118 i++; 119 } 120 value.total_scores = String.valueOf((int)sum); 121 } 122 }); 123 } 124 } 125 class PersonOverride { 126 private String name; 127 private int age; 128 private boolean gender; 129 130 public PersonOverride() { 131 this("default", 1, true); 132 } 133 134 public PersonOverride(String name, int age, boolean gender) { 135 this.name = name; 136 this.age = age; 137 this.gender = gender; 138 } 139 140 @Override 141 public String toString() { 142 return name + "-" + age + "-" + gender; 143 } 144 } 145 class Class { 146 String num; 147 TreeMap<String, Student> students = new TreeMap<>(); //班級里的學生 學號 學生 148 Class(String num){ 149 this.num = num; 150 } 151 } 152 class Course { 153 String type; 154 String test_way; 155 String name; 156 Course(String name,String type, String test_way){ 157 this.type = type; 158 this.name = name; 159 this.test_way = test_way; 160 } 161 } 162 class Inspect_Course extends Course{ 163 Inspect_Course(String name, String type, String test_way) { 164 super(name, type, test_way); 165 } 166 } 167 168 class Test_Course extends Course{ 169 double normal_weight; 170 double end_weight; 171 172 Test_Course(String name, String type, String test_way,String normal_weight,String end_weight) { 173 super(name, type, test_way); 174 this.normal_weight = Float.parseFloat(normal_weight); 175 this.end_weight = Float.parseFloat(end_weight); 176 } 177 } 178 class Lab_Course extends Course{ 179 int sub_scores_num; 180 ArrayList<Float> weights = new ArrayList<>(); 181 Lab_Course(String name, String type, String test_way,String line) { 182 super(name, type, test_way); 183 String[] lines = line.split(" "); 184 sub_scores_num = Integer.parseInt(lines[3]); 185 for(int i=4;i<lines.length; i++){ 186 weights.add(Float.parseFloat(lines[i])); 187 } 188 } 189 } 190 class Data_storage { 191 TreeMap<String , Course> courses;//課程 k:課程名 v:課程 192 TreeMap<String, Class> classes = new TreeMap<>();//班級 k:班級號V:班級 193 TreeMap<String, StudentsAll_mes> stu__st_cour;//選課類學生類結合 k:學號 v:選課類 194 InAndOut_put output = new InAndOut_put(); 195 Data_storage(){ 196 //學生和選課類結合 197 stu__st_cour = new TreeMap<>(Data_storage::compare);//重寫排序 198 courses = new TreeMap<>(Data_storage::compare); 199 } 200 201 private static int compare(String o1, String o2) { 202 203 try { 204 Comparator<Object> comparator = Collator.getInstance(Locale.CHINA); 205 if (comparator.compare(o1, o2) < 0) { 206 return -1; 207 } else if (comparator.compare(o1, o2) > 0) { 208 return 1; 209 } 210 } catch (Exception ignored) { 211 } 212 return 0; 213 } 214 215 void setInspectCourses(String name, String type, String test_way){ 216 if(!courses.containsKey(name)) { 217 courses.put(name, new Inspect_Course(name, type, test_way)); 218 } 219 } 220 void setTestCourses(String name, String type, String test_way,String normal_weight, String end_weight){ 221 if(!courses.containsKey(name)) { 222 courses.put(name, new Test_Course(name, type, test_way,normal_weight, end_weight)); 223 } 224 } 225 void setLabCourses(String name, String type, String test_way,String line){ 226 if(!courses.containsKey(name)) { 227 courses.put(name, new Lab_Course(name, type, test_way,line)); 228 } 229 } 230 void setClasses(String num){ 231 if(!classes.containsKey(num)) { 232 classes.put(num, new Class(num)); 233 } 234 } 235 void setStudents(String clas_num, String name, String num){//班級號 姓名 學號 236 if(classes.containsKey(clas_num)){ 237 if(!classes.get(clas_num).students.containsKey(num)) 238 classes.get(clas_num).students.put(num,new Student(name,num)); 239 } 240 } 241 void setStu__st_courAndMap(String num,String course,String normal_score,String end_score){//添加選課類 學生姓名 課程名稱 分數 242 if(!stu__st_cour.containsKey(num)){ 243 stu__st_cour.put(num,new StudentsAll_mes(num,course,normal_score,end_score)); 244 } 245 else{ 246 stu__st_cour.get(num).setGradeMap(course,normal_score,end_score); 247 } 248 } 249 void setStu__st_courAndMap(String num,String course,String end_score){ 250 if(!stu__st_cour.containsKey(num)){ 251 stu__st_cour.put(num,new StudentsAll_mes(num,course,end_score)); 252 } 253 else{ 254 stu__st_cour.get(num).setGradeMap(course,end_score); 255 } 256 } 257 void set_lab_grades(String stu_num,String course,String lab_num,String grades){ 258 ArrayList<Integer> scores = new ArrayList<>(); 259 String[] tem = grades.split(" "); 260 for(int i=3;i<tem.length;i++){ 261 if(tem[i].matches("\\d+")) 262 scores.add(Integer.parseInt(tem[i])); 263 } 264 if(!stu__st_cour.containsKey(stu_num)){ 265 StudentsAll_mes tem_stu_mes = new StudentsAll_mes(); 266 tem_stu_mes.set_lab_stu_mes(stu_num,course,lab_num,scores); 267 stu__st_cour.put(stu_num,tem_stu_mes); 268 }else{ 269 stu__st_cour.get(stu_num).set_lab_gradeMap(course,lab_num,scores); 270 } 271 } 272 } 273 class Input_Format { 274 String regex_c_test = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|選修)\\s考試\\s((0.\\d{1,2})|(1-9?))\\s((0.\\d{1,2})|(1-9?))$"; 275 String regex_c_inspect = "[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s選修\\s考察$"; 276 String regex_c_lab = "^[\\u4e00-\\u9fa5a-zA-Z0-9 ]{1,10}\\s實驗\\s實驗\\s[4-9]\\s((0.\\d{1,2})|(1-9?))(\\s((0.\\d{1,2})|(1-9?))){3,9}$"; 277 String regex_CS = "^\\d{8}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s+[\\u4E00-\\u9FA5A-Za-z0-9]{1,10}\\s*((100)|(\\d{1,2})|(0))?\\s+((100)|(\\d{1,2})|(0))$"; 278 String regex_lab = "^\\d{8}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s[\\u4e00-\\u9fa5a-zA-Z0-9 ]{1,10}\\s((100)|([1-9]\\d)|\\d)(\\s((100)|([1-9]\\d)|\\d)){2,9}$"; 279 boolean isEnd = true;//結束標志 280 String[] strings; 281 void inputProcessing(String line,Data_storage data_storage) { 282 lineProcessing(line);//分割 283 data_storage.output.add_input(line);//存儲 284 if(line.matches(regex_c_inspect)){ 285 data_storage.setInspectCourses(strings[0],strings[1],strings[2]); 286 }else if(line.matches(regex_c_lab)){ 287 data_storage.setLabCourses(strings[0],strings[1],strings[2],line); 288 }else if(line.matches(regex_c_test)){ 289 data_storage.setTestCourses(strings[0],strings[1],strings[2],strings[3],strings[4]);//成績信息 290 } else if(line.matches(regex_CS)||line.matches(regex_lab)){ 291 data_storage.setClasses(strings[0].substring(0,6)); 292 data_storage.setStudents(strings[0].substring(0, 6), strings[1], strings[0]);//學生的添加 293 if (data_storage.courses.containsKey(strings[2])) {//課程里有這個課 294 if (data_storage.courses.get(strings[2]).type.equals("選修")) {// 295 if (data_storage.courses.get(strings[2]).test_way.equals("考試")&&strings.length == 5) { 296 data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3], strings[4]); 297 }else if(data_storage.courses.get(strings[2]).test_way.equals("考察")&&strings.length==4){ 298 data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3]); 299 } else { 300 data_storage.setStu__st_courAndMap(strings[0], strings[2], "no access", "no access"); 301 } 302 } else if (data_storage.courses.get(strings[2]).type.equals("必修")) {// 303 if (strings.length == 5) { 304 data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3],strings[4]); 305 } else {//無效 306 data_storage.setStu__st_courAndMap(strings[0], strings[2], "no access", "no access"); 307 } 308 } else if(data_storage.courses.get(strings[2]).type.equals("實驗")){ 309 if(strings.length == 3+((Lab_Course) data_storage.courses.get(strings[2])).sub_scores_num){ 310 data_storage.set_lab_grades(strings[0],strings[2], String.valueOf(((Lab_Course) data_storage.courses.get(strings[2])).sub_scores_num),line); 311 }else{ 312 data_storage.set_lab_grades(strings[0],strings[2],"num error","no access"); 313 } 314 } 315 }else{ 316 data_storage.setStu__st_courAndMap(strings[0], strings[2], "not exist"); 317 } 318 } 319 } 320 void lineProcessing(String line){ 321 strings = line.split(" "); 322 } 323 } 324 class Inspect_Score extends Score{ 325 String end_score; 326 Inspect_Score(String end_score) { 327 this.end_score = end_score; 328 } 329 } 330 class Output_Format { 331 Calculate_grades calculate = new Calculate_grades(); 332 String regex_c_test = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|選修|實驗)\\s(考試|考察|實驗)\\s((\\d{1,2})|(1-9?))\\s((\\d{1,2})|(1-9?))$"; 333 String regex_c_test_e = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|選修|實驗)\\s(考試|考察|實驗)\\s((0.\\d{1,2})|(1-9?))\\s((0.\\d{1,2})|(1-9?))$"; 334 String regex_c_inspect = "[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|選修|實驗)\\s(考試|考察|實驗)$"; 335 String regex_c_lab = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|選修|實驗)\\s(考試|考察|實驗)\\s[4-9]\\s((0.\\d{1,2})|(1-9?))(\\s((0.\\d{1,2})|(1-9?))){1,10}$"; 336 String regex_CS = "^\\d{8}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s*((100)|(\\d{1,2})|(0))?\\s+((100)|(\\d{1,2})|(0))$"; 337 String regex_lab = "^\\d{8}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s((100)|([1-9]\\d)|\\d)(\\s((100)|([1-9]\\d)|\\d)){1,20}$"; 338 void outputProcessing(Data_storage data) { 339 data.classes.forEach((num,Class)-> Class.students.forEach((name, student)-> calculate.final_score(data,student.num))); 340 for(String i:data.output.input){ 341 String[] tem = i.split(" "); 342 if(i.matches(regex_c_test_e)||i.matches(regex_c_test)||i.matches(regex_c_inspect)||i.matches(regex_c_lab)){ 343 if(tem[1].equals("必修")&&(tem[2].equals("考察")||tem[2].equals("實驗"))){ 344 data.output.add_output(tem[0] + " : course type & access mode mismatch"); 345 }else if(tem[1].equals("實驗")&&!tem[2].equals("實驗")) { 346 data.output.add_output(tem[0] + " : course type & access mode mismatch"); 347 }else if(tem[1].equals("選修")&&tem[2].equals("實驗")) { 348 data.output.add_output(tem[0] + " : course type & access mode mismatch"); 349 } 350 if(tem[1].equals("實驗")&&tem[2].equals("實驗")) { 351 if(tem.length-4>=4&&tem.length - 4<=9) { 352 if (Integer.parseInt(tem[3]) != tem.length - 4) { 353 data.output.add_output(tem[0] + " : number of scores does not match"); 354 data.courses.remove(tem[0]); 355 continue; 356 } 357 float tem_weight = 0; 358 for (int j = 4; j < tem.length; j++) { 359 tem_weight += Float.parseFloat(tem[j]); 360 } 361 if (Math.abs(tem_weight - 1) > 0.0001) { 362 data.output.add_output(tem[0] + " : weight value error"); 363 data.courses.remove(tem[0]); 364 continue; 365 } 366 }else{ 367 try { 368 if (Integer.parseInt(tem[3]) != tem.length - 4) { 369 data.output.add_output(tem[0] + " : number of scores does not match"); 370 data.courses.remove(tem[0]); 371 continue; 372 } 373 } catch (Exception ignored) { 374 375 } 376 } 377 }if((tem[1].equals("必修")||tem[1].equals("選修"))&&tem[2].equals("考試")){ 378 if(tem.length-3==2) { 379 float tem_weight = Float.parseFloat(tem[3]) + Float.parseFloat(tem[4]); 380 if (Math.abs(tem_weight - 1) > 0.0001) { 381 data.output.add_output(tem[0] + " : weight value error"); 382 data.courses.remove(tem[0]); 383 } 384 } 385 } 386 }else if(i.matches(regex_CS)||i.matches(regex_lab)) { 387 if(!data.courses.containsKey(tem[2])){//不存在 388 data.output.add_output(tem[2]+" does not exist"); 389 data.stu__st_cour.get(tem[0]).gradeMap.remove(tem[2]); 390 }else{ 391 if(data.courses.get(tem[2]).type.equals("必修") && tem.length!=5) {//必修 但是只有期末成績 392 data.output.add_output(tem[0]+" "+tem[1]+" : access mode mismatch"); 393 }else if(data.courses.get(tem[2]).type.equals("選修")) { 394 if ((data.courses.get(tem[2]).test_way.equals("考試") && tem.length != 5) || 395 (data.courses.get(tem[2]).test_way.equals("考察") && tem.length != 4)) 396 data.output.add_output(tem[0] + " " + tem[1] + " : access mode mismatch"); 397 }else if(data.courses.get(tem[2]).type.equals("實驗")){ 398 if(data.courses.get(tem[2]).test_way.equals("實驗")&&(tem.length-3<4||tem.length-3>9||tem.length-3!=((Lab_Course) data.courses.get(tem[2])).sub_scores_num)) 399 data.output.add_output(tem[0] + " " + tem[1] + " : access mode mismatch"); 400 } 401 } 402 }else if(!i.equals("end")){ 403 data.output.add_output("wrong format"); 404 } 405 } 406 data.classes.forEach((cla_num,Class1)->{//遍歷所有班級 407 Class1.students.forEach((stu_num,student)->{ 408 int tem=calculate.stu_all_grades(data,stu_num); 409 if(tem>=0) 410 data.output.add_output(stu_num+" "+Class1.students.get(stu_num).name+" "+tem); 411 else 412 data.output.add_output(stu_num+" "+Class1.students.get(stu_num).name+" "+"did not take any exams"); 413 }); 414 }); 415 data.courses.forEach((key,value)-> { 416 int[] tem = calculate.single_course_grades(data, key); 417 if (tem[0] < 0 && tem[1] < 0 && tem[2] < 0) {//三個為- 則沒成績 418 data.output.add_output(key + " has no grades yet"); 419 }else { 420 if (value.type.equals("選修") || value.type.equals("必修") || value.type.equals("實驗")) { 421 data.output.add_output(key + " " + tem[2]); 422 } 423 } 424 }); 425 data.classes.forEach((num,Class)->{ 426 int tem = calculate.Class_grades(data,num); 427 if(tem>=0) { 428 data.output.add_output(num + " " + tem); 429 }else 430 data.output.add_output(num+" has no grades yet"); 431 }); 432 } 433 void output_all(Data_storage data){ 434 data.output.output.forEach(System.out::println); 435 } 436 } 437 abstract class Score { 438 String total_scores = "-100"; 439 } 440 class Student { 441 String name; 442 String num; 443 Student(String name, String num) { 444 this.name = name; 445 this.num = num; 446 } 447 } 448 class StudentsAll_mes { 449 String num;//學生 450 TreeMap<String,Score> gradeMap =new TreeMap<>(); 451 StudentsAll_mes(String stu_name, String course, String normal_score,String test_score){ 452 this.num = stu_name; 453 gradeMap.put(course,new Test_Score(normal_score,test_score)); 454 } 455 StudentsAll_mes(String stu_name, String course, String test_score){ 456 this.num = stu_name; 457 gradeMap.put(course,new Inspect_Score(test_score)); 458 } 459 460 public StudentsAll_mes() { 461 462 } 463 void set_lab_stu_mes(String stu_num,String course,String lab_num,ArrayList<Integer> scores){ 464 this.num = stu_num; 465 gradeMap.put(course,new Lab_Score(lab_num,scores)); 466 } 467 void set_lab_gradeMap(String course,String lab_num,ArrayList<Integer> scores){ 468 if(!gradeMap.containsKey(course)) 469 gradeMap.put(course,new Lab_Score(lab_num,scores)); 470 } 471 void setGradeMap(String course, String normal_score,String test_score){ 472 if(!gradeMap.containsKey(course)) 473 gradeMap.put(course, new Test_Score(normal_score,test_score)); 474 } 475 void setGradeMap(String course,String test_score){ 476 if(!gradeMap.containsKey(course)) 477 gradeMap.put(course,new Inspect_Score(test_score)); 478 } 479 } 480 class Test_Score extends Score{ 481 String normal_score; 482 String end_score; 483 Test_Score(String normal_score,String end_score) { 484 this.normal_score = normal_score; 485 this.end_score = end_score; 486 } 487 } 488 class Lab_Score extends Score { 489 String lab_num;//試驗次數 490 ArrayList<Integer> scores; 491 Lab_Score(String lab_num,ArrayList<Integer> scores){ 492 this.lab_num = lab_num; 493 this.scores = scores; 494 } 495 } 496 class InAndOut_put { 497 List<String> output = new ArrayList<>(); 498 List<String> input = new ArrayList<>(); 499 void add_output(String out){ 500 output.add(out); 501 } 502 void add_input(String out){ 503 input.add(out); 504 } 505 }
我的代碼中的主要類和功能如下:
Main
類:包含程序的入口方法main
,用于接收用戶輸入、處理數據和輸出結果。Data_storage
類:用于存儲數據,包括課程、班級和學生的信息,以及學生的成績。Input_Format
類:用于處理用戶輸入的數據,并根據輸入的格式解析和存儲相關信息。Output_Format
類:用于對數據進行計算和格式化輸出,包括計算學生平均成績、課程平均成績和班級平均成績等。Calculate_grades
類:用于計算學生、課程和班級的平均成績。Class
類:表示一個班級,包含班級號和學生信息。Course
類及其子類:表示一個課程,包含課程名稱、類型和考試方式等信息。Score
類及其子類:表示學生的成績,包括平時成績、期末考試成績和總分成績等。
代碼通過讀取用戶輸入的數據,解析并存儲到相應的數據結構中。然后根據存儲的數據進行成績計算和格式化輸出。其中,成績計算部分涉及單個學生總課程平均分計算、單門課程成績計算和班級平均成績計算。
主要類圖如下:

從類圖可以看出本次代碼非常復雜,我徹底改變了課程程序統(tǒng)計程序-2的邏輯結構,改變了原來的輸入輸出讀取方式以及字符匹配模式。
本次代碼的圈復雜度如下:
? 從這個圖可以看出,本次代碼雖然類很多,但是結構比第二次作業(yè)要清晰,代碼深度較高,平均的復雜度以及選擇分支減少,減少了內存開銷。
期末考試
編程求得正方體和正三棱錐的表面積和體積,要求必須體現擴展性(繼承)和多態(tài)性。
類結構如下圖所示(參考):
試編程完成如上類設計,主方法源碼如下(可直接拷貝使用):
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
double side = input.nextDouble();
display(new Cube(side));
display(new RegularPyramid(side));
}
其中,display(Solid solid)
方法為定義在Main類中的靜態(tài)方法,作用為體現程序的多態(tài)性。
注:正三棱錐的體積計算公式為底面積*高/3。
輸入格式:
輸入一個實型數,分別作為正方體的邊長和正三棱錐的邊長。
輸出格式:
分別輸出正方體的表面積、體積以及正棱錐的表面積和體積。保留兩位小數,建議使用String.format(“%.2f”,value)
進行小數位數控制。
輸入樣例:
在這里給出一組輸入。例如:
2.5
輸出樣例:
在這里給出相應的輸出。例如:
37.50 15.63 10.83 1.84
這個題目難度不大,主要在于三棱錐的體積與表面積的計算方法以及截斷整數那里讓我修改了一次。
我的代碼如下:
import java.util.Scanner; abstract class Solid { protected double side; public Solid(double side) { this.side = side; } public abstract double getSurfaceArea(); public abstract double getVolume(); } class Cube extends Solid { public Cube(double side) { super(side); } public double getSurfaceArea() { return 6 * Math.pow(side, 2); } public double getVolume() { return Math.pow(side, 3); } } class RegularPyramid extends Solid { public RegularPyramid(double side) { super(side); } public double getSurfaceArea() { return Math.pow(side, 2) *Math.sqrt(3); } public double getVolume() { return Math.pow(side, 3) / (6 * Math.sqrt(2)); } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); double side = input.nextDouble(); display(new Cube(side)); display(new RegularPyramid(side)); } public static void display(Solid solid) { System.out.println(String.format("%.2f", solid.getSurfaceArea())); System.out.println(String.format("%.2f", solid.getVolume())); } }
Solid
是一個抽象類,表示幾何體,包含一個受保護的成員變量side
表示邊長,以及兩個抽象方法getSurfaceArea()
和getVolume()
用于計算幾何體的表面積和體積。Cube
是Solid
的子類,表示立方體,通過繼承Solid
類并實現抽象方法來計算立方體的表面積和體積。RegularPyramid
也是Solid
的子類,表示正四面體,同樣通過繼承Solid
類并實現抽象方法來計算正四面體的表面積和體積。Main
類包含了程序的入口方法main
,在該方法中使用Scanner
類獲取用戶輸入的邊長,然后創(chuàng)建一個立方體和一個正四面體對象,并調用display
方法顯示它們的表面積和體積。display
方法接受一個Solid
類型的參數,根據傳入的具體幾何體對象調用相應的方法來顯示它們的表面積和體積。
本次代碼的行數以及結構很清晰明了,在此不貼出其類圖及復雜度分析。
問題描述:本問題中的魔方有兩種,一種是正方體魔方,一種是正三棱錐魔方,其中,正方體或正三棱錐魔方是由單元正方體或正三棱錐組成,單元正方體或正三棱錐的個數由階數(即層數)決定,即魔方邊長=階數*單元邊長。魔方如下圖所示:
?
利用“立體圖形”問題源碼,實現如下功能:
魔方有三個屬性:顏色,階數,類型(正方體魔方、正三棱錐魔方),程序要求輸出魔方的顏色、表面積和體積。參考設計類圖如下所示:
主方法部分可參考如下源碼(可拷貝直接使用):
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
String color = input.next();
int layer = input.nextInt();
double side = input.nextDouble();
RubikCube cube1 = new SquareCube(color, layer,new Cube(side));
color = input.next();
layer = input.nextInt();
side = input.nextDouble();
RubikCube cube2 = new RegularPyramidCube(color, layer,new RegularPyramid(side));
display(cube1);
display(cube2);
}
}
其中,display(RubikCube cube)
方法為Main類中定義的靜態(tài)方法,用戶輸出魔方的信息,用于體現多態(tài)性。
輸入格式:
第一部分:正方體魔方顏色、階數、單元正方體邊長,以空格或回車分隔;
第二部分:正三棱錐魔方顏色、階數、單元正三棱錐邊長,以空格或回車分隔。
輸出格式:
正方體魔方顏色
正方體魔方表面積
正方體魔方體積
正三棱錐魔方顏色
正三棱錐魔方表面積
正三棱錐魔方體積
注:小數點保留兩位
輸入樣例:
在這里給出一組輸入。例如:
red 3 4.5
black 4 2.1
輸出樣例:
在這里給出相應的輸出。例如:
red
1093.50
2460.38
black
122.21
69.85
這道題目只需要在第一道的基礎上略微修改計算方式以及添加抽象魔方類即可解決。
代碼如下:


import java.util.Scanner; abstract class Solid { protected double side; public Solid(double side) { this.side = side; } public abstract double getSurfaceArea(); public abstract double getVolume(); } class Cube extends Solid { public Cube(double side) { super(side); } public double getSurfaceArea() { return 6 * Math.pow(side, 2); } public double getVolume() { return Math.pow(side, 3); } } class RegularPyramid extends Solid { public RegularPyramid(double side) { super(side); } public double getSurfaceArea() { return Math.pow(side, 2) *Math.sqrt(3); } public double getVolume() { return Math.pow(side, 3) / (6 * Math.sqrt(2)); } } abstract class RubikCube { protected String color; protected int layer; protected Solid solid; public RubikCube(String color, int layer, Solid solid) { this.color = color; this.layer = layer; this.solid = solid; } public String getColor() { return color; } public abstract double getSurfaceArea(); public abstract double getVolume(); } class SquareCube extends RubikCube { public SquareCube(String color, int layer, Solid solid) { super(color, layer, solid); } public double getSurfaceArea() { return 6 * Math.pow(layer * solid.side, 2); } public double getVolume() { return Math.pow(layer * solid.side, 3); } } class RegularPyramidCube extends RubikCube { public RegularPyramidCube(String color, int layer, Solid solid) { super(color, layer, solid); } public double getSurfaceArea() { return layer * layer * solid.getSurfaceArea(); } public double getVolume() { return layer * layer * layer * solid.getVolume(); } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String color = input.next(); int layer = input.nextInt(); double side = input.nextDouble(); RubikCube cube1 = new SquareCube(color, layer, new Cube(side)); color = input.next(); layer = input.nextInt(); side = input.nextDouble(); RubikCube cube2 = new RegularPyramidCube(color, layer, new RegularPyramid(side)); display(cube1); display(cube2); } public static void display(RubikCube cube) { System.out.println(cube.getColor()); System.out.println(String.format("%.2f", cube.getSurfaceArea())); System.out.println(String.format("%.2f", cube.getVolume())); } }
RubikCube
是一個抽象類,表示魔方,包含顏色、層數和幾何體對象的信息。它繼承自Solid
類,并實現了抽象方法getSurfaceArea()
和getVolume()
來計算魔方的表面積和體積。SquareCube
是RubikCube
的子類,表示正方體魔方。通過繼承RubikCube
類并實現抽象方法來計算正方體魔方的表面積和體積。RegularPyramidCube
也是RubikCube
的子類,表示正四面體魔方。同樣通過繼承RubikCube
類并實現抽象方法來計算正四面體魔方的表面積和體積。
在Main
類中,除了之前的功能外,添加了用戶輸入魔方的顏色、層數和邊長。根據用戶輸入創(chuàng)建一個正方體魔方對象和一個正四面體魔方對象,并調用display
方法顯示它們的顏色、表面積和體積。
display
方法接受一個RubikCube
類型的參數,根據傳入的魔方對象調用相應的方法來顯示它們的顏色、表面積和體積。
在魔方問題的基礎上,重構類設計,實現列表內魔方的排序功能(按照魔方的體積進行排序)。
提示:題目中RubikCube類要實現Comparable接口。
其中,Main類源碼如下(可直接拷貝使用):
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
String color;
int layer;
double side;
RubikCube cube;
ArrayList<RubikCube> list = new ArrayList<>();
int choice = input.nextInt();
while(choice != 0) {
switch(choice) {
case 1://SquareCube
color = input.next();
layer = input.nextInt();
side = input.nextDouble();
cube = new SquareCube(color, layer,new Cube(side));
list.add(cube);
break;
case 2://RegularPyramidCube
color = input.next();
layer = input.nextInt();
side = input.nextDouble();
cube = new RegularPyramidCube(color, layer,new RegularPyramid(side));
list.add(cube);
break;
}
choice = input.nextInt();
}
list.sort(Comparator.naturalOrder());//正向排序
for(int i = 0; i < list.size(); i++) {
System.out.print(list.get(i).getColor() + " " +
String.format("%.2f", list.get(i).getArea()) + " " +
String.format("%.2f", list.get(i).getVolume()) );
System.out.println("");
}
}
}
輸入格式:
輸入魔方類型(1:正方體魔方;2:正三棱錐魔方;0:結束輸入)
魔方顏色、魔方階數、魔方單元正方體、正三棱錐邊長
..循環(huán)..
輸出格式:
按魔方體積升序輸出列表中各魔方的信息(實型數均保留兩位小數),輸出樣式參見輸出樣例。
輸入樣例:
在這里給出一組輸入。例如:
1 blue 3 4.5
2 red 4 2.1
1 yellow 5 2.3
2 black 4 9.42
1 white 4 5.4423
0
輸出樣例:
在這里給出相應的輸出。例如:
red 122.21 69.85
yellow 793.50 1520.88
blue 1093.50 2460.38
black 2459.14 6304.73
white 2843.39 10316.38
這道題目是在魔方問題的基礎上,對用戶輸入的魔方數據的表面和體積進行排序。
我的代碼如下:


import java.util.Scanner; import java.util.ArrayList; import java.util.Comparator; abstract class Solid { protected double side; public Solid(double side) { this.side = side; } public abstract double getSurfaceArea(); public abstract double getVolume(); } class Cube extends Solid { public Cube(double side) { super(side); } public double getSurfaceArea() { return 6 * Math.pow(side, 2); } public double getVolume() { return Math.pow(side, 3); } } class RegularPyramid extends Solid { public RegularPyramid(double side) { super(side); } public double getSurfaceArea() { return Math.pow(side, 2) *Math.sqrt(3); } public double getVolume() { return Math.pow(side, 3) / (6 * Math.sqrt(2)); } } abstract class RubikCube implements Comparable<RubikCube> { protected String color; protected int layer; protected Solid solid; public RubikCube(String color, int layer, Solid solid) { this.color = color; this.layer = layer; this.solid = solid; } public String getColor() { return color; } public abstract double getSurfaceArea(); public abstract double getVolume(); @Override public int compareTo(RubikCube other) { return Double.compare(this.getVolume(), other.getVolume()); } } class SquareCube extends RubikCube { public SquareCube(String color, int layer, Solid solid) { super(color, layer, solid); } public double getSurfaceArea() { return 6 * Math.pow(layer * solid.side, 2); } public double getVolume() { return Math.pow(layer * solid.side, 3); } } class RegularPyramidCube extends RubikCube { public RegularPyramidCube(String color, int layer, Solid solid) { super(color, layer, solid); } public double getSurfaceArea() { return layer * layer * solid.getSurfaceArea(); } public double getVolume() { return layer * layer * layer * solid.getVolume(); } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String color; int layer; double side; RubikCube cube; ArrayList<RubikCube> list = new ArrayList<>(); int choice = input.nextInt(); while(choice != 0) { switch(choice) { case 1://SquareCube color = input.next(); layer = input.nextInt(); side = input.nextDouble(); cube = new SquareCube(color, layer,new Cube(side)); list.add(cube); break; case 2://RegularPyramidCube color = input.next(); layer = input.nextInt(); side = input.nextDouble(); cube = new RegularPyramidCube(color, layer,new RegularPyramid(side)); list.add(cube); break; } choice = input.nextInt(); } list.sort(Comparator.naturalOrder());//正向排序 for(int i = 0; i < list.size(); i++) { System.out.print(list.get(i).getColor() + " " + String.format("%.2f", list.get(i).getSurfaceArea()) + " " + String.format("%.2f", list.get(i).getVolume()) ); System.out.println(""); } } }
這段代碼中的類包括:
Solid
:抽象基類,表示一個立體,包含邊長屬性和計算表面積和體積的抽象方法。Cube
:繼承自Solid
,表示一個立方體,實現了計算表面積和體積的方法。RegularPyramid
:繼承自Solid
,表示一個正四面體,實現了計算表面積和體積的方法。RubikCube
:抽象基類,表示一個魔方,包含顏色、層數和實際立體對象的屬性,以及計算表面積和體積的抽象方法和比較方法。SquareCube
:繼承自RubikCube
,表示一個立方體魔方,實現了計算表面積和體積的方法。RegularPyramidCube
:繼承自RubikCube
,表示一個金字塔魔方,實現了計算表面積和體積的方法。Main
:主類,包含main
方法,用于接收用戶輸入、創(chuàng)建魔方對象、進行排序和打印結果。
用戶可以通過輸入數字選擇魔方類型(1表示立方體魔方,2表示金字塔魔方),然后依次輸入顏色、層數和邊長。輸入0表示結束輸入。
最后,程序將根據魔方的體積對魔方列表進行排序,并打印每個魔方的顏色、表面積和體積。
我的代碼的類圖如下:
?
在原來的魔方問題代碼上,我添加了用戶選擇立體類型以及排序輸出部分。
前亞利桑那州境內的一位步槍銷售商銷售密蘇里州制造的步槍機(lock)、槍托(stock)和槍管(barrel)。槍機賣45美元,槍托賣30美元,槍管賣25美元。銷售商每月至少要售出一支完整的步槍,且生產限額是銷售商在一個月內可銷售70個槍機、80個槍托和90個槍管。
根據每個月的銷售情況,計算銷售商的傭金(提成)算法如下:
-
不到(含)1000美元的部分為10%;
-
1000(含)~1800美元的部分為15%;
-
超過1800美元的部分為20%。
傭金程序生成月份銷售報告,匯總銷售商的銷售總額和傭金。
編程要求:必須符合面向對象編程,且保證類設計的單一職責模式,使用面向過程編程判定0分。
提示:可以設置一個銷售訂單類。參考類圖如下:
輸入格式:
輸入銷售商每個月售出槍機、槍托、槍管的數量,可以用空格或者回車分隔。
輸出格式:
分別輸出銷售商在該月的銷售額和傭金,中間用空格分開。
輸入樣例1:
在這里給出一組輸入。例如:
30 40 50
輸出樣例1:
在這里給出相應的輸出。例如:
3800.00 620.00
輸入樣例2:
在這里給出一組輸入。例如:
88 56 98
輸出樣例2:
在這里給出相應的輸出。例如:
Wrong Format
這是一道簡單的題目,我的代碼如下:
import java.util.Scanner; class SalesOrder { private int lockCount; private int stockCount; private int barrelCount; private static final int LOCK_PRICE = 45; private static final int STOCK_PRICE = 30; private static final int BARREL_PRICE = 25; public SalesOrder(int lockCount, int stockCount, int barrelCount) { if ((lockCount > 70 || stockCount > 80 || barrelCount > 90)||(lockCount<1||stockCount<1||barrelCount<1)) { throw new IllegalArgumentException("Wrong Format"); } this.lockCount = lockCount; this.stockCount = stockCount; this.barrelCount = barrelCount; } public double calculateTotalSales() { return lockCount * LOCK_PRICE + stockCount * STOCK_PRICE + barrelCount * BARREL_PRICE; } public double calculateCommission() { double totalSales = calculateTotalSales(); if (totalSales <= 1000) { return totalSales * 0.10; } else if (totalSales <= 1800) { return 1000 * 0.10 + (totalSales - 1000) * 0.15; } else { return 1000 * 0.10 + 800 * 0.15 + (totalSales - 1800) * 0.20; } } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int lockCount = input.nextInt(); int stockCount = input.nextInt(); int barrelCount = input.nextInt(); try { SalesOrder order = new SalesOrder(lockCount, stockCount, barrelCount); System.out.printf("%.2f %.2f\n", order.calculateTotalSales(), order.calculateCommission()); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); } } }
這是期末考試的附加題,難度不大,只要注意題目的條件控制好輸入輸出,基本不會出錯。文章來源:http://www.zghlxwxcb.cn/news/detail-749208.html
總結:
這階段的題目是PTA的最后一部分題目,題目難度相較于第二次也變小了,最后一階段的題目加入了很多面向對象java的特點題目,加入了接口,繼承多態(tài)部分題目,這些題目讓我對面向對象java這門語言更加熟悉和了解,PTA的題目讓我記憶猶新,我曾因為兩道題做出來而竊竊自喜,也曾因為菜單計價系列題目而痛不欲生,這些都使我受益良多,最后一階段的題目算是對java的學習到了一個新階段,我開始有意識地理清代碼結構以及想辦法降低代碼復雜度,而不是像以前一樣只求做出來,我開始思考題目的需求和哪些方法匹配,字符匹配是否需要用到正則表達式,類的設計是應該繼承還是組合,應該用哪種方式來儲存數據(鏈表還是數組)……,這些思考使我的代碼能力和設計思維進一步提高,為我以后的工作和學習打下了良好的基礎。文章來源地址http://www.zghlxwxcb.cn/news/detail-749208.html
?
到了這里,關于面向對象程序設計第三次bolg的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!