* Примерна задача 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)". Благодаря предварително.
Това е проверка "ако е последен в списъка" (тогава просто го "изтриваме"). В противен случай преместваме последния на негово място и изтриваме последния.