* Примерна задача 1
Публикувано на 31 октомври 2009 в раздел ПИК3 Java.
1. Дефинирайте клас, описващ дати от календара.
а) Дефинирайте конструктор по подразбиране и такъв с параметри за задаване на дата.
б) Дефинирайте за него подходящите get и set методи.
в) Направете необходимите проверки за валидност на данните (ако не са валидни да се генерира изключение):
calException.java:
package example;
// Клас дефиниращ изключение "невалидна дата"
public class calException extends Exception{
public calException(){
super("Invalid date");
}
public calException(String msg){
super(msg);
}
public String toString(){
return "Invalid date";
}
}
calendar.java:
package example;
public class calendar{
private int day;
private int month;
private int year;
// Конструктор по подразбиране
// данните се четат от клавиатурата
// възможно е s.nextInt() да хвърли InputMismatchException!
public calendar() throws calException, java.util.InputMismatchException{
java.util.Scanner s = new java.util.Scanner(System.in);
System.out.print("Enter day: ");
this.day = s.nextInt();
System.out.print("Enter month: ");
this.month = s.nextInt();
System.out.print("Enter year: ");
this.year = s.nextInt();
if (this.validate(this.day, this.month, this.year)== false){
throw new calException();
}
}
// Конструктор с параметри за създаване на дата
public calendar(int day, int month, int year) throws calException{
if (this.validate(day, month, year) == false) throw new calException();
else{
this.day = day;
this.month = month;
this.year = year;
}
}
// Метод за валидиране на дата (за вътрешно ползване на класа)
private boolean validate(int day, int month, int year){
if (day < 1) return false;
if (month < 1 || month > 12) return false;
switch(month){
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
if(day > 31) return false;
break;
case 4: case 6: case 9: case 11:
if(day > 30) return false;
break;
case 2:
if (year%400==0 || (year%4==0 && year%100!=0)){
if (day > 29) return false;
}
else{
if (day > 28) return false;
}
break;
}
return true;
}
// get методи:
public int getDay(){
return this.day;
}
public int getMonth(){
return this.month;
}
public int getYear(){
return this.year;
}
// set методи:
public void setDay(int day) throws calException{
if (this.validate(day, this.month, this.year)==false) throw new calException();
else this.day = day;
}
public void setMonth(int month) throws calException{
if (this.validate(this.day, month, this.year)==false) throw new calException();
else this.month = month;
}
public void setYear(int year) throws calException{
if (this.validate(this.day, this.month, year)==false) throw new calException();
else this.year = year;
}
}
2. Дефинирайте клас, описващ студент като включите следните данни:
- Име;
- Факултетен номер;
- Дата на раждане – използвайте класа от зад.1;
- Среден успех.
а) Дефинирайте конструктор по подразбиране и с параметри за инициализиране на обекта.
б) Дефинирайте подходящите get и set методи.
в) Дефинирайте метод, който по зададен параметър текуща дата, връща възрастта на студента като брой навършени години.
г) Дефинирайте статичен метод, който сравнява двама студента по успех (връща -1, 0 или 1 в зависимост от това дали първият е с по-висок, равен или по-нисък успех от втория).
student.java:
package example;
public class student{
private String name;
private long fnum;
private calendar birthdate;
private double gpa;
// Конструктор по подразбиране
public student() throws calException, java.util.InputMismatchException{
java.util.Scanner s = new java.util.Scanner(System.in);
System.out.print("Enter name: ");
name = s.nextLine();
System.out.print("Enter fnum: ");
fnum = s.nextLong();
birthdate = new calendar();
System.out.print("Enter GPA: ");
gpa = s.nextDouble();
}
// Конструктор с подадени параметри
public student(String name, int day, int month, int year, long fnum, double gpa)
throws calException{
this.name = name;
this.fnum = fnum;
this.gpa = gpa;
birthdate = new calendar(day, month, year);
}
// Втори конструктор с подадени параметри
public student(String name, long fnum, double gpa, calendar birthdate){
this.name = name;
this.fnum = fnum;
this.gpa = gpa;
this.birthdate = birthdate;
}
// Get методи
public String getName(){
return this.name;
}
public calendar getBirthdate(){
return this.birthdate;
}
public double getGPA(){
return this.gpa;
}
public long getFNum(){
return this.fnum;
}
// Set методи
void setName(String name){
this.name = name;
}
void setFNum(long fnum){
this.fnum = fnum;
}
void setBirthdate(calendar birthdate){
this.birthdate = birthdate;
}
void setGPA(double GPA){
this.gpa = gpa;
}
// Метод връщащ годините на студента спрямо подадена текуща дата
public int showYears(calendar currentDate){
if (currentDate.getMonth() > this.birthdate.getMonth()){
return (currentDate.getYear() - this.birthdate.getYear());
}
else{
if (currentDate.getMonth() < this.birthdate.getMonth()){
return (currentDate.getYear() - this.birthdate.getYear() - 1);
}
else{
if (currentDate.getDay() > this.birthdate.getDay()){
return (currentDate.getYear() - this.birthdate.getYear());
}
else{
return (currentDate.getYear() - this.birthdate.getYear() - 1);
}
}
}
}
// Статичен метод сравняващ успеха на двама студенти
public static int compare(student s1, student s2){
if (s1.getGPA() > s2.getGPA()) return -1;
else{
if (s1.getGPA() > s2.getGPA()) return 1;
else return 0;
}
}
}
3. Дефинирайте клас, описващ студентите от вашия поток, като включите:
- Списък от 100 студенти – използвайте класа от зад. 2 като информация за студентите включени в списъка;
- Поток номер;
- Специалност.
а) Дефинирайте конструктор по подразбиране и с параметри за инициализиране на обекта.
б) Дефинирайте подходящите get и set методи.
в) Дефинирайте метод, който добавя студент в потока. Обръщаме внимание, че факултетния номер на студент би следвало да бъде уникално число. Методът да връща true или false в зависимост дали добавянето е успешно.
г) Дефинирайте метод, който изтрива студент от потока по зададен параметър факултетен номер. Методът връща true или false в зависимост дали е изтрит или не.
д) Дефинирайте метод, който търси има ли студент по зададени като параметър факултетен номер и да връща обект от тип student.
е) Предефенирайте метода от д) така, че да работи и подаден параметър "име на студент" (може да връща повече от един намерен студент).
ж) Дефинирайте метод, който намира студента с максимален успех от потока. Обръщаме внимание, че е възможно е да има повече от един студент с максимален успех.
potok.java:
package example;
public class potok{
private static final int MAXSTUDENTS = 100;
private student[] list;
private int firstFreeSlot;
private int potokN;
private int specN;
// Конструктор по подразбиране
public potok() throws java.util.InputMismatchException{
java.util.Scanner s = new java.util.Scanner(System.in);
System.out.print("Enter group N: ");
this.potokN = s.nextInt();
System.out.print("Enter specialty N: ");
this.specN = s.nextInt();
this.list = new student[MAXSTUDENTS];
this.firstFreeSlot = 0;
}
// Конструктор с подадени параметри
public potok(int potokN, int specN){
this.potokN = potokN;
this.specN = specN;
this.list = new student[MAXSTUDENTS];
this.firstFreeSlot = 0;
}
// Get методи
public int getPotokN(){
return this.potokN;
}
public int getSpecN(){
return this.specN;
}
public student getStudent(int i){
return this.list[i];
}
// Set методи
void setPotokN(int potokN){
this.potokN = potokN;
}
void setSpecN(int specN){
this.specN = specN;
}
// Метод добавящ студент в потока
boolean addStudent(student s){
if (this.firstFreeSlot == this.MAXSTUDENTS){
System.err.println("Max students exceeded "+this.MAXSTUDENTS);
return false;
}
// Търси за вече съществуващ студент
for (int i=0; i < this.firstFreeSlot; i++){
if (s.getFNum() == this.list[i].getFNum()){
System.err.println("Student with fnum "+s.getFNum()+" already exists!");
return false;
}
}
// Добавя студент в първия наличен свободен слот
this.list[this.firstFreeSlot] = s;
this.firstFreeSlot++;
return true;
}
// Метод изтриващ студент от потока
boolean delStudent(long fnum){
for (int i=0; i < this.firstFreeSlot; i++){
if (fnum == this.list[i].getFNum()){
if (i == firstFreeSlot - 1){
this.list[i] = null;
this.firstFreeSlot--;
return true;
}
else{
this.list[i] = this.list[(this.firstFreeSlot-1)];
this.list[(this.firstFreeSlot-1)] = null;
this.firstFreeSlot--;
return true;
}
}
}
return false;
}
// Търсене на студент по факултетен номер
student findStudent(long fnum){
for (int i=0; i < this.firstFreeSlot; i++){
if (fnum == this.list[i].getFNum()){
return this.list[i];
}
}
return null;
}
// Търсене на студент по име (неуникално)
java.util.LinkedList<student> findStudent(String name){
java.util.LinkedList<student> result = new java.util.LinkedList<student>();
for (int i=0; i < this.firstFreeSlot; i++){
if (name.equalsIgnoreCase(this.list[i].getName())){
result.add(this.list[i]);
}
}
return result;
}
// Намира най-добрите студенти в потока
java.util.LinkedList<student> getBestStudents(){
// Ако все още няма ваведени студенти
if (this.firstFreeSlot == 0){
System.err.println("No students in the group");
return null;
}
// Намира най-добрия успех
double maxGPA = this.list[0].getGPA();
int place = 0;
for (int i=1; i < this.firstFreeSlot; i++){
if (this.list[i].getGPA() > maxGPA){
maxGPA = this.list[i].getGPA();
place = i;
}
}
// Натрупва в списък най-добрите студенти
java.util.LinkedList<student> result = new java.util.LinkedList<student>();
for (int i=place; i < this.firstFreeSlot; i++){
if (this.list[i].getGPA() == maxGPA){
result.add(this.list[i]);
}
}
return result;
}
}
4. Дефинирайте метод, който определя среден успех на потока и връща клас, съдържащ номер на потока, специалност и среден успех.
potokstats.java:
package example;
public class potokstats{
private int potokN;
private int specN;
private double srusp;
public potokstats(int potokN, int specN, double srusp){
this.potokN = potokN;
this.specN = specN;
this.srusp = srusp;
}
public void print(){
System.out.println("Sp | Gr | GPA");
System.out.println(this.specN+" | "+this.potokN+" | "+this.srusp);
}
}
Добавяме в potok.java:
// Намира средния успех на потока
potokstats getSrUsp(){
if(firstFreeSlot == 0){
System.err.println("No students in this group yet");
return null;
}
double srusp = 0;
for (int i=0; i < this.firstFreeSlot; i++){
srusp += this.list[i].getGPA();
}
srusp /= this.firstFreeSlot;
return new potokstats(this.potokN, this.specN, srusp);
}
5. Демонстрирайте функционалността на създадените класове
mainprog.java:
package example;
class mainprog{
public static void main(String[] args){
// Създава поток от студенти
potok p = new potok(1, 1);
// Добавя 10 студента
for (int i=0; i<3; i++){
student s = null;
try{
s = new student();
}
catch(java.util.InputMismatchException e){
System.err.println("Invalid input data!");
i--;
}
catch (calException e){
System.err.println(e.getMessage());
}
finally{
try{
while(System.in.available() > 0) System.in.skip(System.in.available());
}
catch(java.io.IOException e){}
}
if(s!=null) p.addStudent(s);
}
// Изтрива студент с фак.номер 1212
if (p.delStudent(1212)) System.out.println("Successfully deleted student 1212");
else System.out.println("Student 1212 not found and cannot be deleted");
// Намира студент с фак.номер 1313 и показва името му и годините му
System.out.print("Student with fnum 1313 is: ");
student s1313 = p.findStudent(1313);
if (s1313 != null){
try{
calendar curcal = new calendar(30,10,2009);
System.out.println(s1313.getName()+" who is "+s1313.showYears(curcal)+" years old");
}
catch (calException e){
System.out.println("Bad calendar");
}
}
else{
System.out.println("Student 1313 not found and cannot be printed");
}
// Сравнява оценките на студент 1313 и 1414:
System.out.println("Compare s1313 and s1414: ");
student s1414 = p.findStudent(1414);
if(s1313!=null && s1414!=null){
int c = student.compare(s1313, s1414);
if(c < 0) System.out.println("s1313 is better");
else if(c > 0) System.out.println("s1414 is better");
else System.out.println("s1313 and s1414 are equal");
}
else System.out.println("cannot compare because one or both do not exists");
// Търсим студентите с име Peter и им отпечатва факултетните номера и оценките
System.out.println("The student(s) with name Peter are:");
java.util.LinkedList<student> peterStudents = p.findStudent("Peter");
if (peterStudents != null){
for (int i=0; i<peterStudents.size(); i++){
System.out.print(peterStudents.get(i).getFNum()+" "+peterStudents.get(i).getGPA());
System.out.println();
}
}
// Намира най-добрите студенти в потока
System.out.println("Best students are:");
java.util.LinkedList<student> bestStudents = p.getBestStudents();
if (bestStudents != null){
for (int i=0; i<bestStudents.size(); i++){
System.out.print(bestStudents.get(i).getFNum()+" "+bestStudents.get(i).getName());
System.out.print(" "+bestStudents.get(i).getGPA());
System.out.println();
}
}
// Среден успех на потока
potokstats ps = p.getSrUsp();
System.out.println("Statistics for the group:");
ps.print();
}
}
Имам едно въпростче по отношение на "Метод изтриващ студент от потока". Не мога да разбера действието на "if (i == firstFreeSlot - 1)". Благодаря предварително.
Това е проверка "ако е последен в списъка" (тогава просто го "изтриваме"). В противен случай преместваме последния на негово място и изтриваме последния.