C, PHP, VB, .NET

Дневникът на Филип Петров


* Задача от контролно 1, вариант 1, 22 ноември 2014 г.

Публикувано на 22 ноември 2014 в раздел ПИК3 Java.

Това е набързо написано (като за контролно :P) примерно решение на задачата от днешната контролна работа. Вероятно може много неща по него да се изгладят. Не е тествано въобще с реални данни - може да не е съвсем коректно. Моля ако някой има време, да го изпробва и да каже ако и къде има проблеми. Изтеглете сорс кода.

Задача 1. Създайте клас за фотоалбум (PhotoAlbum) с член променливи „брой страници“ (pagesCount – тип int) и списък от снимки (масив photos от тип FileInputStream). Максималният брой на снимките в един албум не трябва да превишава pagesCount*3 – това трябва да са границите на масива. Погрижете се новосъздаден фотоалбум да има минимум 10 страници. Освен конструктор с подадени параметри, трябва да създадете и конструктор по подразбиране, в който се създава нов празен албум с 16 страници.

Решение:

import java.io.*;

class PhotoAlbum{
  private int pagesCount;
  FileInputStream[] photos;
  
  public PhotoAlbum(){
    this.pagesCount = 16;
    this.photos = new FileInputStream[this.pagesCount*3];
  }
  
  public PhotoAlbum(int pagesCount, FileInputStream[] photos) throws Exception{
    if(photos.length > pagesCount*3) throw new Exception("Too many photos");
    this.setPagesCount(pagesCount);
    this.photos = new FileInputStream[this.pagesCount*3];
    for(int i=0; i<photos.length; i++){
      this.photos[i] = photos[i];
    }
  }
  
  public int getPagesCount(){
    return this.pagesCount;
  }
  
  public void setPagesCount(int pagesCount) throws Exception{
    if(pagesCount<10) throw new Exception("Not enough pages for album");
    else this.pagesCount = pagesCount;
  }
}

Задача 2. В клас PhotoAlbum добавете следните методи:

a) static boolean equalPhotos(FileInputStream photo1, FileInputStream photo2) – методът трябва да сравни двата файла байт по байт и да върне true ако двете подадени снимки са с еднакво съдържание или false ако са различни;

Решение:

  static boolean equalPhotos(FileInputStream photo1, FileInputStream photo2)
                 throws IOException{
    if(photo1.equals(photo2)) return true;
    BufferedInputStream input1 = new BufferedInputStream(photo1);
    BufferedInputStream input2 = new BufferedInputStream(photo2);
    int ch1=-1, ch2=-1;
    while ((ch1 = input1.read())!=-1){
      ch2 = input2.read();
      if (ch1 != ch2){
         try{
            if(input1 != null) input1.close();
            if(input2 != null) input2.close();
         }
         catch(IOException e){}
         return false;
      }
    }
    try{
       if(input1 != null) input1.close();
       if(input2 != null) input2.close();
    }
    catch(IOException e){}
    return true;
  }

b) FileInputStream[] getDuplicates() – намира снимките, които имат дубликати и връща масив с указатели към тях;

Решение:

  FileInputStream[] getDuplicates() throws IOException{
    LinkedList<FileInputStream> duplicates = new LinkedList<FileInputStream>();
    for (int i=0; i<this.photos.length-1; i++){
      for (int j=i+1; j<photos.length; j++){
        if (this.equalPhotos(this.photos[i], this.photos[j])){
          duplicates.add(this.photos[i]);
          if(!duplicates.contains(this.photos[j])) duplicates.add(this.photos[j]);
        }
      }
    }
    return duplicates.toArray(new FileInputStream[duplicates.size()]);
  }

c) void addNewPhoto(FileInputStream newphoto) – методът добавя нова снимка в масива photos на следния принцип:
a. ако в албума има дублиращи се снимки, добавя новата на мястото на дублирана
b. ако няма дублиращи се снимки и има място в масива, добавя в края на масива
c. ако няма дублиращи се снимки и няма място в масива, хвърля Exception

Решение: // Като производителност е ужасно неефективен, но е един от най-бързите варианти за написване с оглед постигнатото дотук

  void addNewPhoto(FileInputStream newphoto) throws IOException, Exception{
    FileInputStream[] duplicates = this.getDuplicates();
    if(duplicates.length>0){
      int position = 0;
      for(int i=0; i<this.photos.length; i++){
        if(photos[i].equals(duplicates[0])){
          position =i;
          break;
        }
      }
      this.photos[position] = newphoto;
    }
    else{
      for(int i=0; i<this.photos.length; i++){
        if(this.photos[i] == null){
          this.photos[i] = newphoto;
          return;
        }
      }
      throw new Exception("Album is full");
    }
  }

Задача 3. Напишете клас BigPhotoAlbum, който наследява PhotoAlbum и добавя изискването броя на страниците на албума да е минимум 64.

Решение:

class BigPhotoAlbum extends PhotoAlbum{
  
  public BigPhotoAlbum() throws Exception{
      super(64, new FileInputStream[0]);
  }
  
  public BigPhotoAlbum(int pagesCount, FileInputStream[] photos) throws Exception{
    super(pagesCount, photos);
    if(pagesCount<64) throw new Exception("Not enough pages for a big album");
  }
  
  public void setPagesCount(int pagesCount) throws Exception{
    if(pagesCount<64) throw new Exception("Not enough pages for a big album");
    else super.setPagesCount(pagesCount);
  }   
}

Задача 4. Напишете клас с main метод, в който извършете следните действия:
a) Използвайки полиморфизъм създайте масив от 3 елемента, в който добавете два PhotoAlbum и един BigPhotoAlbum;

Решение:

    PhotoAlbum[] list = new PhotoAlbum[3];
    list[0] = new PhotoAlbum();
    try{ list[1] = new BigPhotoAlbum(); } catch(Exception e){}
    list[2] = new PhotoAlbum();

b) Потърсете дублиращите се снимки във всеки от трите фотоалбума поотделно;

Решение:

    FileInputStream[] duplicates1=null, 
      duplicates2=null, duplicates3=null; 
    try{
      duplicates1 = list[0].getDuplicates();
      duplicates2 = list[1].getDuplicates();
      duplicates3 = list[2].getDuplicates();
    }
    catch(IOException e){
      System.out.println(e.getMessage());
    }

c) Намерете общите дубликати на снимки измежду трите списъка намерени в b). Казано по друг начин – направете масив с тези снимки, които присъстват едновременно в трите албума.

    LinkedList<FileInputStream> dups = new LinkedList<FileInputStream>();
    for(int i=0; i<duplicates1.length; i++){
      for(int j=0; j<duplicates2.length; j++){
        for(int k=0; k<duplicates3.length; k++){
          try{
            if(PhotoAlbum.equalPhotos(duplicates1[i], duplicates2[j])
                 &&
               PhotoAlbum.equalPhotos(duplicates2[j], duplicates3[k])){
              dups.add(duplicates1[i]);
              if(!dups.contains(duplicates2[j])) dups.add(duplicates2[j]);
              if(!dups.contains(duplicates3[k])) dups.add(duplicates3[k]);
            }
          }
          catch(IOException e){
            System.out.println(e.getMessage());
          }
        }
      }
    }
    FileInputStream[] DuplicatesInAll = 
      dups.toArray(new FileInputStream[dups.size()]);

 



2 коментара


  1. Викам set метода на супер класа, защото нямам достъп до private променливата. Сигурно може да се напише по-елегантно.
    Колкото до "по-приличен" set метод в супер класа... засега не ми идват идеи, които са различни от това да правя в него проверки, които се отнасят за дъщерния клас... А от гледна точка на капсулацията не е добре един клас да се грижи за валидация на данни за негови наследници. Ами ако добавим още един наследник? И още един? Ще трябва все да пренаписваме код в базовия клас. Не ми се струва като добра практика.

    Ето още едно нещо, което ме издразни докато пишех решението - конструктора на BigPhotoAlbum() е по подразбиране, а ми се наложи да хвърля Exception. Освен да направя private конструктор и статичен init метод, друго не ми дойде на ум като решение... Но реших да не утежнявам задачата допълнително.

  2. Здравейте!

    Кому е необходимо да override - ваме сетъра ? Правим проверка и ако е >= 64 викаме метода на суперкласа в който проверяваме пак дали е < 10 ?! Та ние вече сме сигурни, че това условие е изпълнено... Не е ли по-подходящо да се напише по-приличен сетър в super - класа ?

    public void setPagesCount(int pagesCount) throws Exception{
    if(pagesCount<64) throw new Exception("Not enough pages for a big album");
    else super.setPagesCount(pagesCount);
    }
    }

Добави коментар

Адресът на електронната поща няма да се публикува


*