Prośba o pomoc w poprawieniu kodu

0

Treść zadania:
Mamy półki. Każda półka ma swoją nazwę i rozmiar (liczbę książek, które może pomieścić)
Mamy książki. Opis książki to: autor, tytuł.
Inicjalnie każda książka jest poza jakąkolwiek półką.
Można ją wstawić na wybraną półkę, albo zdjąć z półki, na której się znajduje.

Stworzyć klasy Book i Bookshelf, opisujące książki i półki w taki sposób, aby następujący program:

public class TestBook {

  
  public static void main(String[] args) {
    Book b1 = new Book("A", "bbb");
    Book b2 = new Book("B", "ccc");
    Book b3 = new Book("C", "ddd");
    
    Bookshelf bs1 = new Bookshelf("P1", 10);
    Bookshelf bs2 = new Bookshelf("P2", 2);
    
    try {
      bs1.insert(b1);
      bs1.insert(b2);
      bs1.insert(b3);
      
      System.out.println(bs1);
      for (Book b : bs1.getBooks()) System.out.println(b);
      
      bs2.insert(b1);
    } catch (Exception exc) {
        System.out.println(exc.getMessage());      
    }
    
    try {
      for (Book b : bs1.getBooks()) bs1.remove(b);
      bs2.insert(b1);
      bs2.insert(b2);
      
      System.out.println(bs2);
      for (Book b : bs2.getBooks()) System.out.println(b);
      
      bs2.insert(b3);
    } catch (Exception exc) {
        System.out.println(exc.getMessage());      
    }
    
    try {
      bs2.remove(b3);
    } catch (Exception exc) {
        System.out.println(exc.getMessage());      
    }
  }

} 

wyprowadził następujące wyniki:

Półka P1
A bbb
B ccc
C ddd
Nie mogę wstawić książki na półkę (Półka P2) - jest już na półce: Półka P1
Półka P2
A bbb
B ccc
Nie mogę wstawić książki na półkę (Półka P2) - brak miejsca
Nie mogę zdjąć książki z półki (Półka P2) - nie jest na tej półce 

Mój kod:

import java.util.ArrayList;

public class TestBook {

  
  public static void main(String[] args) {
    Book b1 = new Book("A", "bbb");
    Book b2 = new Book("B", "ccc");
    Book b3 = new Book("C", "ddd");
    
    Bookshelf bs1 = new Bookshelf("P1", 10);
    Bookshelf bs2 = new Bookshelf("P2", 2);
    
    try {
      bs1.insert(b1);
      bs1.insert(b2);
      bs1.insert(b3);
      
      System.out.println(bs1);
      for (Book b : bs1.getBooks()) System.out.println(b);
      
      bs2.insert(b1);
    } catch (Exception exc) {
        System.out.println(exc.getMessage());      
    }
    
    try {
      for (Book b : bs1.getBooks()) bs1.remove(b);
      bs2.insert(b1);
      bs2.insert(b2);
      
      System.out.println(bs2);
      for (Book b : bs2.getBooks()) System.out.println(b);
      
      bs2.insert(b3);
    } catch (Exception exc) {
        System.out.println(exc.getMessage());      
    }
    
    try {
      bs2.remove(b3);
    } catch (Exception exc) {
        System.out.println(exc.getMessage());      
    }
  }

}


class Book {
 
    private String autor, tytul;
    public String polka = null; // Inicjalnie każda książka jest poza jakąkolwiek półką.
 
  public Book(String a, String t){
 	autor = a;
    tytul = t;
    }
    
  public String toString(){
    String daneKsiazki=(autor+" "+tytul);
    return daneKsiazki;
    } 
}
    
class Bookshelf { 
     
	private String nazwaPolki;
    private int iloscMiejsca;
    
    ArrayList<Book> Books = new ArrayList<Book>();
    
    Bookshelf(String n, int ilosc){
        nazwaPolki = n;
        iloscMiejsca = ilosc;
    }
    
    public ArrayList<Book> getBooks(){
        return Books;
    }
    
    public void insert(Book b) throws Exception{
    	
     if(b.polka != null){
        throw new Exception("Nie moge wstawic ksiazki na polke (Polka" + nazwaPolki + ") - jest już na polce: " + b.polka);
       }
     else {
          if(Books.size()>=iloscMiejsca){
      	  throw new Exception("Nie moge wstawic ksiazki na polke (Polka " + nazwaPolki + ") - brak miejsca");
          }
          Books.add(b);
        }
    }
 
 public void remove(Book b) throws Exception{
        boolean mozna = Books.remove(b);
        
        if(mozna==true){b.polka=null;}
        else{
        	 throw new Exception("Nie moge zdjac ksiazki z polki (Polka " + nazwaPolki + ") - nie jest na tej polce");
        }
    }
 
    public String toString(){
        return "Polka " + nazwaPolki;
    } 
} 

Wynik mojego programu:

Półka P1
A bbb
B ccc
C ddd
null
Nie mogę zdjąć książki z półki (Półka P2) - nie jest na tej półce 

Mam takie pytanie: dlaczego w wyniku programu pojawia się null i nie ma drugiej półki (P2)?
Przyznam, że korzystałam ze wskazówek na tym forum, m.in. by skorzystać tutaj z ArrayList.

Widziałam też, że polecano użycie Iteratora i metody hasNext(), ale czy bez tego zadanie też może być wykonane poprawnie? Czy lepiej byłoby go użyć?

0

Nie rozumiem dlaczego napisałaś klasę TestBook, jej nie możesz zmieniać.
Pole polka w klasie Book powinno być typu Bookshelf, a nie String.
Wywołania typu

bs2.insert(b1);

muszą zmienić wartość pola polka w obiekcie b1.

0

Racja, mogłam wstawić same klasy Book i Bookshelf, po prostu wkleiłam cały kod. Mój błąd.

Zmieniłam już pole polka na tym Bookshelf.
Zmieniłam też na obiekt b1, jednak nie bardzo rozumiem dlaczego muszę podać numer... wiem, że tak jest w klasie TestBook, ale jest też:

       bs2.insert(b3);

Poza tym po zmianie wciąż wynik programu jest taki sam jak pisałam wyżej. Co może być tego powodem?

1

Nie zrozumiałaś ostatniej uwagi, zmień metodę insert

    public void insert(Book b) throws Exception
    { 
        if(b.polka != null)
        {
            throw new Exception("Nie moge wstawic ksiazki na polke (Polka" + nazwaPolki + ") - jest już na polce: " + b.polka);
        }
        else 
        {
            if(Books.size()>=iloscMiejsca)
            {
                throw new Exception("Nie moge wstawic ksiazki na polke (Polka " + nazwaPolki + ") - brak miejsca");
            }
            Books.add(b);
            b.polka = this; //tego brakowało
        }
    }
0

Poprawione.
Teraz program daje taki wynik:

Półka P1
A bbb
B ccc
C ddd
Nie mogę wstawić książki na półkę (Półka P2) - jest już na półce: Półka P1
null
Nie mogę zdjąć książki z półki (Półka P2) - nie jest na tej półce 
1

Zmień dwie metody w klasie Bookshelf.

    public ArrayList<Book> getBooks()
    {
        ArrayList<Book> result = new ArrayList<Book>();
        for(Book b:Books)
        {
            if(b != null)
            {
                result.add(b);
            }
        }
        return result;
    }
    public void remove(Book book) throws Exception
    {
        boolean mozna = false;
        for(int i=0;i<Books.size();i++)
        {
            Book b = Books.get(i);
            if(book == b)
            {
                mozna = true;
                Books.set(i,null);
                break;                
            }
        }
 
        if(mozna)
        {
            book.polka = null;
        }
        else
        {
            throw new Exception("Nie moge zdjac ksiazki z polki (Polka " + nazwaPolki + ") - nie jest na tej polce");
        }
    }
1

Po zmianach z powyższego postu kod działa zgodnie z wymaganiami. Tym niemniej kod klasy jest błędny - źle sprawdza czy na półce jest miejsce na kolejną książkę.

import java.util.*;
class Bookshelf 
{  
    private String nazwaPolki;
    private int iloscMiejsca;
    private int ileWolne;
    private ArrayList<Book> books = new ArrayList<Book>();
 
    Bookshelf(String n, int ilosc)
    {
        nazwaPolki = n;
        iloscMiejsca = ilosc;
        ileWolne = ilosc;
    }
 
    public ArrayList<Book> getBooks()
    {
        ArrayList<Book> result = new ArrayList<Book>();
        for(Book b:books)
        {
            if(b != null)
            {
                result.add(b);
            }
        }
        return result;
    }
 
    public void insert(Book b) throws Exception
    { 
        if(b.polka != null)
        {
            throw new Exception("Nie moge wstawic ksiazki na polke (Polka" + nazwaPolki + ") - jest juz na polce: " + b.polka);
        }
        else 
        {
            if(ileWolne<=0)
            {
                throw new Exception("Nie moge wstawic ksiazki na polke (Polka " + nazwaPolki + ") - brak miejsca");
            }
            boolean jestNull = false;
            for(int i=0;i<books.size();i++)
            {
                if(books.get(i) == null)
                {
                    books.set(i,b);
                    jestNull = true;
                    break;
                }
            }
            if(!jestNull)
            {
                books.add(b);
            }
            b.polka = this;
            ileWolne--;
        }
    }
 
    public void remove(Book book) throws Exception
    {
        boolean mozna = false;
        for(int i=0;i<books.size();i++)
        {
            Book b = books.get(i);
            if(book == b)
            {
                mozna = true;
                books.set(i,null);
                ileWolne++;
                break;                
            }
        }
        //boolean mozna = Books.remove(b);
 
        if(mozna)
        {
            book.polka = null;
        }
        else
        {
            throw new Exception("Nie moge zdjac ksiazki z polki (Polka " + nazwaPolki + ") - nie jest na tej polce");
        }
    }
 
    public String toString()
    {
        return "Polka " + nazwaPolki;
    } 
}
0

Bardzo dziękuję za pomoc :) i za to, że sprawdziłeś jeszcze kod, bo gdy w nocy zobaczyłam, że wynik jest poprawny nie pomyślałam, że może jednak są jeszcze błędy.

Mam jeszcze parę pytań dotyczących już samego kodu i wyjaśnienia jego działania. Często jest tak, że rozumiem wskazówki innych osób, wiem gdzie sama popełniłam błąd, ale nie umiem wyjaśnić ponazywać pewnych kroków w programie.

  public ArrayList<Book> getBooks()
    {
        ArrayList<Book> result = new ArrayList<Book>();
        for(Book b:books)
        {
            if(b != null)
            {
                result.add(b);
            }
        }
        return result;
    }

Jak opisać pętlę for jeśli nie składa się z 3 elementów, tzn. deklaracji zmiennych, warunku pętli i instrukcji?
Ja to rozumiem tak, że mamy metodę dodawania książek do listy (jak określić czym jest lista 'result' względem tej 'ArrayList<Book> Books = new ArrayList<Book>();'?)

         boolean jestNull = false;

Chciałabym zamiast 'jestNull' wpisać coś innego, ale nie jestem pewna do czego się to odnosi. Czy do tego, że dana książka nie jest na żadnej półce, czy do tego, że półka nie jest pusta?

            b.polka = this; 

i mam z tym problem. Ogólnie ominęłam to wcześniej, bo nie bardzo rozumiem używanie this. Czytałam o tym, ale przykłady są różne (i z tego co widziałam to wiele zastosowań this) a ja dalej nie umiem opisać tego w miarę zrozumiale i na swój sposób co właściwie się wtedy dzieje.

Przeprasza za może takie podstawowe pytania, ale wcześniej pisałam programy na wyczucie i jak działały to było dobrze. Wiem, że to nie było zbyt mądre i teraz chcę zrozumieć w pełni kod i umieć po kolei powiedzieć co się w nim dzieje.

1
  1. Taka postać pętli for:
for(Book b:books){

jest, krótszym zapisem tradycyjnej pętli

for(int i=0;i<books.size();i++){
    Book b = books.get(i);
  1. Wymagania zadania wymusiły dość nietypowy sposób usuwania książki b z kolekcji books, zamiast naturalnego
books.remove(b)

jest szukanie książki b w kolekcji books i, jeśli książka zostanie znaleziona, zastępowanie książki b nullem. Skutek jest taki, że kolekcja books zawiera nulle. Metoda getBooks() tworzy zmienną lokalną result, do której przepisuje tylko "prawdziwe" książki (pomija nulle) i tylko te książki zwraca.
3. Zmienna

boolean jestNull = false;

zawiera informację czy w kolekcji books jest gdzieś zawarty null (jako wynik uprzedniego usuwania). Jeśli tak jest, to w metodzie insert zamiast dodawać kolejny element do kolekcji books, zastępujemy ten null "prawdziwą" książką.
4. this w ciele metody insert oznacza ten obiekt, na rzecz, którego metoda została wywołana. Po wywołaniu

bs.insert(book);

kod (w ciele metody insert):

book.polka = this;

oznacza

book.polka = bs;

Drugiej formy nie można użyć, bo zmienna bs jest wewnątrz metody insert nieznana.

0

Dziękuję za wyjaśnienie tego skróconego zapisu for i używania this :)

bogdans napisał(a):
  1. Wymagania zadania wymusiły dość nietypowy sposób usuwania książki b z kolekcji books, zamiast naturalnego
books.remove(b)

jest szukanie książki b w kolekcji books i, jeśli książka zostanie znaleziona, zastępowanie książki b nullem. Skutek jest taki, że kolekcja books zawiera nulle. Metoda getBooks() tworzy zmienną lokalną result, do której przepisuje tylko "prawdziwe" książki (pomija nulle) i tylko te książki zwraca.
3. Zmienna

boolean jestNull = false;

zawiera informację czy w kolekcji books jest gdzieś zawarty null (jako wynik uprzedniego usuwania). Jeśli tak jest, to w metodzie insert zamiast dodawać kolejny element do kolekcji books, zastępujemy ten null "prawdziwą" książką.

Czyli jest tak:

          public void remove(Book book) throws Exception{
   boolean mozna = false;
        
        for(int i=0;i<Books.size();i++){
            Book b = Books.get(i);
            if(book == b){
                mozna = true;
                Books.set(i,null);
                ileWolne++;
                break;                
            }
        }
 
        if(mozna){book.polka = null;}

Tutaj pętla for przeszukuje kolekcje i gdy okaże się, że jest tam książka b (na miejscu o indeksie i) to jest ona zamieniana na null, zwiększa się miejsce na półce, pętla for się przerywa i idzie do kolejnego ifa by zaznaczyć, że książka book nie leży na półce, więc jest luzem, stąd null.
Na liscie zostaje element null.

Potem jest metoda insert i:

           boolean jestNull = false;
          
            for(int i=0;i<Books.size();i++){
            	
                if(Books.get(i) == null){
                    Books.set(i,b);
                    jestNull = true;
                    break;
                }
            }
            if(!jestNull){
                Books.add(b);
            }					    
            b.polka = this;		 	 
            ileWolne--;				
        }

Pętla for przeszukuje elementy listy a jak znajdzie element null to zamienia go na książkę b. zmienna jestNull otrzymuje wartość true i opuszczamy pętlę. Natomiast kiedy wykona się drugi if z negacją jestNull?

0

Natomiast kiedy wykona się drugi if z negacją jestNull?

Kiedy w kolekcji books nie ma żadnego nulla, są same "prawdziwe" książki.

0

Dziękuję za pomoc i wyjaśnienia :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1