目录:
(1)关于PTA题目集
(2)对本门课的意见
本次与上次blog之间时间跨度较大,故攒下了不少可以拿来说一说的题目。
这几次作业用得比较频繁的知识点有用正则表达式来判断输入信息是否合法,利用Comparator接口进行重写排序,数组主要用的是ArrayList类,尝试了HashMap类以及HashSet类的使用,明白了HashMap类适合查找信息而HashSet类适合存储信息,更加熟悉了String相关字符串类的运用,明白了Comparator接口也可用于HashMap类的排序,进一步了解了子类与父类的使用方法和关系,进一步了解了有无父类的区别,还用到了IntegerStack接口的改写。
关于题量,个人感觉还好,主要那些迭代题得在第一次写的时候就得好好写,后续的迭代才能轻松些。别的一些小题有没见过的方法上网好好查下也没啥问题了。
关于难度,大体上都能上90,想要满分得一个个试哪种情况还没考虑到,不容易的,毕竟我是遇上迭代就没满分了。其余的小题确实不难。
关于本次迭代的成绩计算系列题目:
主要给第一次的:
某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。
考察的总成绩直接等于期末成绩
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。
1、输入:
包括课程、课程成绩两类信息。
课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。
课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
课程性质输入项:必修、选修
考核方式输入选项:考试、考察
课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
以上信息的相关约束:
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)成绩平均分只取整数部分,小数部分丢弃
参考类图:
我的代码:
import java.util.*;
import java.text.*;
public class Main {
public static void main(String[] args) {
Courseselection courseselection = new Courseselection();
courseselection.play();
}
}
class Class_ {
private String num;
private ArrayList<Student> students = new ArrayList<>();
public Class_(String num) {
this.num = num;
}
public String getNum() {
return num;
}
public ArrayList<Student> getStudents() {
return students;
}
public void addStudent(Student student) {
this.students.add(student);
}
public void showScore(){
boolean flag = false;
int num = 0;
int averageScore = 0;
for(int i = 0; i < this.students.size(); i ++){
if(this.students.get(i).getScores().size() != 0){
flag = true;
num = num + 1;
averageScore = averageScore + students.get(i).averageScore();
}
}
if(flag)
System.out.println(this.num + " " + averageScore / num);
else
System.out.println(this.num + " has no grades yet");
}
}
abstract class Score {
protected abstract int sumScore();
protected abstract int usualScore();
protected abstract int finalScore();
}
class Test_grades extends Score{
private int usualScore;
private int finalScore;
public Test_grades(int usualScore, int finalScore) {
this.usualScore = usualScore;
this.finalScore = finalScore;
}
@Override
public int sumScore(){
return (int)(usualScore * 0.3 + finalScore * 0.7);
}
@Override
public int usualScore(){
return usualScore;
}
@Override
public int finalScore(){
return finalScore;
}
}
class Examine_grades extends Score{
private int examScore;
public Examine_grades(int examScore) {
this.examScore = examScore;
}
@Override
public int sumScore(){
return examScore;
}
@Override
public int usualScore(){
return 0;
}
@Override
public int finalScore(){
return 0;
}
}
class Course {
private String name;
private String quality;
private String way;
private ArrayList<Score> scores = new ArrayList<>();
public Course(String name, String quality, String way) {
this.name = name;
this.quality = quality;
this.way = way;
}
public String getName() {
return name;
}
public String getWay() {
return way;
}
public void showScore(){
int averageScore = 0;
if(scores.size() == 0)
System.out.println(this.name + " has no grades yet");
else {
if (this.way.equals("考察")) {
for (int i = 0; i < scores.size(); i++)
averageScore = averageScore + scores.get(i).sumScore();
System.out.println(name + " " + averageScore / scores.size() + " " + averageScore / scores.size());
}
if (this.way.equals("考试")) {
int averageUsualScore = 0, averageFinalScore = 0;
for (int i = 0; i < scores.size(); i++) {
averageScore = averageScore + scores.get(i).sumScore();
averageUsualScore = averageUsualScore + scores.get(i).usualScore();
averageFinalScore = averageFinalScore + scores.get(i).finalScore();
}
System.out.println(name + " " + averageUsualScore / scores.size() + " " + averageFinalScore / scores.size() + " " + averageScore / scores.size());
}
}
}
public void addScore(Score score){
this.scores.add(score);
}
public boolean check(){
if(quality.equals("必修") && way.equals("考察")){
System.out.println(name + " : course type & access mode mismatch");
return false;
}
if(getStringLengthRegex(name) > 10 || !(quality.equals("必修") || quality.equals("选修")) || !(way.equals("考试") || way.equals("考察"))){
System.out.println("wrong format");
return false;
}
return true;
}
public static int getStringLengthRegex(String s) {
s = s.replaceAll("[^\\x00-\\xff]", "**");
int length = s.length();
return length;
}
}
class Student {
private String studyNum;
private String name;
private ArrayList<String> courses = new ArrayList<>();
private ArrayList<Score> scores = new ArrayList<>();
public Student(String studyNum, String name) {
this.studyNum = studyNum;
this.name = name;
}
public String getStudyNum() {
return studyNum;
}
public String getName() {
return name;
}
public ArrayList<String> getCourses() {
return courses;
}
public void addCourse(String course) {
this.courses.add(course);
}
public ArrayList<Score> getScores() {
return scores;
}
public void addScore(Score score) {
this.scores.add(score);
}
public int averageScore(){
int averageScore = 0;
for (int i = 0; i < scores.size(); i++) {
averageScore = averageScore + scores.get(i).sumScore();
}
return averageScore / scores.size();
}
public void showScore(){
if(this.scores.size() == 0)
System.out.println(this.studyNum + " " + this.name + " did not take any exams");
else
System.out.println(this.studyNum + " " + this.name + " " + this.averageScore());
}
}
class Courseselection {
private ArrayList<Class_> class_s = new ArrayList<>();
private ArrayList<Student> students = new ArrayList<>();
private ArrayList<Course> courses = new ArrayList<>();
Scanner input = new Scanner(System.in);
public Courseselection() {
}
public void play(){
String line = input.nextLine();
String[] information = line.split(" ");
Course courseNew;
while(information.length == 3 || (information.length == 2 && information[2].equals("必修"))) {
for (int i = 0; i < courses.size(); i++) {
if (courses.get(i).getName().equals(information[0])) {
if(information.length == 3)
courseNew = new Course(information[0], information[1], information[2]);
else
courseNew = new Course(information[0], information[1], "必修");
courseNew.check();
line = input.nextLine();
information = line.split(" ");
i = 0;
}
if (information.length != 3 && !(information.length == 2 && information[2].equals("必修")))
break;
}
if (information.length != 3 && !(information.length == 2 && information[2].equals("必修")))
break;
if(information.length == 3)
courseNew = new Course(information[0], information[1], information[2]);
else
courseNew = new Course(information[0], information[1], "必修");
if (courseNew.check())
courses.add(courseNew);
line = input.nextLine();
information = line.split(" ");
}
while(!information[0].equals("end")) {
int i;
Score scoreNew = new Examine_grades(0);
boolean flag = false, flag1 = false, flag2 = false, flag4 = false;
for(int i2 = 0; i2 < students.size(); i2 ++){
if(students.get(i2).getStudyNum().equals(information[0]) && students.get(i2).getName().equals(information[1]))
for (int i1 = 0; i1 < students.get(i2).getCourses().size(); i1++)
if (students.get(i2).getCourses().get(i1).equals(information[2])) {
line = input.nextLine();
information = line.split(" ");
i2 = 0;
break;
}
if(information[0].equals("end"))
break;
}
if(information[0].equals("end"))
break;
if (information[0].length() != 8 || information[1].length() > 10) {
System.out.println("wrong format");
} else {
Student studentNew = new Student(information[0], information[1]);
for (i = 0; i < courses.size(); i++)
if (information[2].equals(courses.get(i).getName())) {
flag1 = true;
if (courses.get(i).getWay().equals("考试")) {
if (information.length != 5) {
System.out.println(information[0] + " " + information[1] + " : access mode mismatch");
} else {
if (Double.valueOf(information[3]) < 0 || Double.valueOf(information[4]) < 0 || Double.valueOf(information[3]) > 100 || Double.valueOf(information[4]) > 100) {
System.out.println("wrong format");
flag4 = true;
break;
}
double grade1 = Double.valueOf(information[3]);
double grade2 = Double.valueOf(information[4]);
courses.get(i).addScore(new Test_grades((int)grade1, (int)grade2));
studentNew.addCourse(information[2]);
scoreNew = new Test_grades((int)grade1, (int)grade2);
flag = true;
}
break;
} else if (courses.get(i).getWay().equals("考察")) {
if (information.length != 4) {
System.out.println(information[0] + " " + information[1] + " : access mode mismatch");
} else {
if (Double.valueOf(information[3]) < 0 || Double.valueOf(information[3]) > 100) {
System.out.println("wrong format");
flag4 = true;
break;
}
double grade = Double.valueOf(information[3]);
courses.get(i).addScore(new Examine_grades((int)grade));
studentNew.addCourse(information[2]);
scoreNew = new Examine_grades((int)grade);
flag = true;
}
break;
}
}
if (!flag4) {
for (int i1 = 0; i1 < students.size(); i1++) {
if (information[0].equals(students.get(i1).getStudyNum()) && information[1].equals(students.get(i1).getName())) {
if(flag) {
students.get(i1).addCourse(information[2]);
students.get(i1).addScore(scoreNew);
}
flag2 = true;
break;
}
}
if (!flag2) {
if (flag)
studentNew.addScore(scoreNew);
students.add(studentNew);
}
if (!flag1)
System.out.println(information[2] + " does not exist");
}
}
line = input.nextLine();
information = line.split(" ");
}
for (int i = 0; i < students.size(); i++) {
boolean flag = false;
String classnumNew = students.get(i).getStudyNum().substring(0, 6);
for (int i1 = 0; i1 < class_s.size(); i1++) {
if (class_s.get(i1).getNum().equals(classnumNew)) {
class_s.get(i1).addStudent(students.get(i));
flag = true;
break;
}
}
if (!flag) {
class_s.add(new Class_(classnumNew));
class_s.get(class_s.size() - 1).addStudent(students.get(i));
}
}
Comparator<Student> comparator1 = new Comparator<Student>(){
public int compare(Student s1, Student s2) {
return Integer.valueOf(s1.getStudyNum()) - Integer.valueOf(s2.getStudyNum());
}
};
Comparator<Object> comparator2 = Collator.getInstance(Locale.CHINA);
Collections.sort(courses, (e1, e2) -> {
return comparator2.compare(e1.getName(), e2.getName());
});
Comparator<Class_> comparator3 = new Comparator<Class_>(){
public int compare(Class_ c1, Class_ c2) {
return Integer.valueOf(c1.getNum()) - Integer.valueOf(c2.getNum());
}
};
Collections.sort(students, comparator1);
Collections.sort(class_s, comparator3);
for(int i = 0; i < students.size(); i ++)
students.get(i).showScore();
for(int i = 0; i < courses.size(); i ++)
courses.get(i).showScore();
for(int i = 0; i < class_s.size(); i ++)
class_s.get(i).showScore();
}
}
SourceMonitor的报表内容:
PowerDesigner的相应类图:
关于此系列题目的分析:
个人感觉这类题目都有一些固定的解题思路:
先说第一题:先是需要输入数据,再对数据进行处理,最后输出数据。其中输入数据可能需要对数据进行筛选以及判断,如课程名与课程类型,成绩计算方式的输入就是一行仅有固定的几个类型的数据,像是第二个字符串一定是必修、选修,且第一个字符串非学号。那么就可以以此作为判断输入的那行是课程信息还是学生的成绩信息的依据,当然,作为结束的end是题目要求中自带的。再者就是对输入数据的要求,如课程名不可超过十位,课程性质与考察方式是固定的那几种且相互之间有关联。若非如此就输出相对应的错误提示且入不入录信息都是有讲究的之类的。再到对数据进行处理,这里就要更加复杂些,也是比较能体现C语言中的面向过程编程与java中面向结果编程的区别的地方。在java里,数据被存储进了不同的类里,再经由这些类中的方法对这些数据进行处理和输出。比如在学生类中对各种课程成绩的处理便是通过averageScore()方法实现的,而对成绩的输出便是通过showScore()方法实现的。深入进其中的数据处理便要显得多种多样了,如学生类的数据处理便是将其中各科成绩的数据处理方法整合后得出结果,这其中也体现了java编程的单一职责原则,因为它没有一股脑的将成绩的处理都放在学生类的方法里,而是让成绩类做了成绩类该做的,再由学生类做学生类该做的。说到成绩类该做的,成绩类又有了不同种类的成绩属性的划分,便也有了不同数据处理的方法的划分,像平时成绩与期末成绩按比例乘后和的方法。那课程类中对于成绩的处理也会有与学生类相似的地方,但又不调用学生类的方法,这样的话也算是勉强用到了迪米特法则吧,毕竟课程类中一定得用到成绩类但不一定得用学生类。
在这数据处理的过程当中,是对各种基础语句特别是判断语句的进一步熟悉的过程,再者就是各种java自带的方法,这个除了书上基本的常用的方法如ArrayList类,String类等方法便是自己上网搜的诸如正则的具体的那些表达式,一些特殊的计算技巧等了,这个就是仁者见仁智者见智了。最后到输出数据,在输出数据时,我们的数据都是存储在一个个对象的属性中的,而在题目集八的这道题中,最后输出的数据需要将其按或成绩大小或学号大小进行升序排序,那么就需要Comparable接口按类中属性进行判断后在数组中改变数据的位置。进行完这步之后再来根据题目要求按特定的格式输出数据,pta上做到如今的题目集基本上都是这么个路数。
关于此系列之后迭代的题目:
第一次迭代:添加了实验的课程性质与考核方式,添加了对其的课程信息与成绩信息的限制。说白了就是在数据输入上增加了类型,在数据处理上增加了限制,对于先前代码的改动并不算大。
第二次迭代:这次迭代便算是改得大了些,先是对数据处理也就是成绩的计算方式进行了由固定比例计算到靠用户给的比例计算的区别,许多方法都得重写。再者就是将原本继承的关系变成了组合的关系,这下代码长度可就得长上不少了,好像还有代码长度限制,有些难受。既然有了新的数据输入,那新的输入限制必然是少不了的,这大概就是迭代的魅力吧。
不过话说回来,我始终是没能在一次成绩题中满分的,没能领略完整其魅力,有些遗憾。
再来到关键字数量计算的题目:
编写程序统计一个输入的Java源码中关键字(区分大小写)出现的次数。说明如下:
- Java中共有53个关键字(自行百度)
- 从键盘输入一段源码,统计这段源码中出现的关键字的数量
- 注释中出现的关键字不用统计
- 字符串中出现的关键字不用统计
- 统计出的关键字及数量按照关键字升序进行排序输出
- 未输入源码则认为输入非法
输入格式:
输入Java源码字符串,可以一行或多行,以exit
行作为结束标志
输出格式:
- 当未输入源码时,程序输出
Wrong Format
- 当没有统计数据时,输出为空
- 当有统计数据时,关键字按照升序排列,每行输出一个关键字及数量,格式为
数量\t关键字
我的代码:
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> keyWords = new HashMap<>();
Set<String> information = new HashSet<>();
String[] keyWord = {"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof", "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while"};
Scanner input = new Scanner(System.in);
String line = input.nextLine();//创建基本对象
StringBuilder line1 = new StringBuilder();//用于收集除exit所有行
while (!line.equals("exit")) {
line1.append(line.replaceAll("//.*", " ").replaceAll("\".*\"", " "));
line = input.nextLine();
}//每行输入除去前注释负号和双引号内内容
line = line1.toString();
if (line.length() == 0) {
System.out.println("Wrong Format");
return;
}//若无输入则输出Wrong Format
line = sort("\"(.*?)\"", line);
line = sort("/\\**(.*?)/", line);
line = line.replace("[", " ");
line = line.replace("]", " ");
line = line.replace("*", "a");
line = line.replace("/", "a");
line = line.replace("=", "a");
line = line.replace("!", "a");
line = line.replace(":", "a");
line = line.replace("\\", "a");
line = line.replaceAll("[^a-zA-Z]", " ");//除去各种无关符号
for (int i = 0; i < 53; i++) {
Pattern pattern = Pattern.compile("\\b" + keyWord[i] + "\\b");
Matcher matcher = pattern.matcher(line);
while (matcher.find())
if (information.contains(keyWord[i]))
keyWords.replace(keyWord[i], keyWords.get(keyWord[i]) + 1);
else {
keyWords.put(keyWord[i], 1);
information.add(keyWord[i]);
}
}//利用set和treeset对其内容进行判断并收集
Set set = keyWords.keySet();
Object[] arr = set.toArray();
Arrays.sort(arr);
for (Object i : arr)
System.out.println(keyWords.get(i) + "\t" + i);//排序并输出
}
public static String sort(String pattern, String line) {
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(line);
while (m.find()) {
line = line.replace(m.group(), " ");
m = p.matcher(line);
}
return line;
}//sort类用于彻底除去两边注释符号和双引号
}
这题就不放SourceMonitor的生成报表内容以及PowerDesigner的相应类图了,也不长,不太必要感觉。
关于此题的分析:
这题被要求了要用HashMap类与HashSet类做,那毋庸置疑是用来让我们熟悉这两个类的用法的题了。由于这两个类能够快速查找存储的数据的特性,HashMap类适合用来存储存在何种关键字及关键字个数,HashSet类适合用于判断存在的关键字是否已被存储(好吧其实是我想不出有HashMap类存在的前提下HashSet类还能用来干嘛了)。然后就是老样子,搭好数据输入,数据处理,数据输出的框架,此外比较特别的还有这道题用到了大量的正则表达式,甚至专门建了个字符串组来存储关键词。另外就是其中关键词存在的位置是否能被视作关键词这点有些疑问,所以网上的标准答案就被我拿来“借鉴”了下,结果一开始还以为答案有问题,在pta上一试嚯满分,还好这次作业看的是最后一次提交的代码,不然得有抄袭的风险。
主要说最后一题吧:
错误源码:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ArrayList<PersonOverride> person1 = new ArrayList<>(), person2 = new ArrayList<>();
String n1 = input.nextLine(), n2 = input.nextLine(), line;
String[] inforamtion;
for(int i = 0; i < Integer.valueOf(n1); i ++){
PersonOverride personOverride = new PersonOverride();
person1.add(personOverride);
}
for(int i = 0; i < Integer.valueOf(n2); i ++){
boolean flag = true;
line = input.nextLine();
inforamtion = line.split(" ");
PersonOverride personOverride = new PersonOverride(inforamtion[0], Integer.valueOf(inforamtion[1]), Boolean.valueOf(inforamtion[2]));
if(new PersonOverride().equals(personOverride)) {
continue;
}
for(PersonOverride s : person2){
if(s.equals(personOverride)){
flag = false;
break;
}
}
if(flag)
person2.add(personOverride);
}
for(int i = 0; i < Integer.valueOf(n1); i ++){
System.out.println(person1.get(i).toString());
}
person2.forEach((e) ->{
System.out.println(e.toString());
});
System.out.println(person2.size());
System.out.println(Arrays.toString(PersonOverride.class.getConstructors()));
}
}
class PersonOverride {
private String name;
private int age;
private boolean gender;
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isGender() {
return gender;
}
public PersonOverride(String name, int age, boolean gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public PersonOverride() {
this("default", 1, true);
}
@Override
public String toString(){
return this.name + "-" + this.age + "-" + this.gender;
}
public boolean equals(PersonOverride personOverride){
if(this.name.equals(personOverride.getName()) && this.age == personOverride.getAge() && this.gender == personOverride.isGender())
return true;
return false;
}
}